Grouper des tests

Pour enchaîner nous allons remplir des blancs et créer une suite de tests.

Un autre test

Ajouter un autre test peut être aussi simple qu'ajouter une nouvelle méthode à un scénario de test...

class TestOfLogging extends UnitTestCase {

    function testCreatingNewFile() {
        @unlink('../temp/test.log');
        $log = new Log('../temp/test.log');
        $this->assertFalse(file_exists('../temp/test.log'), 'Created before message');
        $log->message('Should write this to a file');
        $this->assertTrue(file_exists('../temp/test.log'), 'File created');
        @unlink('../temp/test.log');
    }
    
    function testSecondMessageIsAppended() {
        @unlink('../temp/test.log');
        $log = new Log('../temp/test.log');
        $log->message('Test line 1');
        $messages = file('../temp/test.log');
        $this->assertPattern('/Test line 1/', $messages[0]);
        $log->message('Test line 2');
        $messages = file('../temp/test.log');
        $this->assertPattern('/Test line 2/', $messages[1]);
        @unlink('../temp/test.log');
    }
}

La méthode du scénario de test assertPattern() utilise les expressions rationnelles Perl pour vérifier qu'une chaîne respecte un certain motif.

Tout ce que nous faisons dans ce nouveau test, c'est écrire une ligne dans un fichier, puis la lire, le tout deux fois de suite. Nous souhaitons simplement vérifier que le loggueur ajoute le texte à la fin plutôt qu'écraser les données déjà existantes.

De toute façon ce test passe directement...

Log class test

1/1 test cases complete. 4 passes, 0 fails and 0 exceptions.
Notre code contient actuellement beaucoup de répétitions, nous devons effacer le fichier de test avant et après chaque test.

De même que JUnit, SimpleTest utilise les méthodes setUp() et tearDown() qui sont exécutées respectivement avant et après chaque test. La suppression du fichier est commune à tous les tests : nous devrions donc y mettre cette opération.

Nos tests sont verts donc nous pouvons faire un peu de remaniement...

class TestOfLogging extends UnitTestCase {

    function setUp() {
        @unlink('../temp/test.log');
    }

    function tearDown() {
        @unlink('../temp/test.log');
    }

    function testCreatingNewFile() {
        $log = new Log('../temp/test.log');
        $this->assertFalse(file_exists('../temp/test.log'), 'Created before message');
        $log->message('Should write this to a file');
        $this->assertTrue(file_exists('../temp/test.log'), 'File created');
    }
    
    function testSecondMessageIsAppended() {
        $log = new Log('../temp/test.log');
        $log->message('Test line 1');
        $messages = file('../temp/test.log');
        $this->assertPattern('/Test line 1/', $messages[0]);
        $log->message('Test line 2');
        $messages = file('../temp/test.log');
        $this->assertPattern('/Test line 2/', $messages[1]);
    }
	
}

Le test reste vert. Nous pouvons continuer à ajouter des méthodes sans test au scénario, il suffit que leur nom ne commence pas par la chaîne "test". Seules les méthodes commençant par "test" sont exécutées. Nous pouvons donc continuer le remaniement...

class TestOfLogging extends UnitTestCase {

    function setUp() {
        @unlink('../temp/test.log');
    }

    function tearDown() {
        @unlink('../temp/test.log');
    }
    
    function getFileLine($filename, $index) {
        $messages = file($filename);
        return $messages[$index];
    }
    
    function testCreatingNewFile() {
        $log = new Log('../temp/test.log');
        $this->assertFalse(file_exists('../temp/test.log'), 'Created before message');
        $log->message('Should write this to a file');
        $this->assertTrue(file_exists('../temp/test.log'), 'File created');
    }
    
    function testSecondMessageIsAppended() {
        $log = new Log('../temp/test.log');
        $log->message('Test line 1');
        $this->assertPattern('/Test line 1/', $this->getFileLine('../temp/test.log', 0));
        $log->message('Test line 2');
        $this->assertPattern('/Test line 2/', $this->getFileLine('../temp/test.log', 1));
    }
}

Que vous préfériez cette version ou la précédente ne dépend que de votre goût personnel. Il y a un peu plus de code dans cette dernière mais la logique du test est plus claire.

Une suite de tests

Un scénario de test ne fonctionne pas tout seul pendant très longtemps. Quand on code pour de vrai nous souhaitons exécuter un maximum de tests aussi souvent et aussi rapidement que possible. Ça veut dire les grouper dans des suites de tests qui incluent l'ensemble des tests de l'application.

Premièrement nous devons créer une suite de tests dans le répertoire tests...

<?php
require_once(dirname(__FILE__) . '/simpletest/autorun.php');
require_once('log_test.php');

class AllTests extends TestSuite {
    function __construct() {
        parent::__construct();
        $this->addTest(new TestOfLogging());
    }
}
?>

Il n'y a presque de pas de différence tant que les choses marchent...

All tests

1/1 test cases complete. 4 passes and 0 fails.
Ajouter des tests est donc très facile.

Dans la page suivante nous les ajouterons encore plus rapidement.

Ajouter un autres test au scénario existant et remanier.
La technique brute pour créer des suites de tests unitaires.
Ensuite vient le contrôle de comment la classe sous le test interagit avec le reste du système.
Avant il y a la création du premier test.
Vous aurez besoin de SimpleTest pour exécuter ces exemples.