Download - Commencer avec le tdd

Transcript
Page 1: Commencer avec le tdd

Commencer avec le TDDEric Hogue

PHP Québec - 2013-06-06

Page 2: Commencer avec le tdd

Test Driven Development

Page 3: Commencer avec le tdd

Où Commencer?

Page 4: Commencer avec le tdd

Les tests unitaires

Test automatisé qui exerce une seule unité de code

Page 5: Commencer avec le tdd

Outils

● PHPUnit● SimpleTest● atoum● PHPT

Page 6: Commencer avec le tdd

PHPUnit

FactorialTest.php<?phpclass FactorialTest extends \PHPUnit_Framework_TestCase {}

Page 7: Commencer avec le tdd

public function testSomething() {}

/** @test */public function somethingElse() {}

Page 8: Commencer avec le tdd

Les assertions

● $this->assertTrue();● $this->assertEquals();● $this->assertSame();● $this->assertContains();● $this->assertNull();● $this->assertRegExp();● ...

Page 9: Commencer avec le tdd

Préparation des tests

setup() -> Avant chaque testteardown() -> Après chaque test

Page 10: Commencer avec le tdd

phpunit.xml

<phpunit bootstrap="bootstrap.php" colors="true"strict="true"verbose="true"

>...

</phpunit>

Page 11: Commencer avec le tdd

Le TDD

nyuhuhuuhttp://www.flickr.com/photos/nyuhuhuu/4442144329/

Page 12: Commencer avec le tdd

Red - Green - Refactor

Rouge Un test qui échoue

Page 13: Commencer avec le tdd

Red - Green - Refactor

VertFaire passer le test

Page 14: Commencer avec le tdd

Red - Green - Refactor

RefactorArranger le code

Page 15: Commencer avec le tdd

/** @test */public function create() {

$this->assertNotNull(new Factorial);}

Page 16: Commencer avec le tdd

class Factorial {}

Page 17: Commencer avec le tdd

/** @test */public function factOf1() {

$facto = new Factorial;$this->assertSame(1, $facto->fact(1));

}

Page 18: Commencer avec le tdd

public function fact($number) {return 1;

}

Page 19: Commencer avec le tdd

Duplication

public function create() {$this->assertNotNull(new Factorial);

}

public function factOf1() {$facto = new Factorial;

...

Page 20: Commencer avec le tdd

public function setup() {$this->facto = new Factorial;

}/** @test */public function factOf1() {

$this->assertSame(1, $this->facto->fact(1));}

Page 21: Commencer avec le tdd

/** @test */public function factOf2() {

$this->assertSame(2, $this->facto->fact(2));}

Page 22: Commencer avec le tdd

public function fact($number) {return $number;

}

Page 23: Commencer avec le tdd

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));}

Page 24: Commencer avec le tdd

public function factDataProvider() {return array(

array(1, 1),array(2, 2),

);}

Page 25: Commencer avec le tdd

/** * @test * @dataProvider factDataProvider */public function factorial($number, $expected) {

$result = $this->facto->fact($number);$this->assertSame($expected, $result);

}

Page 26: Commencer avec le tdd

array(3, 6,),

Page 27: Commencer avec le tdd

array(3, 6,),

public function fact($number) {if ($number < 2) return 1;return $number * $this->fact($number - 1);

}

Page 28: Commencer avec le tdd

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

Page 29: Commencer avec le tdd

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

Page 30: Commencer avec le tdd

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

Page 31: Commencer avec le tdd

Beaucoup de travail

Page 32: Commencer avec le tdd

Photo: Adam Melanconhttp://www.flickr.com/photos/melancon/348974082/

Page 33: Commencer avec le tdd

Les dépendances

Zhent_http://www.flickr.com/photos/zhent/574472488/in/faves-96579472@N07/

Page 34: Commencer avec le tdd

Les fichiers

Ryan Vettesehttp://www.flickr.com/photos/rvettese/383453435/

Page 35: Commencer avec le tdd

vfsStream

Système de fichier virtuel

composer.json"require-dev": {

"mikey179/vfsStream": "*"},

Page 36: Commencer avec le tdd

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'));

Page 37: Commencer avec le tdd

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);

Page 38: Commencer avec le tdd

La base de données

shindoversehttp://www.flickr.com/photos/shindotv/3835363999/

Page 39: Commencer avec le tdd

Les Mocks

Permet de remplacer une dépendance

● PHPUnit mocks● Mockery● Phake

Page 40: Commencer avec le tdd

Création

$mock = $this->getMock('\Namespace\Classe');

Page 41: Commencer avec le tdd

Création

$mock = $this->getMock('\Namespace\Classe');

Ou

$mock =$this->getMockBuilder ('\Namespace\Classe') ->disableOriginalConstructor() ->getMock();

Page 42: Commencer avec le tdd

$mock->expect($this->once()) ->method('nomMéthode')

Page 43: Commencer avec le tdd

$mock->expect($this->once()) ->method('nomMéthode') ->with(1, 'aa', $this->anything())

Page 44: Commencer avec le tdd

$mock->expect($this->once()) ->method('nomMéthode') ->with(1, 'aa', $this->anything()) ->will($this->returnValue(10));

Page 45: Commencer avec le tdd

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'))));

Page 46: Commencer avec le tdd

$pdo = $this->getMockBuilder('\stdClass')->disableOriginalConstructor()->setMethods(array('prepare'))->getMock();

$pdo->expects($this->once())->method('prepare')->will($this->returnValue($statement));

Page 47: Commencer avec le tdd

Pour utiliser PDO

$this->getMockBuilder('\PDO')

Page 48: Commencer avec le tdd

class PDOMock extends \PDO { public function __construct() {}

}

$pdo = $this->getMockBuilder('\PDOMock')->getMock();

Page 49: Commencer avec le tdd

mysql_*

Eliot Phillipshttp://www.flickr.com/photos/hackaday/5553713944/

Page 50: Commencer avec le tdd

L'extension DbUnit

extends PHPUnit_Extensions_Database_TestCase

public function getConnection() { $pdo = new PDO('sqlite::memory:');

return $this->createDefaultDBConnection($pdo, ':memory:');

}

Page 51: Commencer avec le tdd

public function getDataSet() {return $this->createFlatXMLDataSet('file');

}

Page 52: Commencer avec le tdd

API

Page 53: Commencer avec le tdd

● 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

Page 54: Commencer avec le tdd

Avantages - Inconvénients

Page 55: Commencer avec le tdd

Avantages du TDD

● Moins de régression

Page 56: Commencer avec le tdd

Avantages du TDD

● Moins de régression● Plus de confiance

Page 57: Commencer avec le tdd

Avantages du TDD

● Moins de régression● Plus de confiance● Couplage plus faible

Page 58: Commencer avec le tdd

Avantages du TDD

● Moins de régression● Plus de confiance● Couplage plus faible● Design plus simple

Page 59: Commencer avec le tdd

Inconvénients du TDD

● Plus long

Page 60: Commencer avec le tdd

“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/

Page 61: Commencer avec le tdd

Inconvénients du TDD

● Plus long● Difficile à vendre aux gestionnaires

Page 62: Commencer avec le tdd

Inconvénients du TDD

● Plus long● Difficile à vendre aux gestionnaires● C'est difficile

Page 63: Commencer avec le tdd

Prochaines étapes?

Page 64: Commencer avec le tdd

Continuous Testing

Page 65: Commencer avec le tdd

BDD

● phpspec● Codeception● Behat

○ Mink + Goutte/Selenium

Page 66: Commencer avec le tdd

Behat + Mink

Feature: Add a new postIn order to post the next meetupAs an admin userI want to add a new event

Page 67: Commencer avec le tdd

Scenario: View eventsGiven I am on "/"When I go to "evenement"Then I should see "Commencer avec le

TDD"

Page 68: Commencer avec le tdd

Intégration Continue

Page 69: Commencer avec le tdd

Intégration Continue

● Exécute les tests automatiquement○ tests unitaires○ tests d'acceptation○ tests de performace ○ ...

Page 70: Commencer avec le tdd

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

Page 71: Commencer avec le tdd

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

Page 72: Commencer avec le tdd

Damián Navashttp://www.flickr.com/photos/wingedwolf/5471047557/

Commentaires:https://joind.in/8740

Twitter:@ehogue

Blogue:http://erichogue.ca/

Questions