SlideShare une entreprise Scribd logo
1  sur  18
Test Double
UN’INTRODUZIONE DI
CARMELANTONIO ZOLFO
TDD, un breve riepilogo
 Test Driven Development: metodologia di sviluppo

software che antepone la stesura di test allo sviluppo
reale delle funzionalità.
 Come?
Scrivo test che
fallisce e lo
eseguo

Rifattorizzo il
codice

Scrivo codice che
soddisfi il test
TDD, un breve riepilogo
 Perché scrivere prima il test?
 Previene/fa regredire/mette in luce bug;
 Assicura copertura del codice;
 Permette di comprendere finalità e modalità della

funzione testata;
 Permette refactoring, sperimentazioni e
cambiamenti nel codice preesistente
TDD, un breve riepilogo
 Come deve essere un buon test?
 Automatizzato;
 Isolato;
 Ripetibile;
 Facile da scrivere, leggere => facile da mantenere
Fasi di un test

 SUT: system under test (classe, oggetto o metodo testato)
Fasi di un test

VS metodo scientifico

 Ipotesi
 Tesi
 Dimostrazione
Test classico 1/2
class OrderTest extends PHPUnit_Framework_TestCase {
const DISARONNO = ‘Amaretto di Saronno’;
const BACARDI = ‘Bacardi Superior’;
private $warehouse;
public function setUp()
{
$this->warehouse = new Warehouse();
$this->warehouse->add(self::DISARONNO, 50);
$this->warehouse->add(self::BACARDI, 25);
}
public function testFillingRemovesInventoryIfInStock()
{
$order = new Order(self::DISARONNO, 50); //fase setup II parte
$order->fill($this->warehouse); //fase exercise
$this->assertTrue($order->isFilled()); //fase verification
$this->assertCount(0, $this->warehouse->getInventory(self::DISARONNO));
}
Test classico 2/2
public function testFillingRemovesInventoryIfInStock()
{
$order = new Order(self::DISARONNO, 51);
$order->fill($this->warehouse);
$this->assertFalse($order->isFilled());
$this->assertCount(50, $this->warehouse->getInventory(self::DISARONNO));
}
}
Test Double
Test Double, quando entrano in gioco?
Indirect output

Indirect input

 DOC: depended on component
Test Double, quando entrano in gioco?
Indirect output

Indirect input

 Il Test Double sostituisce il DOC in fase di test
Test Double, varianti
 Dummy Object: un placeholder passato al SUT ma





mai utilizzato
Test Stub: sostituisce un DOC per avere un punto di
controllo sugli indirect input necessari al SUT
Test Spy: offre un punto di osservazione sugli
indirect input necessari al SUT
Mock Object: costituisce un punto di osservazione
sugli indirect output erogati dal SUT
Fake Object: sostituisce le funzionalità di un DOC
con una implementazione semplificata senza fornire
controllo sugli indirect input/output del SUT
Test Double – Mock 1/2
class OrderTest extends PHPUnit_Framework_TestCase
{
const DISARONNO = ‘Amaretto di Saronno’;
public function testFillingRemovesInventoryIfInStock()
{
//setup - dati
$order = new Order(self::DISARONNO, 50);
$warehouseMock = $this->getMock('Warehouse', array('hasInventory', 'remove'));

$warehouseMock->expects($this->at(0)) //setup - expectations
->method('hasInventory')
->with($this->equalTo(self::DISARONNO), $this->equalTo(50)) //indirect output
->will($this->returnValue(true)); //indirect input
$order->fill($warehouseMock); //exercise
Test Double – Mock 2/2
$this->assertTrue($order->isFilled()); //verify
}
public function testFillingDoesNotRemoveIfNotEnoughInStock() {
$order = new Order(self::DISARONNO, 51);
$warehouseMock = $this->getMock('Warehouse', array('hasInventory'));
$warehouseMock->expects($this->once())
->method("hasInventory”)
->will($this->returnValue(false));
$order->fill($warehouseMock);

$this->assertFalse($order->isFilled());
}
}
Test Double – Stub 1/2
interface MailService {
public function send (Message $msg);
}
class MailServiceStub implements MailService {
private $messages = array();
public function send (Message $msg)
{
$this->messages[] = $msg;
}
public function numberSent()
{
return count($this->messages);
}
}
Test Double – Stub 2/2
class OrderTest extends PHPUnit_Framework_TestCase
{
…
public function testOrderSendsMailIfUnfilled() {
$order = new Order(self::DISARONNO, 51);
...
$mailServiceStub = new MailServiceStub();
$order->setMailer($mailServiceStub);
$order->fill($warehouse);
$this->assertEquals(1, $mailer->numberSent());
}
}
Test Double – Stub vs Mock as Spy
class OrderTest extends PHPUnit_Framework_TestCase
{
…
public function testOrderSendsMailIfUnfilled() {
$order = new Order(self::DISARONNO, 51);
…
$mailServiceMock = $this->getMock('MailService', array('send'));

$order->setMailer($mailServiceMock);
$mailServiceMock->expects($this->once())
->method("send");

$order->fill($warehouse);
}
}
Credits & Contacts
 PHPUnit – manuale - http://phpunit.de/manual/
 xUnit Patterns – Test Double, Gerard Meszaros -

http://xunitpatterns.com/Test%20Double.html
 Mocks arent Stubs, Martin Fowler -

http://martinfowler.com/articles/mocksArentStubs.html

Test Double, un’introduzione
di Carmelantonio Zolfo
carmelantonio.zolfo@gmail.com

Contenu connexe

Tendances

Tendances (13)

Applicazioni native in java
Applicazioni native in javaApplicazioni native in java
Applicazioni native in java
 
Dispensa di PL-SQL
Dispensa di PL-SQLDispensa di PL-SQL
Dispensa di PL-SQL
 
Java 8
Java 8Java 8
Java 8
 
Odoo connector PyCon 2015
Odoo connector  PyCon 2015Odoo connector  PyCon 2015
Odoo connector PyCon 2015
 
Lezione 12 (28 marzo 2012)
Lezione 12 (28 marzo 2012)Lezione 12 (28 marzo 2012)
Lezione 12 (28 marzo 2012)
 
Assembly and Reverse Engineering
Assembly and Reverse EngineeringAssembly and Reverse Engineering
Assembly and Reverse Engineering
 
Costrutti linguistici
Costrutti linguisticiCostrutti linguistici
Costrutti linguistici
 
Unit Test di Gabriele Seroni
Unit Test di Gabriele SeroniUnit Test di Gabriele Seroni
Unit Test di Gabriele Seroni
 
Lezione 12 (28 marzo 2012)
Lezione 12 (28 marzo 2012)Lezione 12 (28 marzo 2012)
Lezione 12 (28 marzo 2012)
 
Laboratorio Programmazione: Funzioni
Laboratorio Programmazione: FunzioniLaboratorio Programmazione: Funzioni
Laboratorio Programmazione: Funzioni
 
PHP
PHPPHP
PHP
 
2011.02.19 Introducing F#
2011.02.19 Introducing F#2011.02.19 Introducing F#
2011.02.19 Introducing F#
 
Gcc & Make
Gcc & MakeGcc & Make
Gcc & Make
 

Similaire à Test double - un'introduzione (PHP)

TDD in WordPress
TDD in WordPressTDD in WordPress
TDD in WordPresslucatume
 
Introduzione al Test Driven Development
Introduzione al Test Driven DevelopmentIntroduzione al Test Driven Development
Introduzione al Test Driven DevelopmentEnnio Masi
 
Mocking Objects Practices
Mocking Objects PracticesMocking Objects Practices
Mocking Objects PracticesGrUSP
 
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...Alessandro Alpi
 
Software Testing & Test Driven Development
Software Testing & Test Driven DevelopmentSoftware Testing & Test Driven Development
Software Testing & Test Driven DevelopmentSergio Santoro
 
Sql Injection: attacchi e rimedi
Sql Injection: attacchi e rimediSql Injection: attacchi e rimedi
Sql Injection: attacchi e rimediDavide Micale
 
Baby Steps TripServiceKata
Baby Steps TripServiceKataBaby Steps TripServiceKata
Baby Steps TripServiceKataAndrea Francia
 
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...Davide Cerbo
 
PASS Virtual Chapter - SQL Server Continuous Integration
PASS Virtual Chapter - SQL Server Continuous IntegrationPASS Virtual Chapter - SQL Server Continuous Integration
PASS Virtual Chapter - SQL Server Continuous IntegrationAlessandro Alpi
 
Introduzione a Node.js
Introduzione a Node.jsIntroduzione a Node.js
Introduzione a Node.jsMichele Capra
 
CONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVERCONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVERDotNetCampus
 
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerAlessandro Alpi
 

Similaire à Test double - un'introduzione (PHP) (20)

Unit testing 101
Unit testing 101Unit testing 101
Unit testing 101
 
TDD in WordPress
TDD in WordPressTDD in WordPress
TDD in WordPress
 
Introduzione al Test Driven Development
Introduzione al Test Driven DevelopmentIntroduzione al Test Driven Development
Introduzione al Test Driven Development
 
Testing
TestingTesting
Testing
 
Il testing con zend framework
Il testing con zend frameworkIl testing con zend framework
Il testing con zend framework
 
Il testing con zend framework
Il testing con zend frameworkIl testing con zend framework
Il testing con zend framework
 
introduzione a symfony 2
introduzione a symfony 2 introduzione a symfony 2
introduzione a symfony 2
 
Mocking Objects Practices
Mocking Objects PracticesMocking Objects Practices
Mocking Objects Practices
 
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
DevOpsHeroes 2016 - Realizzare Continouous Integration con SQL Server e Visua...
 
Software Testing & Test Driven Development
Software Testing & Test Driven DevelopmentSoftware Testing & Test Driven Development
Software Testing & Test Driven Development
 
Sql Injection: attacchi e rimedi
Sql Injection: attacchi e rimediSql Injection: attacchi e rimedi
Sql Injection: attacchi e rimedi
 
Baby Steps TripServiceKata
Baby Steps TripServiceKataBaby Steps TripServiceKata
Baby Steps TripServiceKata
 
Spring Intro
Spring IntroSpring Intro
Spring Intro
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
The Hitchhiker's Guide to testable code: semplici regole per scrivere codice ...
 
PASS Virtual Chapter - SQL Server Continuous Integration
PASS Virtual Chapter - SQL Server Continuous IntegrationPASS Virtual Chapter - SQL Server Continuous Integration
PASS Virtual Chapter - SQL Server Continuous Integration
 
Introduzione a node.js
Introduzione a node.jsIntroduzione a node.js
Introduzione a node.js
 
Introduzione a Node.js
Introduzione a Node.jsIntroduzione a Node.js
Introduzione a Node.js
 
CONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVERCONTINUOUS INTEGRATION CON SQL SERVER
CONTINUOUS INTEGRATION CON SQL SERVER
 
DotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql ServerDotNetCampus - Continuous Integration con Sql Server
DotNetCampus - Continuous Integration con Sql Server
 

Test double - un'introduzione (PHP)

  • 2. TDD, un breve riepilogo  Test Driven Development: metodologia di sviluppo software che antepone la stesura di test allo sviluppo reale delle funzionalità.  Come? Scrivo test che fallisce e lo eseguo Rifattorizzo il codice Scrivo codice che soddisfi il test
  • 3. TDD, un breve riepilogo  Perché scrivere prima il test?  Previene/fa regredire/mette in luce bug;  Assicura copertura del codice;  Permette di comprendere finalità e modalità della funzione testata;  Permette refactoring, sperimentazioni e cambiamenti nel codice preesistente
  • 4. TDD, un breve riepilogo  Come deve essere un buon test?  Automatizzato;  Isolato;  Ripetibile;  Facile da scrivere, leggere => facile da mantenere
  • 5. Fasi di un test  SUT: system under test (classe, oggetto o metodo testato)
  • 6. Fasi di un test VS metodo scientifico  Ipotesi  Tesi  Dimostrazione
  • 7. Test classico 1/2 class OrderTest extends PHPUnit_Framework_TestCase { const DISARONNO = ‘Amaretto di Saronno’; const BACARDI = ‘Bacardi Superior’; private $warehouse; public function setUp() { $this->warehouse = new Warehouse(); $this->warehouse->add(self::DISARONNO, 50); $this->warehouse->add(self::BACARDI, 25); } public function testFillingRemovesInventoryIfInStock() { $order = new Order(self::DISARONNO, 50); //fase setup II parte $order->fill($this->warehouse); //fase exercise $this->assertTrue($order->isFilled()); //fase verification $this->assertCount(0, $this->warehouse->getInventory(self::DISARONNO)); }
  • 8. Test classico 2/2 public function testFillingRemovesInventoryIfInStock() { $order = new Order(self::DISARONNO, 51); $order->fill($this->warehouse); $this->assertFalse($order->isFilled()); $this->assertCount(50, $this->warehouse->getInventory(self::DISARONNO)); } }
  • 10. Test Double, quando entrano in gioco? Indirect output Indirect input  DOC: depended on component
  • 11. Test Double, quando entrano in gioco? Indirect output Indirect input  Il Test Double sostituisce il DOC in fase di test
  • 12. Test Double, varianti  Dummy Object: un placeholder passato al SUT ma     mai utilizzato Test Stub: sostituisce un DOC per avere un punto di controllo sugli indirect input necessari al SUT Test Spy: offre un punto di osservazione sugli indirect input necessari al SUT Mock Object: costituisce un punto di osservazione sugli indirect output erogati dal SUT Fake Object: sostituisce le funzionalità di un DOC con una implementazione semplificata senza fornire controllo sugli indirect input/output del SUT
  • 13. Test Double – Mock 1/2 class OrderTest extends PHPUnit_Framework_TestCase { const DISARONNO = ‘Amaretto di Saronno’; public function testFillingRemovesInventoryIfInStock() { //setup - dati $order = new Order(self::DISARONNO, 50); $warehouseMock = $this->getMock('Warehouse', array('hasInventory', 'remove')); $warehouseMock->expects($this->at(0)) //setup - expectations ->method('hasInventory') ->with($this->equalTo(self::DISARONNO), $this->equalTo(50)) //indirect output ->will($this->returnValue(true)); //indirect input $order->fill($warehouseMock); //exercise
  • 14. Test Double – Mock 2/2 $this->assertTrue($order->isFilled()); //verify } public function testFillingDoesNotRemoveIfNotEnoughInStock() { $order = new Order(self::DISARONNO, 51); $warehouseMock = $this->getMock('Warehouse', array('hasInventory')); $warehouseMock->expects($this->once()) ->method("hasInventory”) ->will($this->returnValue(false)); $order->fill($warehouseMock); $this->assertFalse($order->isFilled()); } }
  • 15. Test Double – Stub 1/2 interface MailService { public function send (Message $msg); } class MailServiceStub implements MailService { private $messages = array(); public function send (Message $msg) { $this->messages[] = $msg; } public function numberSent() { return count($this->messages); } }
  • 16. Test Double – Stub 2/2 class OrderTest extends PHPUnit_Framework_TestCase { … public function testOrderSendsMailIfUnfilled() { $order = new Order(self::DISARONNO, 51); ... $mailServiceStub = new MailServiceStub(); $order->setMailer($mailServiceStub); $order->fill($warehouse); $this->assertEquals(1, $mailer->numberSent()); } }
  • 17. Test Double – Stub vs Mock as Spy class OrderTest extends PHPUnit_Framework_TestCase { … public function testOrderSendsMailIfUnfilled() { $order = new Order(self::DISARONNO, 51); … $mailServiceMock = $this->getMock('MailService', array('send')); $order->setMailer($mailServiceMock); $mailServiceMock->expects($this->once()) ->method("send"); $order->fill($warehouse); } }
  • 18. Credits & Contacts  PHPUnit – manuale - http://phpunit.de/manual/  xUnit Patterns – Test Double, Gerard Meszaros - http://xunitpatterns.com/Test%20Double.html  Mocks arent Stubs, Martin Fowler - http://martinfowler.com/articles/mocksArentStubs.html Test Double, un’introduzione di Carmelantonio Zolfo carmelantonio.zolfo@gmail.com