Prev Next

Chapitre 1. Automatiser les tests

Même les bons programmeurs font des erreurs. La différence entre un bon programmeur et un mauvais est que le bon programmeur utilise des tests pour détecter ses erreurs dès que possible. Plus vite vous faites des tests pour trouver une erreur, plus grandes sont vos chances de la trouver et moins la recherche et la correction vous coûteront cher. Ceci explique pourquoi repousser les tests juste avant la livraison d'un logiciel est tellement problématique. La plupart des erreurs ne seront pas trouvées du tout et le coût pour corriger celles qui auront été trouvées sera tel que vous devrez faire des choix car vous ne pourrez pas les corriger toutes.

Tester avec PHPUnit n'est pas une activité totalement différente de ce vous faites probablement déjà. C'est juste une façon différente de la réaliser. La différence se situe entre tester, c'est-à-dire, contrôler que votre programme se comporte de la façon attendue, et réaliser une batterie de tests, morceaux de code exécutables qui testent automatiquement la justesse de parties (unités) du logiciel. Ces morceaux de code exécutables sont appelés tests unitaires.

Dans ce chapitre, nous partirons du simple code de test à base de print pour aboutir au test totalement automatisé. Imaginez qu'il vous a été demandé de tester le array de PHP (tableau). Parmi les fonctionnalités à tester se trouve la fonction count(). Pour un tableau nouvellement créé, nous attendons que la fonction count() retourne 0. Après avoir ajouté un élément, count() doit retourner 1. Exemple 1.1, « Tester les opérations sur les tableaux » montre ce que nous voulons tester.

Exemple 1.1. Tester les opérations sur les tableaux

<?php
$fixture = array();
// $fixture doit être vide.

$fixture[] = 'element';
// $fixture doit contenir un élément.
?>

Un moyen vraiment simple de contrôler que nous obtenons les résultats que nous attendons consiste à afficher le résultat de count() avant et après l'ajout de l'élément (voir Exemple 1.2, « Utiliser print pour tester les opérations sur les tableaux »). Si nous obtenons 0 puis 1, array et count() se comportent comme espéré.

Exemple 1.2. Utiliser print pour tester les opérations sur les tableaux

<?php
$fixture = array();
print count($fixture) . "\n";

$fixture[] = 'element';
print count($fixture) . "\n";
?>
0
1

Maintenant, nous aimerions passer de tests qui nécessitent une interprétation manuelle à des tests qui sont exécutés automatiquement. Dans Exemple 1.3, « Comparer les valeurs attendues et constatées pour tester les opérations sur les tableaux », nous écrivons la comparaison entre les valeurs attendues et constatées dans le code de test et nous affichons ok si ces valeurs sont égales. Si jamais nous voyons un message not ok, nous savons que quelque chose ne va pas.

Exemple 1.3. Comparer les valeurs attendues et constatées pour tester les opérations sur les tableaux

<?php
$fixture = array();
print count($fixture) == 0 ? "ok\n" : "not ok\n";

$fixture[] = 'element';
print count($fixture) == 1 ? "ok\n" : "not ok\n";
?>
ok
ok

Nous factorisons maintenant la comparaison des valeurs attendues et constatées dans une fonction qui lève une Exception quand il y a non correspondance (Exemple 1.4, « Utiliser une fonction d'assertion pour tester les opérations sur les tableaux »). Ceci nous offre deux avantages : l'écriture de tests devient plus facile et nous n'avons de message que quand il y a un problème.

Exemple 1.4. Utiliser une fonction d'assertion pour tester les opérations sur les tableaux

<?php
$fixture = array();
assertTrue(count($fixture) == 0);

$fixture[] = 'element';
assertTrue(count($fixture) == 1);

function assertTrue($condition)
{
if (!$condition) {
throw new Exception('Assertion en échec.');
}
}
?>

Le test est maintenant complètement automatisé. Au lieu de simplement tester comme nous le faisions dans notre première version, avec cette version, nous avons un test automatisé.

L'objectif en utilisant des tests automatisés et de faire moins d'erreurs. Tant que votre code ne sera pas parfait, même avec d'excellents tests, vous constaterez certainement une réduction drastique des défauts dès que vous commencerez à utiliser des tests automatisés. Les tests automatisés vous donnent une confiance justifiée en votre code. Vous pouvez mettre à profit cette confiance pour faire évoluer de façon plus audacieuse votre conception (refactoring), mieux collaborer avec les autres membres de votre équipe (tests communs à l'équipe), améliorer les relations avec vos clients et rentrer chez vous tous les soirs avec la preuve que le système est meilleur maintenant qu'il ne l'était ce matin grâce à vos efforts.

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