Upload
eric-hogue
View
7.260
Download
1
Embed Size (px)
DESCRIPTION
Le TDD (Test Driven Development) devient de plus en plus populaire. Guider le développement d’une application par les tests est maintenant une pratique acceptée dans plusieurs communautés. Mais démarrer avec le TDD peut être une tâche ardue. Dans cette présentation, nous allons voir ce qu’est le TDD. En commençant par les principes fondamentaux au TDD. Puis nous verrons quels sont les outils utilisés. Puis comment appliquer ces techniques dans le travail quotidien.
Citation preview
Commencer avec le TDDEric Hogue
PHP Québec - 2013-06-06
Test Driven Development
Où Commencer?
Les tests unitaires
Test automatisé qui exerce une seule unité de code
Outils
● PHPUnit● SimpleTest● atoum● PHPT
PHPUnit
FactorialTest.php<?phpclass FactorialTest extends \PHPUnit_Framework_TestCase {}
public function testSomething() {}
/** @test */public function somethingElse() {}
Les assertions
● $this->assertTrue();● $this->assertEquals();● $this->assertSame();● $this->assertContains();● $this->assertNull();● $this->assertRegExp();● ...
Préparation des tests
setup() -> Avant chaque testteardown() -> Après chaque test
phpunit.xml
<phpunit bootstrap="bootstrap.php" colors="true"strict="true"verbose="true"
>...
</phpunit>
Le TDD
nyuhuhuuhttp://www.flickr.com/photos/nyuhuhuu/4442144329/
Red - Green - Refactor
Rouge Un test qui échoue
Red - Green - Refactor
VertFaire passer le test
Red - Green - Refactor
RefactorArranger le code
/** @test */public function create() {
$this->assertNotNull(new Factorial);}
class Factorial {}
/** @test */public function factOf1() {
$facto = new Factorial;$this->assertSame(1, $facto->fact(1));
}
public function fact($number) {return 1;
}
Duplication
public function create() {$this->assertNotNull(new Factorial);
}
public function factOf1() {$facto = new Factorial;
...
public function setup() {$this->facto = new Factorial;
}/** @test */public function factOf1() {
$this->assertSame(1, $this->facto->fact(1));}
/** @test */public function factOf2() {
$this->assertSame(2, $this->facto->fact(2));}
public function fact($number) {return $number;
}
Encore de la duplication
/** @test */public function factOf1() {
$this->assertSame(1, $this->facto->fact(1));}/** @test */public function factOf2() {
$this->assertSame(2, $this->facto->fact(2));}
public function factDataProvider() {return array(
array(1, 1),array(2, 2),
);}
/** * @test * @dataProvider factDataProvider */public function factorial($number, $expected) {
$result = $this->facto->fact($number);$this->assertSame($expected, $result);
}
array(3, 6,),
array(3, 6,),
public function fact($number) {if ($number < 2) return 1;return $number * $this->fact($number - 1);
}
Les 3 lois du TDD selon Uncle Bob
● Ne jamais écrire du code de production sauf pour faire passer un test unitaire qui échoue
http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
Les 3 lois du TDD selon Uncle Bob
● Ne jamais écrire du code de production sauf pour faire passer un test unitaire qui échoue
● Ne pas écrire plus de test que nécéssaire pour avoir un échec○ une erreur de compilation est un échec
http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
Les 3 lois du TDD selon Uncle Bob
● Ne jamais écrire du code de production sauf pour faire passer un test unitaire qui échoue
● Ne pas écrire plus de test que nécéssaire pour avoir un échec○ une erreur de compilation est un échec
● Ne pas écrire plus de code de production que nécéssaire pour faire passer le test unitaire
http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
Beaucoup de travail
Photo: Adam Melanconhttp://www.flickr.com/photos/melancon/348974082/
Les dépendances
Zhent_http://www.flickr.com/photos/zhent/574472488/in/faves-96579472@N07/
Les fichiers
Ryan Vettesehttp://www.flickr.com/photos/rvettese/383453435/
vfsStream
Système de fichier virtuel
composer.json"require-dev": {
"mikey179/vfsStream": "*"},
Vérifier la création d'un répertoire
$root = vfsStream::setup('dir');$parentDir = $root->url('dir');
//Code qui créer un sous répertoire$this->createDir($parentDir, 'test');
$this->assertTrue($root->hasChild('test'));
Lire un fichier
$struct = array('subDir' => array('test.txt' => 'contenu')
);$root = vfsStream::setup('root', null, $struct);$parentDir = $root->url('root');
$content = file_get_contents($parentDir . '/subDir/test.txt');$this->assertSame('contenu' , $content);
La base de données
shindoversehttp://www.flickr.com/photos/shindotv/3835363999/
Les Mocks
Permet de remplacer une dépendance
● PHPUnit mocks● Mockery● Phake
Création
$mock = $this->getMock('\Namespace\Classe');
Création
$mock = $this->getMock('\Namespace\Classe');
Ou
$mock =$this->getMockBuilder ('\Namespace\Classe') ->disableOriginalConstructor() ->getMock();
$mock->expect($this->once()) ->method('nomMéthode')
$mock->expect($this->once()) ->method('nomMéthode') ->with(1, 'aa', $this->anything())
$mock->expect($this->once()) ->method('nomMéthode') ->with(1, 'aa', $this->anything()) ->will($this->returnValue(10));
PDO
$statement = $this->getMockBuilder('\PDOStatement')
->getMock();$statement->expects($this->once())
->method('execute')->will($this->returnValue(true));
$statement->expects($this->once())->method('fetchAll')->will($this->returnValue(array(array('id' =>
123, 'name' => 'Eric Hogue'))));
$pdo = $this->getMockBuilder('\stdClass')->disableOriginalConstructor()->setMethods(array('prepare'))->getMock();
$pdo->expects($this->once())->method('prepare')->will($this->returnValue($statement));
Pour utiliser PDO
$this->getMockBuilder('\PDO')
class PDOMock extends \PDO { public function __construct() {}
}
$pdo = $this->getMockBuilder('\PDOMock')->getMock();
mysql_*
Eliot Phillipshttp://www.flickr.com/photos/hackaday/5553713944/
L'extension DbUnit
extends PHPUnit_Extensions_Database_TestCase
public function getConnection() { $pdo = new PDO('sqlite::memory:');
return $this->createDefaultDBConnection($pdo, ':memory:');
}
public function getDataSet() {return $this->createFlatXMLDataSet('file');
}
API
● Mettre tous les appels HTTP dans une classe○ Zend\Http○ Simple classe qui appel curl
● Faire un mock de cette classe○ Retourne le xml/json voulu
Avantages - Inconvénients
Avantages du TDD
● Moins de régression
Avantages du TDD
● Moins de régression● Plus de confiance
Avantages du TDD
● Moins de régression● Plus de confiance● Couplage plus faible
Avantages du TDD
● Moins de régression● Plus de confiance● Couplage plus faible● Design plus simple
Inconvénients du TDD
● Plus long
“If it doesn't have to work, I can get it done a lot faster!”- Kent Beck
Improve Ithttp://www.flickr.com/photos/improveit/1573943815/
Inconvénients du TDD
● Plus long● Difficile à vendre aux gestionnaires
Inconvénients du TDD
● Plus long● Difficile à vendre aux gestionnaires● C'est difficile
Prochaines étapes?
Continuous Testing
BDD
● phpspec● Codeception● Behat
○ Mink + Goutte/Selenium
Behat + Mink
Feature: Add a new postIn order to post the next meetupAs an admin userI want to add a new event
Scenario: View eventsGiven I am on "/"When I go to "evenement"Then I should see "Commencer avec le
TDD"
Intégration Continue
Intégration Continue
● Exécute les tests automatiquement○ tests unitaires○ tests d'acceptation○ tests de performace ○ ...
Intégration Continue
● Exécute les tests automatiquement○ tests unitaires○ tests d'acceptation○ tests de performace ○ ...
● Vérifie que les standards sont respectés○ phpcs
Intégration Continue
● Exécute les tests automatiquement○ tests unitaires○ tests d'acceptation○ tests de performace ○ ...
● Vérifie que les standards sont respectés○ phpcs
● Détecte des "code smells"○ phploc○ phpcpd○ PHP Depend○ PHP Mess Detector
Damián Navashttp://www.flickr.com/photos/wingedwolf/5471047557/
Commentaires:https://joind.in/8740
Twitter:@ehogue
Blogue:http://erichogue.ca/
Questions