Prev Next

Chapitre 17. PHPUnit et Selenium

Selenium Server

Selenium Server est un outil de test qui vous permet d'écrire des tests automatisés de l'interface utilisateur d'applications web dans n'importe quel langage et menés sur n'importe quel site web HTTP en utilisant n'importe quel navigateur courant. Il réalise des tâches automatisée dans le navigateur en pilotant le processus du navigateur via le système d'exploitation. Les tests Selenium s'exécutent directement dans un navigateur, exactement comme des utilisateurs réels le feraient. Ces tests peuvent être utilisés à la fois comme tests de validation (en exécutant des tests au plus haut niveau sur le système intégré au lieu de simplement tester chaque unité du système indépendamment) et des tests de compatibilité pour les navigateurs (en testant l'application web sur différents systèmes d'exploitation et différents navigateurs).

Le seul scénario géré par PHPUnit_Selenium est celui du serveur Selenium 2.x. Le serveur peut être accédé via l'API classique Selenium RC déjà présente dans la version 1.x ou avec l'API serveur WebDriver (partiellement implémentée) à partir de PHPUnit_Selenium 1.2.

La raison derrière cette décision est que Selenium 2 est rétro compatible et que Selenium RC n'est désormais plus maintenu.

Installation

Premièrement, installer Selenium Server:

  1. Télécharger une archive du Serveur Selenium.
  2. Dézipper l'archive et copier selenium-server-standalone-2.20.0.jar (contrôler le suffixe de version) dans /usr/local/bin, par exemple.
  3. Lancer le serveur Selenium en exécutant java -jar /usr/local/bin/selenium-server-standalone-2.20.0.jar.

Deuxièmement, installer le paquet PHPUnit_Selenium, nécessaire pour accéder nativement au serveur Selenium depuis PHPUnit:

pear install phpunit/PHPUnit_Selenium

Maintenant, nous pouvons envoyer des commandes au serveur Selenium en utilisant son protocole client/serveur.

PHPUnit_Extensions_Selenium2TestCase

Le cas de test PHPUnit_Extensions_Selenium2TestCase vous permet d'utiliser l'API WebDriver (partiellement implémentée).

Exemple 17.1, « Exemple d'utilisation de PHPUnit_Extensions_Selenium2TestCase » montre comment tester le contenu de l'élément <title> du site web http://www.example.com/.

Exemple 17.1. Exemple d'utilisation de PHPUnit_Extensions_Selenium2TestCase

<?php
class WebTest extends PHPUnit_Extensions_Selenium2TestCase
{
protected function setUp()
{
$this->setBrowser('firefox');
$this->setBrowserUrl('http://www.example.com/');
}

public function testTitle()
{
$this->url('http://www.example.com/');
$this->assertEquals('Example WWW Page', $this->title());
}

}
?>
phpunit WebTest
PHPUnit 3.6.0 by Sebastian Bergmann.

F

Time: 28 seconds, Memory: 3.00Mb

There was 1 failure:

1) WebTest::testTitle
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Example WWW Page'
+'IANA — Example domains'

/home/giorgio/WebTest.php:13

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Les commandes de Selenium2TestCare sont implémentées via __call(). Merci de vous référer à the end-to-end test for PHPUnit_Extensions_Selenium2TestCase pour la liste de toutes les fonctionnalités prises en charge.

PHPUnit_Extensions_SeleniumTestCase

L'extension de cas de test PHPUnit_Extensions_SeleniumTestCase implémente le protocole client/serveur pour parler au serveur Selenium ainsi que des méthodes de vérification spécialisées pour le test web.

Exemple 17.2, « Exemple d'utilisation de PHPUnit_Extensions_SeleniumTestCase » montre comment tester le contenu de l'élément <title> du site web http://www.example.com/.

Exemple 17.2. Exemple d'utilisation de PHPUnit_Extensions_SeleniumTestCase

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class WebTest extends PHPUnit_Extensions_SeleniumTestCase
{
protected function setUp()
{
$this->setBrowser('*firefox');
$this->setBrowserUrl('http://www.example.com/');
}

public function testTitle()
{
$this->open('http://www.example.com/');
$this->assertTitle('Example WWW Page');
}
}
?>
phpunit WebTest
PHPUnit 3.6.0 by Sebastian Bergmann.

F

Time: 9 seconds, Memory: 6.00Mb

There was 1 failure:

1) WebTest::testTitle
Current URL: http://www.iana.org/domains/example/

Failed asserting that 'IANA — Example domains' matches PCRE pattern "/Example WWW Page/".


FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Contrairement à la classe PHPUnit_Framework_TestCase, les classes de cas de test qui héritent de PHPUnit_Extensions_SeleniumTestCase doivent fournir une méthode setUp(). Cette méthode est utilisée pour configurer la session du serveur Selenium. Voir Tableau 17.1, « API de Selenium Server: configuration » pour la liste des méthodes qui sont disponibles pour cela.

Tableau 17.1. API de Selenium Server: configuration

Méthode Signification
void setBrowser(string $navigateur) Règle le navigateur que le serveur Selenium Server doit utiliser.
void setBrowserUrl(string $urlNavigateur) Règle l'URL de base pour les tests.
void setHost(string $hote) Règle le nom d'hôte pour la connexion au serveur Selenium Server.
void setPort(int $port) Règle le port pour la connexion au serveur Selenium Server.
void setTimeout(int $delaiExpiration) Règle le délai d'expiration pour la connexion au serveur Selenium Server server.
void setSleep(int $secondes) Règle le nombre de secondes durant lesquelles le client Selenium Server client doit attendre entre l'envoi de commandes au serveur Selenium Server.

PHPUnit peut facultativement faire une capture d'écran quand un test Selenium échoue. Pour activer ceci, réglez $captureScreenshotOnFailure, $screenshotPath et $screenshotUrl dans votre classe de cas de test comme montré dans Exemple 17.3, « Faire une capture d'écran quand un test échoue ».

Exemple 17.3. Faire une capture d'écran quand un test échoue

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class WebTest extends PHPUnit_Extensions_SeleniumTestCase
{
protected $captureScreenshotOnFailure = TRUE;
protected $screenshotPath = '/var/www/localhost/htdocs/screenshots';
protected $screenshotUrl = 'http://localhost/screenshots';

protected function setUp()
{
$this->setBrowser('*firefox');
$this->setBrowserUrl('http://www.example.com/');
}

public function testTitle()
{
$this->open('http://www.example.com/');
$this->assertTitle('Example WWW Page');
}
}
?>
phpunit WebTest
PHPUnit 3.6.0 by Sebastian Bergmann.

F

Time: 7 seconds, Memory: 6.00Mb

There was 1 failure:

1) WebTest::testTitle
Current URL: http://www.iana.org/domains/example/
Screenshot: http://localhost/screenshots/334b080f2364b5f11568ee1c7f6742c9.png

Failed asserting that 'IANA — Example domains' matches PCRE pattern "/Example WWW Page/".


FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Vous pouvez exécuter chaque test en utilisant une série de navigateurs : au lieu d'utiliser setBrowser() pour indiquer un seul navigateur, vous déclarez un tableau public static nommé $browsers dans votre classe de cas de test. Chaque élément de ce tableau décrit la configuration d'un navigateur. Chacun de ces navigateurs peut être hébergé par différents serveurs Selenium Server. Exemple 17.4, « Régler la configuration de multiples navigateurs » montre un exemple.

Exemple 17.4. Régler la configuration de multiples navigateurs

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class WebTest extends PHPUnit_Extensions_SeleniumTestCase
{
public static $browsers = array(
array(
'name' => 'Firefox sur Linux',
'browser' => '*firefox',
'host' => 'ma.box.linux',
'port' => 4444,
'timeout' => 30000,
),
array(
'name' => 'Safari sur MacOS X',
'browser' => '*safari',
'host' => 'ma.box.macosx',
'port' => 4444,
'timeout' => 30000,
),
array(
'name' => 'Safari sur Windows XP',
'browser' => '*custom C:\Program Files\Safari\Safari.exe -url',
'host' => 'ma.box.windowsxp',
'port' => 4444,
'timeout' => 30000,
),
array(
'name' => 'Internet Explorer sur Windows XP',
'browser' => '*iexplore',
'host' => 'ma.box.windowsxp',
'port' => 4444,
'timeout' => 30000,
)
);

protected function setUp()
{
$this->setBrowserUrl('http://www.example.com/');
}

public function testTitle()
{
$this->open('http://www.example.com/');
$this->assertTitle('Example Web Page');
}
}
?>

PHPUnit_Extensions_SeleniumTestCase peut rassembler des informations de couverture de code pour les tests lancés via Selenium:

  1. Copier PHPUnit/Extensions/SeleniumTestCase/phpunit_coverage.php dans le répertoire racine de votre serveur web.
  2. Dans le fichier de configuration du serveur web php.ini, configurez PHPUnit/Extensions/SeleniumTestCase/prepend.php et PHPUnit/Extensions/SeleniumTestCase/append.php respectivement comme auto_prepend_file et auto_append_file.
  3. Dans votre classe de cas de test qui hérite de PHPUnit_Extensions_SeleniumTestCase, utilisez
    protected $coverageScriptUrl = 'http://host/phpunit_coverage.php';
    
    pour configurer l'URL pour le script phpunit_coverage.php.

Tableau 17.2, « Assertions » liste les diverses méthodes de vérification que PHPUnit_Extensions_SeleniumTestCase fournit.

Tableau 17.2. Assertions

Assertion Signification
void assertElementValueEquals(string $localisateur, string $texte) Rapporte une erreur si la valeur de l'élément identifié par $localisateur n'est pas égale au $texte donné.
void assertElementValueNotEquals(string $localisateur, string $texte) Rapporte une erreur si la valeur de l'élément identifié par $localisateur est égale au $texte donné.
void assertElementValueContains(string $localisateur, string $texte) Rapporte une erreur si la valeur de l'élément identifié par $localisateur ne contient pas le $texte donné.
void assertElementValueNotContains(string $localisateur, string $texte) Rapporte une erreur si la valeur de l'élément identifié par $localisateur contient le $texte donné.
void assertElementContainsText(string $localisateur, string $texte) Rapporte une erreur si l'élément identifié par $localisateur ne contient pas le $texte donné.
void assertElementNotContainsText(string $localisateur, string $texte) Rapporte une erreur si l'élément identifié par $localisateur contient le $texte donné.
void assertSelectHasOption(string $localisateurDeSelect, string $option) Rapporte une erreur si l'option de liste déroulante donnée n'est pas disponible.
void assertSelectNotHasOption(string $localisateurDeSelect, string $option) Rapporte une erreur si l'option de liste déroulante donnée est disponible.
void assertSelected($localisateurDeSelect, $option) Rapporte une erreur si l'étiquette de liste déroulante donnée n'est pas sélectionnée.
void assertNotSelected($localisateurDeSelect, $option) Rapporte une erreur si l'étiquette de liste déroulante donnée est sélectionnée.
void assertIsSelected(string $localisateurDeSelect, string $valeur) Rapporte une erreur si la valeur donnée n'est pas sélectionnée dans la liste déroulante.
void assertIsNotSelected(string $localisateurDeSelect, string $valeur) Rapporte une erreur si la valeur donnée est sélectionnée dans la liste déroulante.

Tableau 17.3, « Méthodes canevas » montre la méthode canevas de PHPUnit_Extensions_SeleniumTestCase:

Tableau 17.3. Méthodes canevas

Méthode Signification
void defaultAssertions() Surcharge pour exécuter des assertions qui sont partagées par tous les tests d'un cas de test. Cette méthode est appelée après chaque commande qui est envoyée au serveur Selenium Server.

Merci de vous référer à la documentation des commandes Selenium pour une référence des commandes disponibles et comment elles sont utilisées.

Les commandes de Selenium 1 sont implémentées dynamiquement via __call. Référez-vous également aux documents de l'API pour PHPUnit_Extensions_SeleniumTestCase_Driver::__call() pour une liste de toutes les méthodes gérées du côté PHP, avec les paramètres et le type de retourné quand ils sont disponibles.

En utilisant la méthode runSelenese($filename), vous pouvez également lancer un test Selenium à partir de ses spécifications Selenese/HTML. Plus encore, en utilisant l'attribut statique $seleneseDirectory, vous pouvez créer automatiquement des objets tests à partir d'un répertoire qui contient des fichiers Selenese/HTML. Le répertoire indiqué est parcouru récursivement à la recherche de fichiers .htm qui sont supposés contenir du Selenese/HTML. Exemple 17.5, « Utiliser un répertoire de fichiers Selenese/HTML comme tests » montre un exemple.

Exemple 17.5. Utiliser un répertoire de fichiers Selenese/HTML comme tests

<?php
require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class SeleneseTests extends PHPUnit_Extensions_SeleniumTestCase
{
public static $seleneseDirectory = '/chemin/vers/fichiers';
}
?>

A partir de Selenium 1.1.1, une fonctionnalité expérimentale est incluse permettant à un utilisateur de partager la session entre plusieurs tests. Le seul cas géré est le partage de session entre tous les tests quand un unique navigateur est utilisé. Appelez PHPUnit_Extensions_SeleniumTestCase::shareSession(true) dans votre fichier amorce pour activer le partage de session. La session sera réinitialisée dans le cas où un test échoue (en échec ou incomplet); c'est à la charge de l'utilisateur d'éviter les interactions entre des tests en réinitialisant des cookies ou en se déconnectant de l'application testée (avec une méthode tearDown()).

Prev Next
1. Automatiser les tests
2. Objectifs de PHPUnit
3. Installer PHPUnit
4. Ecrire des tests pour PHPUnit
Dépendances des tests
Fournisseur de données
Tester des exceptions
Tester les erreurs PHP
Tester la sortie écran
Assertions
assertArrayHasKey()
assertClassHasAttribute()
assertClassHasStaticAttribute()
assertContains()
assertContainsOnly()
assertCount()
assertEmpty()
assertEqualXMLStructure()
assertEquals()
assertFalse()
assertFileEquals()
assertFileExists()
assertGreaterThan()
assertGreaterThanOrEqual()
assertInstanceOf()
assertInternalType()
assertLessThan()
assertLessThanOrEqual()
assertNull()
assertObjectHasAttribute()
assertRegExp()
assertStringMatchesFormat()
assertStringMatchesFormatFile()
assertSame()
assertSelectCount()
assertSelectEquals()
assertSelectRegExp()
assertStringEndsWith()
assertStringEqualsFile()
assertStringStartsWith()
assertTag()
assertThat()
assertTrue()
assertXmlFileEqualsXmlFile()
assertXmlStringEqualsXmlFile()
assertXmlStringEqualsXmlString()
5. Le lanceur de tests en ligne de commandes
Options de la ligne de commandes
6. Fixtures
Plus de setUp() que de tearDown()
Variantes
Partager les Fixtures
Etat global
7. Organiser les tests
Composer une suite de tests en utilisant le système de fichiers
Composer une suite de tests en utilisant la configuration XML
8. Tester des bases de données
Systèmes gérés pour tester des bases de données
Difficultés pour tester les bases de données
Les quatre phases d'un test de base de données
1. Nettoyer la base de données
2. Configurer les fixtures
3–5. Exécuter les tests, vérifier les résultats et nettoyer
Configuration d'un cas de test de base de données PHPUnit
Implémenter getConnection()
Implémenter getDataSet()
Qu'en est-il du schéma de base de données (DDL)?
Astuce: utilisez votre propre cas de tests abstrait de base de données
Comprendre DataSets et DataTables
Implémentations disponibles
Attention aux clefs étrangères
Implementer vos propres DataSets/DataTables
L'API de connexion
API d'assertion de base de données
Faire une assertion sur le nombre de lignes d'une table
Faire une assertion sur l'état d'une table
Faire une assertion sur le résultat d'une requête
Faire une assertion sur l'état de plusieurs tables
Foire aux questions
PHPUnit va-t'il (re-)créer le schéma de base de données pour chaque test ?
Suis-je obligé d'utiliser PDO dans mon application pour que l'extension de base de données fonctionne ?
Que puis-je faire quand j'obtiens une erreur « Too much Connections (Trop de connexions) » ?
Comment gérer les valeurs NULL avec les DataSets au format XML à plat / CSV ?
9. Tests incomplets et sautés
Tests incomplets
Sauter des tests
10. Doublure de test
Bouchons
Objets simulacres (Mock Objects)
Bouchon et simulacre pour Web Services
Simuler le système de fichiers
11. Pratiques de test
Pendant le développement
Pendant le débogage
12. Développement dirigé par les tests
Exemple du compte bancaire
13. Développement dirigé par le comportement
Exemple du jeu de Bowling
14. Analyse de couverture de code
Spécifier les méthodes couvertes
Ignorer des blocs de code
Inclure et exclure des fichiers
Cas limites
15. Autres utilisations des tests
Documentation agile
Tests transverses à l'équipe
16. Générateur de squelette
Générer un squelettre de classe de cas de test
Générer un squelette de classe à partir d'une classe de cas de test
17. PHPUnit et Selenium
Selenium Server
Installation
PHPUnit_Extensions_Selenium2TestCase
PHPUnit_Extensions_SeleniumTestCase
18. Journalisation
Résultats de test (XML)
Résultats de test (TAP)
Résultats de test (JSON)
Couverture de code (XML)
Couverture de code (TEXTE)
19. Etendre PHPUnit
Sous-classe PHPUnit_Framework_TestCase
Ecrire des assertions personnalisées
Implémenter PHPUnit_Framework_TestListener
Sous classer PHPUnit_Extensions_TestDecorator
Implémenter PHPUnit_Framework_Test
A. Assertions
B. Annotations
@assert
@author
@backupGlobals
@backupStaticAttributes
@codeCoverageIgnore*
@covers
@dataProvider
@depends
@expectedException
@expectedExceptionCode
@expectedExceptionMessage
@group
@outputBuffering
@runTestsInSeparateProcesses
@runInSeparateProcess
@test
@testdox
@ticket
C. Le fichier de configuration Configuration
PHPUnit
Série de tests
Groupes
Inclure et exclure des fichiers de la couverture de code
Journalisation
Moniteurs de tests
Configurer les réglages de PHP INI, les constantes et les variables globales
Configurer les navigateurs pour Selenium RC
D. Index
Index
E. Bibliographie
F. Copyright