recettes de tests

144
RECETTES de TESTS Charles Desneuf - @SelrahcD

Upload: charles-desneuf

Post on 29-Jan-2018

695 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Recettes de tests

RECETTES de

TESTSCharles Desneuf - @SelrahcD

Page 2: Recettes de tests

@SelrahcD

Page 3: Recettes de tests

Photo by Dan Gold on Unsplash

Page 4: Recettes de tests

Découvrir des bugs Permettre de réfactorer

Documenter Réfléchir à l’interface du système Détecter des problèmes de design

Photo by Brooke Lark on Unsplash

Page 5: Recettes de tests

Découvrir des bugs Permettre de réfactorer

Documenter Réfléchir à l’interface du système Détecter des problèmes de design

Photo by Brooke Lark on Unsplash

Page 6: Recettes de tests

Découvrir des bugs Permettre de réfactorer

Documenter Réfléchir à l’interface du système Détecter des problèmes de design

Photo by Brooke Lark on Unsplash

Page 7: Recettes de tests

Découvrir des bugs Permettre de réfactorer

Documenter Réfléchir à l’interface du système

Détecter des problèmes de designPhoto by Brooke Lark on Unsplash

Page 8: Recettes de tests

Découvrir des bugs Permettre de réfactorer

Documenter Réfléchir à l’interface du système

Détecter des problèmes de designPhoto by Brooke Lark on Unsplash

Page 9: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système

Avoir un résultat prédictible Rapides

Indépendants les uns des autres Simple à mettre en place

Photo by Brooke Lark on Unsplash

Page 10: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système

Avoir un résultat prédictible Rapides

Indépendants les uns des autres Simple à mettre en place

Photo by Brooke Lark on Unsplash

Page 11: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système Avoir un résultat prédictible

Rapides Indépendants les uns des autres

Simple à mettre en placePhoto by Brooke Lark on Unsplash

Page 12: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système

Avoir un résultat prédictible Rapides

Indépendants les uns des autres Simple à mettre en place

Photo by Brooke Lark on Unsplash

Page 13: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système

Avoir un résultat prédictible Rapides

Indépendants les uns des autres Simple à mettre en place

Photo by Brooke Lark on Unsplash

Page 14: Recettes de tests

Indépendants de l’implémentation Décrire le comportement du système

Avoir un résultat prédictible Rapides

Indépendants les uns des autres Simple à mettre en place

Photo by Brooke Lark on Unsplash

Page 15: Recettes de tests

PHPUnit Prophecy

Photo by Scott Umstattd on Unsplash

Page 16: Recettes de tests

ANATOMIE D’UN

TEST

Photo by Michael Browning on Unsplash

Page 17: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 18: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 19: Recettes de tests

public function testIlAnnonceLePlatDuJour()

public function test_il_annonce_le_plat_du_jour()

/** * @test */ public function il_annonce_le_plat_du_jour()

/** * @test */ public function il annonce le plat du jour()

Page 20: Recettes de tests

public function he_should_announce_todays_special()

Page 21: Recettes de tests

public function he_announces_todays_special()

Page 22: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 23: Recettes de tests

➜ recettes phpunit --testdox tests/ServeurTest.php

PHPUnit 4.7.6 by Sebastian Bergmann and contributors.

Serveur

[x] il annonce le plat du jour

[x] il transmet une commande pour le plat du jour a la cuisine

Page 24: Recettes de tests

➜ recettes phpunit --testdox tests/ServeurTest.php

PHPUnit 4.7.6 by Sebastian Bergmann and contributors.

Serveur

[x] il annonce le plat du jour

[x] il transmet une commande pour le plat du jour a la cuisine

Page 25: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 26: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 27: Recettes de tests

Photo by Gemma Evans on Unsplash

ARRANGE

ACT

ASSERT

Page 28: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Page 29: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Arrange

Page 30: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Act

Page 31: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_il_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); } }

Assert

Page 32: Recettes de tests

ARRANGE ACT ASSERT

GIVEN WHEN THEN

Photo by Baher Khairy on Unsplash

Page 33: Recettes de tests

public function test_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlat() ->willReturn('Gencives de porc !') ->shouldBeCalledTimes(1);

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); }

Page 34: Recettes de tests

class Serveur {

public function annonceLeMenu() { $plat = $this->cuisine->quelEstLePlatDuJour();

// fait autre chose, oublie le menu

$plat = $this->cuisine->quelEstLePlatDuJour();

return sprintf( 'Le chef vous propose aujourd\'hui %s', $this->transformeNomDuPlat($plat) ); } }

Page 35: Recettes de tests

class Serveur {

public function annonceLeMenu() { $plat = 'Gencives de porc !';

return sprintf( 'Le chef vous propose aujourd\'hui %s', $this->transformeNomDuPlat($plat) ); } }

Page 36: Recettes de tests

public function test_annonce_le_plat_du_jour() {

$cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlat() ->willReturn('Gencives de porc !') ->shouldBeCalledTimes(1);

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); }

Page 37: Recettes de tests

public function test_annonce_le_plat_du_jour() { $cuisine = $this->prophesize(Cuisine::class);

$cuisine ->quelEstLePlatDuJour() ->willReturn('Gencives de porc !');

$serveur = new Serveur($cuisine->reveal());

$annonce = $serveur->annonceLePlatDuJour();

$this->assertEquals( 'Le chef vous propose aujourd\'hui des gencives de porc', $annonce ); }

Page 38: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Page 39: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Arrange

Page 40: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Act

Page 41: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Assert

Page 42: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Page 43: Recettes de tests

class Serveur {

public function recoitUneCommandePourUnPlatDuJour() { } }

Page 44: Recettes de tests

class Serveur {

public function recoitUneCommandePourUnPlatDuJour() { for($i = 0; $i < 100; $i++) { $this->cuisine->ilFautUnPlatDuJour(); } } }

Page 45: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Page 46: Recettes de tests

class Serveur {

public function recoitUneCommandePourUnPlatDuJour() {

$this->cuisine->ilFautUnPlatDuJour();

} }

Page 47: Recettes de tests

class ServeurTest extends \PHPUnit_Framework_TestCase {

public function test_transmet_une_commande_pour_le_plat_du_jour_a_la_cuisine() { $cuisine = $this->prophesize(Cuisine::class);

$serveur = new Serveur($cuisine->reveal());

$serveur->recoitUneCommandePourUnPlatDuJour();

$cuisine ->ilFautUnPlatDuJour() ->shouldHaveBeenCalledTimes(1); } }

Page 48: Recettes de tests

Mock Arrange

Spy Assert

Photo by Alexander Maasch on Unsplash

Page 49: Recettes de tests

EGALITE

DES

OBJETSPhoto by Brenan Greene on Unsplash

Page 50: Recettes de tests

class PizzaioloTest extends \PHPUnit_Framework_TestCase {

public function test_prepare_une_pizza_margherita_maison() { $pizzaiolo = new Pizzaiolo();

$pizza = $pizzaiolo->preparePizzaMargheritaMaison();

$this->assertEquals( ['pate', 'sauce tomate', 'basilic', 'mozzarella'], $pizza->ingredients() ); } }

Page 51: Recettes de tests

class PizzaSurgelee { public function __construct($ingredients) { $this->ingredients = $ingredients; }

public function ingredients() { return $this->ingredients; } }

Page 52: Recettes de tests

class Pizzaiolo {

public function preparePizzaMargheritaMaison(){

$pizzaSurgelee = $this->acheteUnePizzaMargheritaSurgelee();

return $this->rechauffeLaPizza($pizzaSurgelee); } }

Page 53: Recettes de tests

public function test_prepare_une_pizza_margherita_maison() { $pizzaiolo = new Pizzaiolo();

$pizza = $pizzaiolo->preparePizzaMargheritaMaison();

$this->assertEquals( ['pate', 'sauce tomate', 'basilic', 'mozzarella'], $pizza->ingredients() ); }

Page 54: Recettes de tests

class PizzaioloTest extends \PHPUnit_Framework_TestCase {

public function test_prepare_une_pizza_margherita_maison() { $pizzaiolo = new Pizzaiolo();

$pizza = $pizzaiolo->preparePizzaMargheritaMaison();

$this->assertEquals( new PizzaMaison(['pate', 'sauce tomate', 'basilic', 'mozzarella']), $pizza ); } }

Page 55: Recettes de tests

public function test_prepare_une_pizza_margherita_maison() { $pizzaiolo = new Pizzaiolo();

$pizza = $pizzaiolo->preparePizzaMargheritaMaison();

$this->assertEquals( new PizzaMaison(['pate', 'sauce tomate', 'basilic', 'mozzarella']), $pizza ); }

Page 56: Recettes de tests

class Pizzaiolo { public function preparePizzaMargheritaMaison() {

$pateAPizza = new PateAPizza();

$this->etaleLaPate($pateAPizza);

$this->enduitDeSauceTomate($pateAPizza);

$this->disposeLaMozzarella($pateAPizza);

$this->placeLeBasilic($pateAPizza);

return $this->cuire($pateAPizza);

} }

Page 57: Recettes de tests

public function test_prepare_une_pizza_margherita_maison() { $pizzaiolo = new Pizzaiolo();

$pizza = $pizzaiolo->preparePizzaMargheritaMaison();

$this->assertEquals( new PizzaMaison(['pate', 'sauce tomate', 'basilic', 'mozzarella']), $pizza ); }

Page 58: Recettes de tests

class PizzaMaison { public function __construct($ingredients) { $this->ingredients = $ingredients; }

public function ingredients() { return $this->ingredients; } }

Page 59: Recettes de tests

class PizzaMaison { public function __construct($ingredients) { $this->ingredients = $ingredients; }

public function ingredients() { return $this->ingredients; } }

Page 60: Recettes de tests

TEST CLASS

PER FIXTURE

Photo by Lou Stejskal on Flickr

Page 61: Recettes de tests

class EndiveTest extends \PHPUnit_Framework_TestCase {

public function test_une_endive_de_base_est_crue() { $endive = new Endive();

$this->assertTrue($endive->crue()); }

public function test_une_endive_de_base_est_bonne() { $endive = new Endive();

$this->assertTrue($endive->bonne()); }

public function test_une_endive_cuite_nest_pas_crue() { $endive = new Endive();

$endive->cuire();

$this->assertFalse($endive->crue()); }

public function test_une_endive_cuite_nest_pas_bonne() { $endive = new Endive();

$endive->cuire();

$this->assertFalse($endive->bonne()); } }

Page 62: Recettes de tests

public function test_une_endive_de_base_est_crue() {

$endive = new Endive();

$this->assertTrue($endive->crue()); }

public function test_une_endive_de_base_est_bonne() {

$endive = new Endive();

$this->assertTrue($endive->bonne()); }

Page 63: Recettes de tests

public function test_une_endive_cuite_nest_pas_crue(){

$endive = new Endive();

$endive->cuire();

$this->assertFalse($endive->crue()); }

public function test_une_endive_cuite_nest_pas_bonne() {

$endive = new Endive();

$endive->cuire();

$this->assertFalse($endive->bonne()); }

Page 64: Recettes de tests

class UneEndiveDeBaseTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); }

public function test_est_crue() { $this->assertTrue($this->endive->crue()); }

public function test_est_bonne() { $this->assertTrue($this->endive->bonne()); } }

Page 65: Recettes de tests

class UneEndiveCuiteTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); $this->endive->cuire(); }

public function test_nest_pas_crue() { $this->assertFalse($this->endive->crue()); }

public function test_nest_pas_bonne() { $this->assertFalse($this->endive->bonne()); } }

Page 66: Recettes de tests

class UneEndiveDeBaseTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); }

public function test_est_crue() { $this->assertTrue($this->endive->crue()); }

public function test_est_bonne() { $this->assertTrue($this->endive->bonne()); } }

Page 67: Recettes de tests

class UneEndiveCuiteTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); $this->endive->cuire(); }

public function test_nest_pas_crue() { $this->assertFalse($this->endive->crue()); }

public function test_nest_pas_bonne() { $this->assertFalse($this->endive->bonne()); } }

Page 68: Recettes de tests

class UneEndiveDeBaseTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); }

public function test_est_crue() { $this->assertTrue($this->endive->crue()); }

public function test_est_bonne() { $this->assertTrue($this->endive->bonne()); } }

Page 69: Recettes de tests

// UneEndiveDeBaseTest.php

public function setUp() { $this->endive = new Endive(); }

// UneEndiveCuiteTest.php

public function setUp() { $this->endive = new Endive(); $this->endive->cuire(); }

Page 70: Recettes de tests

class UneEndiveCrueTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); }

}

Page 71: Recettes de tests

class UneEndiveCrueTest extends \PHPUnit_Framework_TestCase {

public function setUp() { $this->endive = new Endive(); }

}

Page 72: Recettes de tests

class Endive { public static function crue() { return new self(); } }

Page 73: Recettes de tests

class UneEndiveCrueTest extends \PHPUnit_Framework_TestCase {

public function setUp() {

$this->endive = Endive::crue();

}

}

Page 74: Recettes de tests

DON’T MOCK

WHAT YOU

DON’T OWNPhoto by Naomi Hébert on Unsplash

Page 75: Recettes de tests

class GratinTest extends \PHPUnit_Framework_TestCase {

public function test_cuit_au_four_donne_un_gratin_croustillant() {

$gratin = new Gratin();

$realistisk = new Realistisk();

$plat = $gratin->cuireAvec($realistisk, self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); } }

Page 76: Recettes de tests

namespace IKEA;

class Realistisk {

/** * @return Tallrik */ public function laga($tallrik, $varaktighet) {

sleep($varaktighet);

return $this->fårEnVarmTallrik(get_class($tallrik) , $varaktighet); } }

Page 77: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() {

$gratin = new Gratin();

$realistisk = new Realistisk();

$plat = $gratin->cuireAvec($realistisk, self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 78: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() { $gratin = new Gratin();

$tallrik = $this->prophesize(Tallrik::class);

$tallrik->fåTallrik() ->willReturn(new GratinCroustillant());

$realistisk = $this->prophesize(Realistisk::class);

$realistisk->laga($gratin, self::50_MINUTES) ->willReturn(function() use($tallrik){ return $tallrik->reveal(); });

$plat = $gratin->cuireAvec($realistisk->reveal(), self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 79: Recettes de tests

class Realistisk {

public function laga($tallrik, $varaktighet) {

sleep($duree);

return $this->fårEnKallTallrik(get_class($tallrik), $varaktighet); } }

Page 80: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() { $gratin = new Gratin();

$tallrik = $this->prophesize(Tallrik::class);

$tallrik->fåTallrik() ->willReturn(new GratinCroustillant());

$realistisk = $this->prophesize(Realistisk::class);

$realistisk->laga($gratin, self::50_MINUTES) ->willReturn(function() use($tallrik){ return $tallrik->reveal(); });

$plat = $gratin->cuireAvec($realistisk->reveal(), self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 81: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() {

$gratin = new Gratin();

$realistisk = new Realistisk();

$plat = $gratin->cuireAvec($realistisk, self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 82: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() {

$gratin = new Gratin();

$realistisk = new Realistisk();

$plat = $gratin->cuireAvec($realistisk, self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 83: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() { $gratin = new Gratin();

$tallrik = $this->prophesize(Tallrik::class);

$tallrik->fåTallrik() ->willReturn(new GratinCroustillant());

$realistisk = $this->prophesize(Realistisk::class);

$realistisk->laga($gratin, self::50_MINUTES) ->willReturn(function() use($tallrik){ return $tallrik->reveal(); });

$plat = $gratin->cuireAvec($realistisk->reveal(), self::50_MINUTES);

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 84: Recettes de tests

interface Four {

public function cuire($plat, $duree); }

Page 85: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() { $gratin = new Gratin();

$four = $this->prophesize(Four::class);

$four->cuire($gratin, self::50_MINUTES) ->willReturn(new GratinCroustillant());

$plat = $gratin->cuireAvec($four->reveal());

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 86: Recettes de tests

public function test_cuit_au_four_donne_un_gratin_croustillant() { $gratin = new Gratin();

$four = $this->prophesize(Four::class);

$four->cuire($gratin, self::50_MINUTES) ->willReturn(new GratinCroustillant());

$plat = $gratin->cuireAvec($four->reveal());

$this->assertEquals(new GratinCroustillant(), $plat); }

Page 87: Recettes de tests

class LeFourDeLaCuisine implements Four { public function __construct(Realistisk $realistisk) { $this->realistisk = $realistisk; }

public function cuire($plat, $duree) { $tallrik = $this->realistisk->laga($plat, $duree);

return $tallrik->fåTallrik(); } }

Page 88: Recettes de tests

class Gratin { public function cuireAvec(Realistisk $realistisk, $duree) {

$tallrik = $realistisk->laga($this, $duree);

return $tallrik->fåTallrik(); } }

Page 89: Recettes de tests

class Gratin { public function cuireAvec(Four $four, $duree) {

return $four->cuire($this, $duree); } }

Page 90: Recettes de tests

class LeFourDeLaCuisineTest extends PHPUnit_Framework_TestCase { public function test_cuit_un_fromage_de_chevre_en_chevre_chaud() {

$four = new FourDeLaCuisine(new Realistisk());

$plat = $four->cuire(new FromageDeChevre(), self::10_MINUTES);

$this->assertEquals(new ChevreChaud(), $plat); } }

Page 91: Recettes de tests

class LeFourDeLaCuisineTest extends PHPUnit_Framework_TestCase { public function test_cuit_un_fromage_de_chevre_en_chevre_chaud() {

$four = new FourDeLaCuisine(new Realistisk());

$plat = $four->cuire(new FromageDeChevre(), self::10_MINUTES);

$this->assertEquals(new ChevreChaud(), $plat); } }

Page 92: Recettes de tests

NE DEPENDEZ

PAS DU

SYSTEMEPhoto by James Harris on Unsplash

Page 93: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $quiche = new Quiche(new Datetime('2017-10-26'));

$this->assertTrue($quiche->peutEtreConsommee()); }

Page 94: Recettes de tests

class Quiche { public function __construct(Datetime $dateCuisson) { $this->dateCuisson = $dateCuisson; }

public function peutEtreConsommee() { return $this->dateCuisson->modify('+2 day') < new Datetime(); } }

Page 95: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $quiche = new Quiche(new Datetime('2017-10-26'));

$this->assertTrue($quiche->peutEtreConsommee()); }

Page 96: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $quiche = new Quiche(new Datetime('2017-10-26'));

$this->assertTrue($quiche->peutEtreConsommee()); }

Page 97: Recettes de tests

class Horloge { public function maintenant() {

return new Datetime();

} }

Page 98: Recettes de tests

class Quiche { public function __construct(Datetime $cuisineeLe) { $this->cuisineeLe = $cuisineeLe; }

public function peutEtreConsommee(Horloge $horloge) { return $this->cuisineeLe->modify('+2 day') < $horloge->maintenant(); } }

Page 99: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $horloge = $this->prophesize(Horloge::class);

$horloge->maintenant()->willReturn(new Datetime('2017-10-27'));

$quiche = new Quiche(new Datetime('2017-10-26'));

$this->assertTrue($quiche->peutEtreConsommee($horloge)); }

Page 100: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $horloge = $this->prophesize(Horloge::class);

$horloge->maintenant()->willReturn(new Datetime('2017-10-27'));

$quiche = new Quiche(new Datetime('2017-10-26'));

$this->assertTrue($quiche->peutEtreConsommee($horloge)); }

Page 101: Recettes de tests

class Quiche {

public function peutEtreConsommeeLe(Datetime $dateDeConsommation) { return $this->cuisineeLe->modify('+2 day') < $dateDeConsommation; } }

Page 102: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $quiche = new Quiche(new Datetime('2017-10-26'));

$quichePeutEtreConsommee = $quiche ->peutEtreConsommeeLe(new Datetime('2017-10-27'));

$this->assertTrue($quichePeutEtreConsommee); }

Page 103: Recettes de tests

public function test_une_quiche_est_consommable_2_jours_apres_avoir_ete_cuite() { $quiche = new Quiche(new Datetime('2017-10-26'));

$quichePeutEtreConsommee = $quiche ->peutEtreConsommeeLe(new Datetime('2017-10-27'));

$this->assertTrue($quichePeutEtreConsommee); }

Page 104: Recettes de tests

OBJECT

MOTHER

Photo by Eaters Collective on Unsplash

Page 105: Recettes de tests

class PlatDePatesTest extends \PHPUnit_Framework_TestCase {

public function test_est_bon_sil_contient_de_la_viande_du_fromage_et_de_la_sauce() { $platDePates = new PlatDePates([ new Ingredient('fromage', 'parmesan'), new Ingredient('viande', 'lardons'), new Ingredient('sauce', 'creme fraiche'), new Ingredient('legume', 'oignon'), ]);

$this->assertTrue($platDePates->estBon()); } }

Page 106: Recettes de tests

class Ingredient { public function __construct($type, $nom) { $this->type = $type; $this->nom = $nom; } }

Page 107: Recettes de tests

class Ingredient { public function __construct($type, $nom, $DLC) { $this->type = $type; $this->nom = $nom; $this->DLC = $DLC; } }

Page 108: Recettes de tests

public function test_est_bon_sil_contient_de_la_viande_du_fromage_et_de_la_sauce() { $platDePates = new PlatDePates([ new Ingredient('fromage', 'parmesan'), new Ingredient('viande', 'lardons'), new Ingredient('sauce', 'creme fraiche'), new Ingredient('legume', 'oignon'), ]);

$this->assertTrue($platDePates->estBon()); }

Page 109: Recettes de tests

class IngredientMother { public static function viande() { return new Ingredient('viande', 'boeuf hache', new Datetime()); }

public static function legume() { return new Ingredient('legume', 'salsifi', new Datetime()); }

public static function fromage() { return new Ingredient('fromage', 'coulommier', new Datetime()); }

public static function sauce() { return new Ingredient('sauce', 'soja', new Datetime()); } }

Page 110: Recettes de tests

public function test_est_bon_sil_contient_de_la_viande_du_fromage_et_de_la_sauce() { $platDePates = new PlatDePates([ IngredientMother::fromage(), IngredientMother::viande(), IngredientMother::sauce(), IngredientMother::legume(), ]);

$this->assertTrue($platDePates->estBon()); }

Page 111: Recettes de tests

function uneViande() { return IngredientMother::viande(); }

function unLegume() { return IngredientMother::legume(); }

function unFromage() { return IngredientMother::fromage(); }

function uneSauce() { return IngredientMother::sauce(); }

Page 112: Recettes de tests

public function test_est_bon_sil_contient_de_la_viande_du_fromage_et_de_la_sauce() { $platDePates = new PlatDePates([ unFromage(), uneViande(), uneSauce(), unLegume(), ]);

$this->assertTrue($platDePates->estBon()); }

Page 113: Recettes de tests

public function test_est_bon_sil_contient_de_la_viande_du_fromage_et_de_la_sauce() { $platDePates = new PlatDePates([ unFromage(), uneViande(), uneSauce(), unLegume(), ]);

$this->assertTrue($platDePates->estBon()); }

Page 114: Recettes de tests

BUILDERS

Photo by Jorge Zapata on Unsplash

Page 115: Recettes de tests

class PlatDePatesTest extends \PHPUnit_Framework_TestCase {

public function test_nest_pas_consommable_sil_contient_un_ingredient_avec_une_DLC_depassee() { $platDePates = new PlatDePates([ new Ingredient('parmesan', new DateTime('2017-10-30')), new Ingredient('lardons', new DateTime('2017-10-15')), ]);

$this->assertFalse( $platDePates->estConsommableLe(new DateTime('2017-10-20')) ); } }

Page 116: Recettes de tests

class PlatDePatesTest extends \PHPUnit_Framework_TestCase {

public function test_nest_pas_consommable_sil_contient_un_ingredient_avec_une_DLC_depassee() { $platDePates = new PlatDePates([ new Ingredient('parmesan', new DateTime('2017-10-30')), new Ingredient('lardons', new DateTime('2017-10-15')), ]);

$this->assertFalse( $platDePates->estConsommableLe(new DateTime('2017-10-20')) ); } }

Page 117: Recettes de tests

class IngredientBuilder { private $nom;

private $dlc;

public function __construct() {

$this->nom = "pomme de terre";

$this->dlc = new Datetime(); }

public function nomme($nom) { $this->nom = $nom;

return $this; }

public function avecUneDLCLe($dlc) { $this->dlc = $dlc;

return $this; }

public function build() { return new Ingredient($this->nom, $this->dlc); } }

Page 118: Recettes de tests

class IngredientBuilder {

public function build() { return new Ingredient($this->nom, $this->dlc); } }

Page 119: Recettes de tests

class IngredientBuilder { public function nomme($nom) { $this->nom = $nom;

return $this; }

public function avecUneDLCLe($dlc) { $this->dlc = $dlc;

return $this; } }

Page 120: Recettes de tests

class IngredientBuilder { public function nomme($nom) { $this->nom = $nom;

return $this; }

public function avecUneDLCLe($dlc) { $this->dlc = $dlc;

return $this; } }

Page 121: Recettes de tests

class IngredientBuilder { public function __construct() {

$this->nom = "pomme de terre";

$this->dlc = new Datetime(); } }

Page 122: Recettes de tests

function UnIngredient() { return new IngredientBuilder(); }

Page 123: Recettes de tests

UnIngredient() ->nomme('Poisson panné') ->avecUneDLCLe(new Datetime('2018-01-12')) ->build();

Page 124: Recettes de tests

class PlatDePatesTest extends \PHPUnit_Framework_TestCase {

public function test_nest_pas_consommable_sil_contient_un_ingredient_avec_une_DLC_depassee() { $platDePates = new PlatDePates([ UnIngredient()->avecUneDLCLe(new Datetime('2017-10-30'))->build(), UnIngredient()->avecUneDLCLe(new Datetime('2017-10-15'))->build(), ]);

$this->assertFalse($platDePates->estConsommableLe(new DateTime('2017-10-20'))); } }

Page 125: Recettes de tests

DATA PROVIDER

Photo by Julian Andres Carmona Serrato on Unsplash

Page 126: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

public function test_est_vegetarien_sil_ne_contient_que_de_la_salade(){ $plat = new Plat(['salade']); $this->assertTrue($plat->estVegetarien()); }

public function test_est_vegetarien_sil_ne_contient_que_du_fromage() { $plat = new Plat(['fromage']); $this->assertTrue($plat->estVegetarien()); }

public function test_nest_pas_vegetarien_sil_contient_de_la_viande() { $plat = new Plat(['salade', 'viande']); $this->assertFalse($plat->estVegetarien()); } }

Page 127: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

public function test_est_vegetarien_sil_ne_contient_que_de_la_salade(){ $plat = new Plat(['salade']); $this->assertTrue($plat->estVegetarien()); }

public function test_est_vegetarien_sil_ne_contient_que_du_fromage() { $plat = new Plat(['fromage']); $this->assertTrue($plat->estVegetarien()); }

public function test_nest_pas_vegetarien_sil_contient_de_la_viande() { $plat = new Plat(['salade', 'viande']); $this->assertFalse($plat->estVegetarien()); } }

Page 128: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

public function test_est_vegetarien_sil_ne_contient_que_de_la_salade(){ $plat = new Plat(['salade']); $this->assertTrue($plat->estVegetarien()); }

public function test_est_vegetarien_sil_ne_contient_que_du_fromage() { $plat = new Plat(['fromage']); $this->assertTrue($plat->estVegetarien()); }

public function test_nest_pas_vegetarien_sil_contient_de_la_viande() { $plat = new Plat(['salade', 'viande']); $this->assertFalse($plat->estVegetarien()); } }

Page 129: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

public function test_est_vegetarien_sil_ne_contient_que_de_la_salade(){ $plat = new Plat(['salade']); $this->assertTrue($plat->estVegetarien()); }

public function test_est_vegetarien_sil_ne_contient_que_du_fromage() { $plat = new Plat(['fromage']); $this->assertTrue($plat->estVegetarien()); }

public function test_nest_pas_vegetarien_sil_contient_de_la_viande() { $plat = new Plat(['salade', 'viande']); $this->assertFalse($plat->estVegetarien()); } }

Page 130: Recettes de tests

const EST_VEGETARIEN = true; const NEST_PAS_VEGETARIEN = false;

Page 131: Recettes de tests

public function plats() { return [ 'Un plat qui ne contient que la salade est vegetarien' => [ new Plat(['salade']), self::EST_VEGETARIEN ], 'Un plat avec du fromage est vegetarien' => [ new Plat(['fromage']), self::EST_VEGETARIEN ], 'Un plat avec de la viande n\'est pas vegetarien' => [ new Plat(['viande']), self::NEST_PAS_VEGETARIEN ], ]; }

Page 132: Recettes de tests

public function plats() { return [ 'Un plat qui ne contient que la salade est vegetarien' => [ new Plat(['salade']), self::EST_VEGETARIEN ], 'Un plat avec du fromage est vegetarien' => [ new Plat(['fromage']), self::EST_VEGETARIEN ], 'Un plat avec de la viande n\'est pas vegetarien' => [ new Plat(['viande']), self::NEST_PAS_VEGETARIEN ], ]; }

Page 133: Recettes de tests

public function plats() { return [ 'Un plat qui ne contient que la salade est vegetarien' => [ new Plat(['salade']), self::EST_VEGETARIEN ], 'Un plat avec du fromage est vegetarien' => [ new Plat(['fromage']), self::EST_VEGETARIEN ], 'Un plat avec de la viande n\'est pas vegetarien' => [ new Plat(['viande']), self::NEST_PAS_VEGETARIEN ], ]; }

Page 134: Recettes de tests

public function plats() { return [ 'Un plat qui ne contient que la salade est vegetarien' => [ new Plat(['salade']), self::EST_VEGETARIEN ], 'Un plat avec du fromage est vegetarien' => [ new Plat(['fromage']), self::EST_VEGETARIEN ], 'Un plat avec de la viande n\'est pas vegetarien' => [ new Plat(['viande']), self::NEST_PAS_VEGETARIEN ], ]; }

Page 135: Recettes de tests

/** * @dataProvider plats */ public function test_est_vegetarien_sil_ne_contient_que_des_ingredients_vegetariens ($plat, $estVegetarien) { $this->assertEquals($estVegetarien, $plat->estVegetarien()); }

Page 136: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

public function test_est_vegetarien_sil_ne_contient_que_de_la_salade(){ $plat = new Plat(['salade']); $this->assertTrue($plat->estVegetarien()); }

public function test_est_vegetarien_sil_ne_contient_que_du_fromage() { $plat = new Plat(['fromage']); $this->assertTrue($plat->estVegetarien()); }

public function test_nest_pas_vegetarien_sil_contient_de_la_viande() { $plat = new Plat(['salade', 'viande']); $this->assertFalse($plat->estVegetarien()); } }

Page 137: Recettes de tests

class PlatTest extends PHPUnit_Framework_TestCase {

const EST_VEGETARIEN = true; const NEST_PAS_VEGETARIEN = false;

/** * @dataProvider plats */ public function test_est_vegetarien_sil_ne_contient_que_des_ingredients_vegetariens ($plat, $estVegetarien) { $this->assertEquals($estVegetarien, $plat->estVegetarien()); }

public function plats() { return [ 'Un plat qui ne contient que la salade est vegetarien' => [ new Plat(['salade']), self::EST_VEGETARIEN ], 'Un plat avec du fromage est vegetarien' => [ new Plat(['fromage']), self::EST_VEGETARIEN ], 'Un plat avec de la viande n\'est pas vegetarien' => [ new Plat(['viande']), self::NEST_PAS_VEGETARIEN ], ]; } }

Page 138: Recettes de tests

Assurez vous que vous testez ce que vous

voulez tester.Photo by rawpixel.com on Unsplash

Page 139: Recettes de tests

Exprimez les règles métiers dans les noms

des tests.Photo by rawpixel.com on Unsplash

Page 140: Recettes de tests

Utilisez le même vocabulaire dans le nom du test et dans

l’exemple.Photo by rawpixel.com on Unsplash

Page 141: Recettes de tests

Ne couplez pas le test à

l’implémentation.Photo by rawpixel.com on Unsplash

Page 142: Recettes de tests

Écoutez les tests pour guider l’implémentation.

Photo by rawpixel.com on Unsplash

Page 143: Recettes de tests

documentation tests design

Photo by rawpixel.com on Unsplash

Page 144: Recettes de tests

@SelrahcD

C’est tout !

documentation tests design

Photo by rawpixel.com on Unsplash