Utilisateur de PHPUnit depuis peu, je me lance progressivement dans l’apprentissage des différentes ficelles de cet outil fort sympathique et je fais face à un petit problème qui ne semble pas venir de mon application.
Petit problème qui consiste juste à faire une assertion de contenu de la propriété content de ma classe Textarea.
Vous l’aurez bien compris, je suis en plein écriture de tests unitaires pour MyOOF dans l’optique de poursuivre son développement en PHP 5.3. Petit développement qui risque de s’annoncer bien agréable à entreprendre puisque je n’ai envie que d’une chose : découvrir mais surtout mettre en application des nouveautés de PHP 5.3
.
Je suis donc en train de rédiger le test unitaire de la classe Textarea que voici (après suppression de tous les autres tests inutiles à la découverte de mon problème) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <?php // TextareaTest.php PHPUnit_Util_Filter::addFileToFilter(__FILE__); require_once __DIR__ . '/loader.php'; class TextareaTest extends PHPUnit_Framework_TestCase { private $_textarea; private $_clone; protected function setUp() { $this->_textarea = new Textarea(array( 'name' => 'foobar', 'xml:lang' => 'fr-FR', 'id' => 'txt', 'rows' => 12, 'style' => 'border: 2px red dotted;' ), 'empty'); } // ... public function testTextareaSetContentSucceed() { $this->assertSame($this->_textarea, $this->_textarea->setContent('MyOOF')); } public function testTextareaGetContentSucceed() { $this->assertEquals('MyOOF', $this->_textarea->getContent()); } public function testTextareaUnsetContentSucceed() { $this->assertSame($this->_textarea, $this->_textarea->unsetContent()); $this->assertClassHasAttribute('content', 'Textarea'); $this->assertEquals('', $this->_textarea->content); } // ... public function tearDown() { unset($this->_textarea); unset($this->_clone); } } |
J’éxécute donc mon test et voici ce que celui-ci me sort au lieu de passer :
/htdocs/.../myoof_current/tests% phpunit TextareaTest.php PHPUnit 3.4.3 by Sebastian Bergmann. .F. Time: 0 seconds There was 1 failure: 1) TextareaTest::testTextareaGetContentSucceed Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -MyOOF +empty FAILURES! Tests: 3, Assertions: 5, Failures: 1. zsh: exit 1 phpunit TextareaTest.php /htdocs/.../myoof_current/tests%
Ajoutons maintenant quelques var_dump() aux bons endroits :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <?php // TextareaTest.php PHPUnit_Util_Filter::addFileToFilter(__FILE__); require_once __DIR__ . '/loader.php'; class TextareaTest extends PHPUnit_Framework_TestCase { private $_textarea; private $_clone; protected function setUp() { $this->_textarea = new Textarea(array( 'name' => 'foobar', 'xml:lang' => 'fr-FR', 'id' => 'txt', 'rows' => 12, 'style' => 'border: 2px red dotted;' ), 'empty'); } // ... public function testTextareaSetContentSucceed() { var_dump($this->_textarea->getContent()); $this->assertSame($this->_textarea, $this->_textarea->setContent('MyOOF')); var_dump($this->_textarea->getContent()); } public function testTextareaGetContentSucceed() { var_dump($this->_textarea->getContent()); $this->assertEquals('MyOOF', $this->_textarea->getContent()); } public function testTextareaUnsetContentSucceed() { $this->assertSame($this->_textarea, $this->_textarea->unsetContent()); $this->assertClassHasAttribute('content', 'Textarea'); $this->assertEquals('', $this->_textarea->content); } // ... public function tearDown() { unset($this->_textarea); unset($this->_clone); } } |
Nous sommes d’accord que les var_dump() devraient nous sortir successivement les outputs suivants :
string(5) "empty" string(5) "MyOOF" string(5) "MyOOF"
Observons :
/htdocs/.../myoof_current/tests% phpunit TextareaTest.php PHPUnit 3.4.3 by Sebastian Bergmann. string(5) "empty" string(5) "MyOOF" .string(5) "empty" F. Time: 0 seconds There was 1 failure: 1) TextareaTest::testTextareaGetContentSucceed Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -MyOOF +empty FAILURES! Tests: 3, Assertions: 5, Failures: 1. zsh: exit 1 phpunit TextareaTest.php /htdocs/.../myoof_current/tests%
Quel est le soucis ? Est-ce que je m’y prends mal avec PHPUnit ou alors est-ce un problème du framework ? Un soucis de cache d’Op-code sachant qu’APC et eAccelerator sont down ?
Si vous avez une petite idée, n’hésitez pas… il est tard et je suis fatigué donc il se peut qu’un détail me soit échappé.
Merci.

Bonjour,
non, ce comportement est normal. SetUp() est appelée avant chaque test, donc au début des trois tests le getContent() doit renvoyer « empty » puisque c’est cette valeur qui est passée au constructeur.
Le bon test serait
Cela vient d’une propriété importante et nécessaire des tests : ils doivent être indépendants les uns des autres, totalement isolés. On doit pouvoir en jouer un tout seul, ou changer leur ordre sans que le résultat du test change. PHPUnit va d’ailleurs les jouer dans des processus différents prochainement, afin de renforcer l’isolation.
Bienvenue dans le monde merveilleux des tests unitaires, une fois appris j’ai réellement du mal à m’en passer tellement cela rend confiant sur son code.
Cédric
En effet, t’as quelques soucis d’utilisation de PHPUnit…
Pas grave, l’outil est puissant, la méthodologie complexe et il faut s’y former.
Ton « problème » vient du fait que la méthode setUp est appelée avant chaque test, et donc elle te réinitialise ton textarea (ce qui est bien son boulot, pour garantir l’indépendance de chaque test).
Si vraiment tu veux utiliser les méthodes de test de façon dépendante, ce que je te déconseille en phase de prise en main, utilise la balise @depends.
D’ailleurs, quel est le but de ton test testTextareaSetContentSucceed ? Tester que setContent te restitue le textarea ? Dans ce cas il faudrait changer le nom du test…
Ah oui d’accord, je comprends mieux maintenant… Je pensais que chaque tests se succédait…
C’est bizarre parce que j’ai régidé ma classe InputTest de cette même manière et tout est bien passé.
Je comprends mieux désormais le « cloisenement » des tests ainsi. Mais est-ce la méthode assertPreConditions() est également rappelé à chaque tests ?
@Gabriele
Quel nom me suggère-tu ?
J’apprends sur le tas, c’est pas encore évident de donner des noms de méthodes correctement ciblés.
Merci à vous deux !
Je pense que cette page répondra assez clairement à ta question
http://www.phpunit.de/manual/current/en/fixtures.html
En résumé
setUpBeforeClass
setUp
assertPreConditions
testOne
assertPostConditions
tearDown
setUp
assertPreConditions
testTwo
tearDown
tearDownAfterClass
mais je n’ai jamais eu à utiliser autre chose que SetUp et TearDown, depuis 9 ans que j’utilise les TU au quotidien. Je vais chercher l’utilité des autres.
Super, merci beaucoup Cédric !
Je crois qu’à vouloir apprendre trop vite, je cherche à complexifier mes tests inutilement…