SlideShare a Scribd company logo
1 of 52
Practical Approach 
for testing your 
software with PHPUnit 
Mario Bittencourt
Agenda 
 Current situation 
 PHPUnit as part of the solution 
 Best Practices
Current situation
Complexity, dependencies 
and pace over time
Software Development 
Life Cycle
Testing 
 Tedious 
 Can only cover a small subset of the use cases 
 Takes a lot of time 
 Change the code to test it
Automation is key 
Goal is to create tests that can be executed 
automatically to verify that the expected behaviour 
is met
PHPUnit as part 
of the solution
Example 
class Account 
{ 
protected $balance; 
public function __construct($initialAmount) 
{ 
$this->balance = $initialAmount; 
} 
public function getBalance() 
{ 
return $this->balance; 
} 
public function deposit($amount) 
{ 
$this->balance += $amount; 
} 
}
Unit Test 
class AccountTest extends PHpUnit_Framework_TestCase 
{ 
public function testDepositIncreasesBalance() 
{ 
$account = new Account(10); 
$account->deposit(1); 
$this->assertEquals(11, $account->getBalance()); 
} 
}
Unit Test 
PHPUnit 4.3.1 by Sebastian Bergmann. 
Account 
[x] Deposit increases balance
Best Practices
Give meaningful names to your 
tests 
public function testDeposit() 
{ 
$account = new Account(10); 
$account->deposit(1); 
$this->assertEquals( 
11, 
$account->getBalance() 
); 
} 
 DON’T
Give meaningful names to your 
tests 
PHPUnit 4.3.1 by Sebastian Bergmann. 
Account 
[ ] Deposit
Give meaningful names to your 
tests 
public function testDepositIncreaseBalance() 
{ 
$account = new Account(10); 
$account->deposit(1); 
$this->assertEquals( 
11, 
$account->getBalance() 
); 
}
Use the most specific 
assertion available 
public function testDepositIncreasesBalance() 
{ 
$account = new Account(10); 
$account->deposit(10); 
$this->assertGreaterThan( 
10,$account->getBalance() 
); 
} 
 DON’T
Use the most specific 
assertion available 
public function testDepositIncreasesBalance() 
{ 
$account = new Account(10); 
$account->deposit(10); 
$this->assertEquals(20, $account->getBalance()); 
}
Use the most specific 
assertion available 
public function deposit($amount) 
{ 
$this->balance += $amount; 
if ($amount >= 10) { 
$this->balance += 1; 
} 
return true; 
}
Use the most specific 
assertion available 
There was 1 failure: 
1) AccountTest::testDepositIncreasesBalance 
Failed asserting that 21 matches expected 20. 
AccountTest.php:14
Don’t forget about protected 
methods 
class Account 
{ 
public function deposit($amount) 
{ 
if ($this->validateAmount($amount)) { 
$this->balance += $amount; 
} else { 
throw new Exception('Invalid amount'); 
} 
} 
}
Don't forget about 
your protected methods 
protected function validateAmount($amount) 
{ 
if ($amount < 0) { 
return false; 
} else { 
return true; 
} 
}
Don't forget about 
your protected methods 
public function testValidateAmountWithNegativeIsFalse() 
{ 
$account = new Account(10); 
$this->assertFalse($account->validateAmount(-1)); 
} 
Fatal error: Call to protected method Account::validateAmount()
Don't forget about 
your protected methods 
public function testValidateAmountWithNegativeIsFalse() 
{ 
$account = new Account(10); 
$reflection = new ReflectionObject($account); 
$method = $reflection->getMethod('validateAmount'); 
$method->setAccessible(true); 
$this->assertFalse( 
$method->invokeArgs($account, array(-1)) 
); 
}
Don't forget about 
your protected methods 
PHPUnit 4.3.1 by Sebastian Bergmann. 
Account 
[x] Deposit increases balance 
[x] Validate amount with negative is false
Test just one thing at a time 
public function deposit($amount) 
{ 
if ($amount == 0) { 
return false; 
} 
$this->balance += $amount; 
return true; 
}
Test just one thing at a time 
public function testDepositIncreasesBalance() 
{ 
$account = new Account(10); 
$this->assertTrue($account->deposit(1)); 
$this->assertEquals(11, $account->getBalance()); 
$this->assertFalse($account->deposit(0)); 
}
Test just one thing at a time 
PHPUnit 4.3.1 by Sebastian Bergmann. 
. 
Time: 35 ms, Memory: 3.00Mb 
OK (1 test, 3 assertions)
Test just one thing at a time 
public function deposit($amount) 
{ 
if ($amount < 0) { 
NEW CRITERIA 
return false; 
} 
$this->balance += $amount; 
return true; 
}
Test just one thing at a time 
PHPUnit 4.3.1 by Sebastian Bergmann. 
There was 1 failure: 
1) AccountTest::testDepositIncreasesBalance 
Failed asserting that true is false. 
AccountTest.php:15 
FAILURES! 
Tests: 1, Assertions: 3, Failures: 1.
Test just one thing at a time 
public function testDepositIncreasesBalance() 
{ 
$account = new Account(10); 
$this->assertTrue($account->deposit(1)); 
$this->assertEquals(11, $account->getBalance()); 
} 
public function 
testDepositWithNegativeShouldReturnFalse() 
{ 
$account = new Account(10); 
$this->assertFalse($account->deposit(-1)); 
}
Test just one thing at a time 
PHPUnit 4.3.1 by Sebastian Bergmann. 
.. 
Time: 49 ms, Memory: 3.00Mb 
OK (2 tests, 3 assertions)
Use Data Providers for 
repetitive tests 
class Score 
{ 
protected $score; 
public function update($balance, $numberCc, 
$amountInLoans) 
{ 
// do something ... 
return $newScore; 
} 
}
Use Data Providers for 
repetitive tests 
class ScoreTest extends PHpUnit_Framework_TestCase 
{ 
public function testScoreSomething1() 
{ 
$score = new Score(10); 
$this->assertEquals(300, $score->update(100, 0, 1)); 
} 
public function testScoreSomething2() 
{ 
$score = new Score(10); 
$this->assertEquals(99, $score->update(100, 1, 2)); 
} 
}
Use Data Providers for 
repetitive tests 
/** 
* @dataProvider scoreProvider 
*/ 
public function testScore($balance, $numberCc, 
$amountInLoans, $expectedScore) 
{ 
$score = new Score(10); 
$this->assertEquals( 
$expectedScore, 
$score->update($balance, $numberCc, $amountInLoans) 
); 
}
Use Data Providers for 
repetitive tests 
public function scoreProvider() 
{ 
return array( 
array(100, 0, 1, 300), 
array(100, 1, 2, 99), 
); 
}
Use Data Providers for 
repetitive tests 
PHPUnit 4.3.1 by Sebastian Bergmann. 
.. 
Time: 25 ms, Memory: 3.00Mb 
OK (2 tests, 2 assertions)
Isolate your test 
public function wire($amount, SwiftInterface $targetBank) 
{ 
if ($targetBank->transfer($amount)) { 
$this->balance -= $amount; 
return true; 
} else { 
return false; 
} 
}
Isolate your test 
class Hsbc implements SwiftInterface { 
public function transfer($amount) 
{ 
// slow method 
} 
}
Isolate your test 
public function 
testWireTransferShouldReturnTrueIfSuccessful() 
{ 
$account = new Account(10); 
$bank = new Hsbc(); 
$this->assertTrue($account->wire(5, $bank)); 
}
Isolate your test 
public function 
testWireTransferShouldReturnFalseIfFailed() 
{ 
// how to fail? 
$account = new Account(10); 
$bank = new Hsbc(); 
$this->assertFalse($account->wire(5, $bank)); 
}
Isolate your test 
public function 
testWireTransferShouldReturnTrueIfSuccessful() 
{ 
$account = new Account(10); 
$bank = $this->getMock(‘Hsbc'); 
$bank->expects($this->any()) 
->method('transfer') 
->will($this->returnValue(true)); 
$this->assertTrue($account->wire(5, $bank)); 
}
Isolate your test 
public function 
testWireTransferShouldReturnFalseIfFailed() 
{ 
$account = new Account(10); 
$bank = $this->getMock('Hsbc'); 
$bank->expects($this->any()) 
->method('transfer') 
->will($this->returnValue(false)); 
$this->assertFalse($account->wire(5, $bank)); 
}
Specify what you are testing 
with @covers 
 Use --coverage-html to generate the code 
coverage report of your code
Specify what you are testing 
with @covers
Specify what you are testing 
with @covers 
class Exchange { 
public function convert($amountUsd, $targetCurrency) 
{ 
// Do some conversion 
} 
}
Specify what you are testing 
with @covers 
public function convertBalance($targetCurrency) 
{ 
$exchange = new Exchange(); 
return $exchange->convert($this->balance, $targetCurrency); 
}
Specify what you are testing 
with @covers 
public function testConvertBalance() 
{ 
$account = new Account(10); 
$this->assertLessThan( 
10, $account->convertBalance('GBP') 
); 
}
Specify what you are testing 
with @covers
Specify what you are testing 
with @covers
Specify what you are testing 
with @covers 
/** 
* @covers Account::convertBalance 
*/ 
public function testConvertBalance() 
{ 
… 
}
Specify what you are testing 
with @covers
That is all folks! 
Contacts 
 Twitter -@bicatu 
 Email – mbneto@gmail.com 
 https://joind.in/12279 
 http://slidesha.re/1xtcT4y

More Related Content

What's hot

What's hot (20)

PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection Smells
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Let it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTPLet it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTP
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Func up your code
Func up your codeFunc up your code
Func up your code
 
CQRS + Event Sourcing in PHP
CQRS + Event Sourcing in PHPCQRS + Event Sourcing in PHP
CQRS + Event Sourcing in PHP
 
Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Dutch php a short tale about state machine
Dutch php   a short tale about state machineDutch php   a short tale about state machine
Dutch php a short tale about state machine
 
Modernising Legacy Code
Modernising Legacy CodeModernising Legacy Code
Modernising Legacy Code
 
What's new with PHP7
What's new with PHP7What's new with PHP7
What's new with PHP7
 
Apex 5 plugins for everyone version 2018
Apex 5 plugins for everyone   version 2018Apex 5 plugins for everyone   version 2018
Apex 5 plugins for everyone version 2018
 
Mutation testing in php with Humbug
Mutation testing in php with HumbugMutation testing in php with Humbug
Mutation testing in php with Humbug
 
Symfony World - Symfony components and design patterns
Symfony World - Symfony components and design patternsSymfony World - Symfony components and design patterns
Symfony World - Symfony components and design patterns
 
Test driven development_for_php
Test driven development_for_phpTest driven development_for_php
Test driven development_for_php
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to Production
 
PLSQL.docx
PLSQL.docxPLSQL.docx
PLSQL.docx
 

Viewers also liked

software testing for beginners
software testing for beginnerssoftware testing for beginners
software testing for beginners
Bharathi Ashok
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
nickokiss
 

Viewers also liked (11)

Apex Testing Best Practices
Apex Testing Best PracticesApex Testing Best Practices
Apex Testing Best Practices
 
software testing for beginners
software testing for beginnerssoftware testing for beginners
software testing for beginners
 
software testing methodologies
software testing methodologiessoftware testing methodologies
software testing methodologies
 
Testing methodology
Testing methodologyTesting methodology
Testing methodology
 
Apex Testing and Best Practices
Apex Testing and Best PracticesApex Testing and Best Practices
Apex Testing and Best Practices
 
Manual testing
Manual testingManual testing
Manual testing
 
Test Automation Best Practices (with SOA test approach)
Test Automation Best Practices (with SOA test approach)Test Automation Best Practices (with SOA test approach)
Test Automation Best Practices (with SOA test approach)
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
 
Software Testing Process & Trend
Software Testing Process & TrendSoftware Testing Process & Trend
Software Testing Process & Trend
 
Manual testing ppt
Manual testing pptManual testing ppt
Manual testing ppt
 
Software testing ppt
Software testing pptSoftware testing ppt
Software testing ppt
 

Similar to Practical approach for testing your software with php unit

Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method Declarations
ICSM 2010
 
Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
Jace Ju
 
New Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian BergmannNew Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian Bergmann
dpc
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 
Account.h Definition of Account class. #ifndef ACCOUNT_H #d.pdf
Account.h  Definition of Account class. #ifndef ACCOUNT_H #d.pdfAccount.h  Definition of Account class. #ifndef ACCOUNT_H #d.pdf
Account.h Definition of Account class. #ifndef ACCOUNT_H #d.pdf
anujmkt
 

Similar to Practical approach for testing your software with php unit (20)

13 PHPUnit #burningkeyboards
13 PHPUnit #burningkeyboards13 PHPUnit #burningkeyboards
13 PHPUnit #burningkeyboards
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09
 
Introduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnitIntroduction to Unit Testing with PHPUnit
Introduction to Unit Testing with PHPUnit
 
Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.Symfony (Unit, Functional) Testing.
Symfony (Unit, Functional) Testing.
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Clean code in unit testing
Clean code in unit testingClean code in unit testing
Clean code in unit testing
 
Automatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method DeclarationsAutomatically Repairing Test Cases for Evolving Method Declarations
Automatically Repairing Test Cases for Evolving Method Declarations
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
New Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian BergmannNew Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian Bergmann
 
Php unit (eng)
Php unit (eng)Php unit (eng)
Php unit (eng)
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Php tests tips
Php tests tipsPhp tests tips
Php tests tips
 
TDD, BDD and mocks
TDD, BDD and mocksTDD, BDD and mocks
TDD, BDD and mocks
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Account.h Definition of Account class. #ifndef ACCOUNT_H #d.pdf
Account.h  Definition of Account class. #ifndef ACCOUNT_H #d.pdfAccount.h  Definition of Account class. #ifndef ACCOUNT_H #d.pdf
Account.h Definition of Account class. #ifndef ACCOUNT_H #d.pdf
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 

Recently uploaded

Recently uploaded (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 

Practical approach for testing your software with php unit

  • 1. Practical Approach for testing your software with PHPUnit Mario Bittencourt
  • 2. Agenda  Current situation  PHPUnit as part of the solution  Best Practices
  • 6. Testing  Tedious  Can only cover a small subset of the use cases  Takes a lot of time  Change the code to test it
  • 7. Automation is key Goal is to create tests that can be executed automatically to verify that the expected behaviour is met
  • 8. PHPUnit as part of the solution
  • 9. Example class Account { protected $balance; public function __construct($initialAmount) { $this->balance = $initialAmount; } public function getBalance() { return $this->balance; } public function deposit($amount) { $this->balance += $amount; } }
  • 10. Unit Test class AccountTest extends PHpUnit_Framework_TestCase { public function testDepositIncreasesBalance() { $account = new Account(10); $account->deposit(1); $this->assertEquals(11, $account->getBalance()); } }
  • 11. Unit Test PHPUnit 4.3.1 by Sebastian Bergmann. Account [x] Deposit increases balance
  • 13. Give meaningful names to your tests public function testDeposit() { $account = new Account(10); $account->deposit(1); $this->assertEquals( 11, $account->getBalance() ); }  DON’T
  • 14. Give meaningful names to your tests PHPUnit 4.3.1 by Sebastian Bergmann. Account [ ] Deposit
  • 15. Give meaningful names to your tests public function testDepositIncreaseBalance() { $account = new Account(10); $account->deposit(1); $this->assertEquals( 11, $account->getBalance() ); }
  • 16. Use the most specific assertion available public function testDepositIncreasesBalance() { $account = new Account(10); $account->deposit(10); $this->assertGreaterThan( 10,$account->getBalance() ); }  DON’T
  • 17. Use the most specific assertion available public function testDepositIncreasesBalance() { $account = new Account(10); $account->deposit(10); $this->assertEquals(20, $account->getBalance()); }
  • 18. Use the most specific assertion available public function deposit($amount) { $this->balance += $amount; if ($amount >= 10) { $this->balance += 1; } return true; }
  • 19. Use the most specific assertion available There was 1 failure: 1) AccountTest::testDepositIncreasesBalance Failed asserting that 21 matches expected 20. AccountTest.php:14
  • 20. Don’t forget about protected methods class Account { public function deposit($amount) { if ($this->validateAmount($amount)) { $this->balance += $amount; } else { throw new Exception('Invalid amount'); } } }
  • 21. Don't forget about your protected methods protected function validateAmount($amount) { if ($amount < 0) { return false; } else { return true; } }
  • 22. Don't forget about your protected methods public function testValidateAmountWithNegativeIsFalse() { $account = new Account(10); $this->assertFalse($account->validateAmount(-1)); } Fatal error: Call to protected method Account::validateAmount()
  • 23. Don't forget about your protected methods public function testValidateAmountWithNegativeIsFalse() { $account = new Account(10); $reflection = new ReflectionObject($account); $method = $reflection->getMethod('validateAmount'); $method->setAccessible(true); $this->assertFalse( $method->invokeArgs($account, array(-1)) ); }
  • 24. Don't forget about your protected methods PHPUnit 4.3.1 by Sebastian Bergmann. Account [x] Deposit increases balance [x] Validate amount with negative is false
  • 25. Test just one thing at a time public function deposit($amount) { if ($amount == 0) { return false; } $this->balance += $amount; return true; }
  • 26. Test just one thing at a time public function testDepositIncreasesBalance() { $account = new Account(10); $this->assertTrue($account->deposit(1)); $this->assertEquals(11, $account->getBalance()); $this->assertFalse($account->deposit(0)); }
  • 27. Test just one thing at a time PHPUnit 4.3.1 by Sebastian Bergmann. . Time: 35 ms, Memory: 3.00Mb OK (1 test, 3 assertions)
  • 28. Test just one thing at a time public function deposit($amount) { if ($amount < 0) { NEW CRITERIA return false; } $this->balance += $amount; return true; }
  • 29. Test just one thing at a time PHPUnit 4.3.1 by Sebastian Bergmann. There was 1 failure: 1) AccountTest::testDepositIncreasesBalance Failed asserting that true is false. AccountTest.php:15 FAILURES! Tests: 1, Assertions: 3, Failures: 1.
  • 30. Test just one thing at a time public function testDepositIncreasesBalance() { $account = new Account(10); $this->assertTrue($account->deposit(1)); $this->assertEquals(11, $account->getBalance()); } public function testDepositWithNegativeShouldReturnFalse() { $account = new Account(10); $this->assertFalse($account->deposit(-1)); }
  • 31. Test just one thing at a time PHPUnit 4.3.1 by Sebastian Bergmann. .. Time: 49 ms, Memory: 3.00Mb OK (2 tests, 3 assertions)
  • 32. Use Data Providers for repetitive tests class Score { protected $score; public function update($balance, $numberCc, $amountInLoans) { // do something ... return $newScore; } }
  • 33. Use Data Providers for repetitive tests class ScoreTest extends PHpUnit_Framework_TestCase { public function testScoreSomething1() { $score = new Score(10); $this->assertEquals(300, $score->update(100, 0, 1)); } public function testScoreSomething2() { $score = new Score(10); $this->assertEquals(99, $score->update(100, 1, 2)); } }
  • 34. Use Data Providers for repetitive tests /** * @dataProvider scoreProvider */ public function testScore($balance, $numberCc, $amountInLoans, $expectedScore) { $score = new Score(10); $this->assertEquals( $expectedScore, $score->update($balance, $numberCc, $amountInLoans) ); }
  • 35. Use Data Providers for repetitive tests public function scoreProvider() { return array( array(100, 0, 1, 300), array(100, 1, 2, 99), ); }
  • 36. Use Data Providers for repetitive tests PHPUnit 4.3.1 by Sebastian Bergmann. .. Time: 25 ms, Memory: 3.00Mb OK (2 tests, 2 assertions)
  • 37. Isolate your test public function wire($amount, SwiftInterface $targetBank) { if ($targetBank->transfer($amount)) { $this->balance -= $amount; return true; } else { return false; } }
  • 38. Isolate your test class Hsbc implements SwiftInterface { public function transfer($amount) { // slow method } }
  • 39. Isolate your test public function testWireTransferShouldReturnTrueIfSuccessful() { $account = new Account(10); $bank = new Hsbc(); $this->assertTrue($account->wire(5, $bank)); }
  • 40. Isolate your test public function testWireTransferShouldReturnFalseIfFailed() { // how to fail? $account = new Account(10); $bank = new Hsbc(); $this->assertFalse($account->wire(5, $bank)); }
  • 41. Isolate your test public function testWireTransferShouldReturnTrueIfSuccessful() { $account = new Account(10); $bank = $this->getMock(‘Hsbc'); $bank->expects($this->any()) ->method('transfer') ->will($this->returnValue(true)); $this->assertTrue($account->wire(5, $bank)); }
  • 42. Isolate your test public function testWireTransferShouldReturnFalseIfFailed() { $account = new Account(10); $bank = $this->getMock('Hsbc'); $bank->expects($this->any()) ->method('transfer') ->will($this->returnValue(false)); $this->assertFalse($account->wire(5, $bank)); }
  • 43. Specify what you are testing with @covers  Use --coverage-html to generate the code coverage report of your code
  • 44. Specify what you are testing with @covers
  • 45. Specify what you are testing with @covers class Exchange { public function convert($amountUsd, $targetCurrency) { // Do some conversion } }
  • 46. Specify what you are testing with @covers public function convertBalance($targetCurrency) { $exchange = new Exchange(); return $exchange->convert($this->balance, $targetCurrency); }
  • 47. Specify what you are testing with @covers public function testConvertBalance() { $account = new Account(10); $this->assertLessThan( 10, $account->convertBalance('GBP') ); }
  • 48. Specify what you are testing with @covers
  • 49. Specify what you are testing with @covers
  • 50. Specify what you are testing with @covers /** * @covers Account::convertBalance */ public function testConvertBalance() { … }
  • 51. Specify what you are testing with @covers
  • 52. That is all folks! Contacts  Twitter -@bicatu  Email – mbneto@gmail.com  https://joind.in/12279  http://slidesha.re/1xtcT4y

Editor's Notes

  1. The test should break because the code it is testing changed but it did not