Prev Next

Chapitre 2. Objectifs de PHPUnit

Arrivé à ce point, nous n'avons que deux tests pour le array de PHP et la fonction count(). Quand nous commencerons à tester les nombreuses fonctions array_*() que PHP offre, nous devrons écrire un test pour chacune d'elles. Nous pourrions écrire l'infrastructure pour tous ces tests à partir de zéro. Cependant, il est bien mieux d'écrire une infrastructure de tests une fois pour toute puis de n'écrire ensuite que les parties spécifiques à chaque test. PHPUnit est ce type d'infrastructure.

Un framework comme PHPUnit doit résoudre une série de contraintes, certaines d'entre elles semblant toujours contradictoires avec d'autres. Les tests doivent être à la fois :

Faciles à apprendre et à écrire.

S'il est difficile à apprendre comment écrire les tests, les développeurs n'apprendront pas à les écrire.

Facile à écrire.

Si les tests ne sont pas faciles à écrire, les développeurs ne les écriront pas.

Faciles à lire.

Le code de test ne doit pas contenir de surcharge supplémentaire de façon à ce que le test lui-même ne soit pas perdu au milieu du bruit qui l'entoure.

Faciles à exécuter.

Les tests doivent s'exécuter en cliquant simplement sur un bouton et afficher leurs résultats d'un façon claire et non ambiguë.

Rapides à exécuter.

Les tests doivent s'exécuter rapidement afin qu'ils puissent être lancés des centaines ou des milliers de fois par jour.

Indépendants.

Les tests ne doivent pas interagir les uns avec les autres. Si l'ordre dans lequel les tests sont lancés change, les résultats, eux, ne doivent pas être modifiés.

Composables.

Nous devons pouvoir lancer n'importe quel nombre ou combinaison de tests ensembles. C'est un corollaire de l'indépendance.

Il existe deux antagonismes majeurs entre ces contraintes :

Faciles à apprendre à écrire contre faciles à écrire.

Les tests ne nécessitent pas généralement toute la souplesse d'un langage de programmation. De nombreux outils de test fournissent leur propre langage de script qui n'inclut que le minimum nécessaire en matière de fonctionnalité pour écrire des tests. Les tests produits sont faciles à lire et à écrire car ils ne comportent pas de bruit susceptible de vous distraire de leur contenu. Cependant, apprendre encore un autre langage de programmation et une série d'outils de programmation est malcommode et encombre l'esprit.

Indépendants contre rapides à exécuter.

Si vous voulez que les résultats d'un test n'aient pas d'effets sur les résultats d'un autre, chaque test doit créer l'état complet du monde avant de commencer à s'exécuter, puis restaurer l'état initial du monde quand il a fini. Cependant, configurer le monde peut prendre un long moment : par exemple, se connecter à une base de données et l'initialiser dans un état connu en utilisant des données réalistes.

PHPUnit tente de résoudre ces conflits en utilisant PHP comme langage de test. Quelquefois, la pleine puissance de PHP est disproportionnée pour écrire de petits tests d'une ligne, mais en utilisant PHP, nous tirons profit de toute l'expérience et des outils dont disposent déjà les programmeurs. Puisque nous essayons de convaincre des testeurs réticents, limiter les obstacles pour écrire ces premiers tests est particulièrement important.

PHPUnit privilégie plutôt l'indépendance à la rapidité d'exécution. Les tests indépendants sont précieux car ils fournissent des retours de grande qualité. Vous n'obtenez pas un rapport avec un tas d'erreurs de test qui sont en fait provoqués par l'échec d'un test au début de la série et qui a laissé le monde en désordre pour les autres tests. Cette orientation en faveur des tests indépendants encourage les conceptions dotées d'un grand nombre d'objets simples. Chaque objet peut être testé rapidement de manière indépendante. Il en résulte de meilleures conceptions et des tests plus rapides.

PHPUnit part du postulat que la plupart des tests réussissent et qu'il n'est pas nécessaire de rendre compte des détails des tests réussis. Quand un test échoue, cela vaut la peine de le signaler et de détailler le problème. La grande majorité des tests doit réussir et aucun commentaire n'est intéressant si ce n'est le nombre de tests exécutés. Dans la pratique, ce postulat est implémenté dans les classes produisant les rapports et pas dans le noyau de PHPUnit. Quand les résultats d'une série de tests sont rapportés, vous voyez combien de tests ont été exécutés mais vous ne verrez les détails que pour ceux qui ont échoué.

Les tests sont supposés être à fine maille, ne testant qu'un seul aspect d'un seul objet. Par conséquent, la première fois qu'un test échoue, l'exécution du test s'interrompt et PHPUnit rapporte le problème. Tester en exécutant de nombreux petits tests est un art. Les tests à fine maille améliore la conception générale du système.

Lorsque vous testez un objet avec PHPUnit, vous ne le faites que via l'interface publique de l'objet. Tester en ne se basant que sur le comportement publiquement visible encourage à affronter et résoudre les problèmes de conception difficiles très tôt, avant que les conséquences d'une mauvaise conception ne puissent infecter de grandes parties du système.

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()
assertJsonFileEqualsJsonFile()
assertJsonStringEqualsJsonFile()
assertJsonStringEqualsJsonString()
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
Sauter des tests en utilisant @requires
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
@author
@backupGlobals
@backupStaticAttributes
@codeCoverageIgnore*
@covers
@coversNothing
@dataProvider
@depends
@expectedException
@expectedExceptionCode
@expectedExceptionMessage
@group
@outputBuffering
@requires
@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