SlideShare uma empresa Scribd logo
1 de 48
Testing the
Untestable
Unit Tests are Great !
• Proof that your code does what it is supposed to do
• Proof that refactoring code doesn’t break its functionality
• Automated Regressions Tests
• Verify that new code doesn’t break existing code
• Unit Tests are a part of the documentation of the code
TDD is Great !
• Writing tests helps design how the code should work
• Write tests as we define the public methods
• All green tests tell us when the coding is complete
• Bugfixing
• Write test for bug
• Fix bug so that test passes
Testing the Untestable
Testing the Untestable
• 100% Code Coverage is over-rated
• Prioritise writing Tests for the code that needs testing
• Diminishing returns
Testing the Untestable
• Test Doubles
• Let the code run
• Mock as little as possible
• Database access
• E-Mailing
• Test values
Testing the Untestable
• Constructor does Real Work
• Indirect Collaborators
• Global State & Singletons
• Class Does Too Much
Testing the Untestable
Constructor does Real Work
• Difficulties
• Creating/Initializing Collaborators
• Communicating with other services, and logic to set up its own
state
• Forcing subclasses/mocks to inherit unwanted behaviour
• Prevents instantiation or altering collaborators in the test.
Testing the Untestable
Constructor does Real Work
• Warning Signs
• new keyword in a constructor
• Static method calls in a constructor
• Anything more than argument validation and field assignment in constructors
• Object not fully initialized after the constructor finishes
• Control flow (conditional or looping logic) in a constructor
• Separate Initialisation methods
Testing the Untestable
Constructor does Real Work
• Why?
• Inflexible and prematurely coupled design
• Violates Single Responsibility Principle
• Testing Directly is Difficult
• Subclassing and Overriding to Test is Still Flawed
• It Forces Collaborators on Us
Testing the Untestable
Indirect Collaborators
• Difficulties
• “Middle Men” make change difficult
• Unnecessary complexity and code bloat
Testing the Untestable
Indirect Collaborators
• Warning Signs
• Objects are passed in but never used directly
• Only used to get access to other objects
• Suspicious names like context, environment, principal,
container, or manager
Testing the Untestable
Indirect Collaborators
• Why?
• Hard to identify the collaborator methods that we need to mock
• Necessary to create mocks that return other mocks
Testing the Untestable
Global State & Singletons
• Difficulties
• Global state mutated in one test can cause a subsequent or
parallel test to fail unexpectedly.
• Forcing subclasses/mocks to inherit unwanted behaviour
• Prevents instantiation or altering collaborators in the test.
Testing the Untestable
Global State & Singletons
• Warning Signs
• Use of Singletons
• Using Static Properties or Methods
• Using Registries or Service Locators
• Static Initialisation Blocks
Testing the Untestable
Global State & Singletons
• Why?
• Changes to global state can be made from anywhere
• Unexpected initial state for individual tests
Testing the Untestable
• Class Does Too Much
• Difficulties
• Tests for individual Methods can’t easily be isolated from other
methods
Testing the Untestable
• Class Does Too Much
• Warning Signs
• Class description uses the word “and”
• Too many methods
• Too many properties
• Too many collaborators
Testing the Untestable
The ideal number of arguments for a function is zero (niladic). Next
comes one (monadic) followed closely by two (dyadic). Three
arguments (triadic) should be avoided where possible. More than three
(polyadic) requires very special justification—and then shouldn't be
used anyway.
Bob Martin – “Clean Code”
Testing the Untestable
public function __construct(
MagentoFrameworkModelContext $context,
MagentoFrameworkViewDesignInterface $design,
MagentoFrameworkRegistry $registry,
MagentoStoreModelAppEmulation $appEmulation,
MagentoStoreModelStoreManagerInterface $storeManager,
MagentoFrameworkAppRequestInterface $request,
MagentoNewsletterModelTemplateFilter $filter,
MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
MagentoNewsletterModelTemplateFactory $templateFactory,
MagentoFrameworkFilterFilterManager $filterManager,
array $data = []
) {
parent::__construct($context, $design, $registry, $appEmulation, $storeManager, $data);
$this->_storeManager = $storeManager;
$this->_request = $request;
$this->_filter = $filter;
$this->_scopeConfig = $scopeConfig;
$this->_templateFactory = $templateFactory;
$this->_filterManager = $filterManager;
}
Testing the Untestable
• Class Does Too Much
• Why?
• Difficult to modify behaviour of one responsibility without
changing/breaking others
• Muddled Responsibilities
Testing the Untestable
namespace reporting;
class dateCalculator {
protected $currentDate;
public function __construct() {
$this->currentDate = new DateTime();
}
public function weekToDate() {
$startDate = clone $this->currentDate;
$startDate->modify('last monday');
return new dateRange(
$startDate->modify('midnight'),
(clone $this->currentDate)->modify('midnight')
);
}
}
Testing the Untestable
namespace reporting;
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
$dateCalculator = new dateCalculator();
$week = $dateCalculator->weekToDate();
$this->assertInstanceOf('reportingdateRange', $week);
$this->assertInstanceOf('DateTime', $week->startDate);
$this->assertEquals(
DateTime::createFromFormat('Y-m-d|', '2018-01-08'),
$week->startDate
);
$this->assertInstanceOf('DateTime', $week->endDate);
$this->assertEquals(
DateTime::createFromFormat('Y-m-d|', '2018-01-10'),
$week->endDate
);
}
}
Testing the Untestable
• Dependency Injection
• Inject either a date value or a DateTime object into the constructor
Testing the Untestable
namespace reporting;
class dateCalculator {
protected $currentDate;
public function __construct(string $date = 'now') {
$this->currentDate = new DateTime($date);
}
public function weekToDate() {
$startDate = clone $this->currentDate;
$startDate->modify('last monday');
return new dateRange(
$startDate->modify('midnight'),
(clone $this->currentDate)->modify('midnight')
);
}
}
Testing the Untestable
namespace reporting;
class dateCalculator {
protected $currentDate;
public function __construct(DateTime $dto) {
$this->currentDate = $dto;
}
public function weekToDate() {
$startDate = clone $this->currentDate;
$startDate->modify('last monday');
return new dateRange(
$startDate->modify('midnight'),
(clone $this->currentDate)->modify('midnight')
);
}
}
Testing the Untestable
• Dependency Injection (Inversion of Control)
• Inject either a date value or a DateTime object into the constructor
• Not always an option if we can’t change the codebase
• e.g. If we’re writing tests preparatory to refactoring
• May require significant changes wherever the class we’re testing is
used within the main codebase
• Or introducing a Dependency Injection Container
Testing the Untestable
• In the case of DateTime, we can modify the the
DateTime constructor
• If we’re using namespacing
Testing the Untestable
class dateCalculator {
protected $currentDate;
public function __construct() {
$this->currentDate = new DateTime("@" . time());
}
....
}
Testing the Untestable
namespace reporting;
function time() {
return strtotime('2018-01-10 01:23:45');
}
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
$dateCalculator = new dateCalculator();
$week = $dateCalculator->weekToDate();
.... Assertions
}
}
Testing the Untestable
• In the case of DateTime, we can modify the the
DateTime constructor
• If we’re using namespacing
• Overriding the time() function with a namespaced
time() function
• So we set our own value to be returned by a call to time()
Testing the Untestable
• Move the assignment of $currentDate and the
instantiation of the DateTime to a separate method
called from the constructor
• We can then mock that new method in our tests
Testing the Untestable
class dateCalculator {
protected $currentDate;
protected function getCurrentDate() {
return new DateTime();
}
public function __construct() {
$this->currentDate = $this->getCurrentDate();
}
....
}
Testing the Untestable
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
$dateCalculator = $this->getMockBuilder('reportingdateCalculator')
->setMethods(['getCurrentDate'])
->getMock();
$dateCalculator->expects($this->once())
->method('getCurrentDate')
->will(
$this->returnValue(new DateTime('2018-01-10 01:23:45'))
);
$week = $dateCalculator->weekToDate();
.... Assertions
}
}
Testing the Untestable
• Or Use Reflection
Testing the Untestable
class dateCalculator {
protected $currentDate;
protected function getCurrentDate() {
return new DateTime();
}
public function __construct() {
$this->currentDate = $this->getCurrentDate();
}
....
}
Testing the Untestable
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
$dateCalculator = $this->getMockBuilder('reportingdateCalculator')
->disableOriginalConstructor()
->setMethods(['getCurrentDate'])
->getMock();
$dateCalculator->expects($this->once())
->method('getCurrentDate')
->will(
$this->returnValue(new DateTime('2018-01-10 01:23:45'))
);
....
}
}
Testing the Untestable
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
....
// now call the constructor
$reflectedClass = new ReflectionClass('reportingdateCalculator');
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($dateCalculator);
$week = $dateCalculator->weekToDate();
.... Assertions
}
}
Testing the Untestable
• Anonymous Classes
• http://php.net/manual/en/language.oop5.anonymous.php
Testing the Untestable
class dateCalculatorTest extends PHPUnitFrameworkTestCase {
public function testDateCalculatorWeek() {
$dateCalculator = new class() extends dateCalculator {
public function __construct() {
// parent::__construct();
$this->currentDate = new DateTime('2018-01-10 01:23:45');
}
};
$week = $dateCalculator->weekToDate();
.... Assertions
}
}
Testing the Untestable
• https://github.com/MarkBaker/SpyMaster
Testing the Untestable
public function testDateCalculatorWeek() {
$dateCalculator = new dateCalculator();
$spy = (new SpyMasterSpyMaster($dateCalculator))
->infiltrate(SpyMasterSpyMaster::SPY_READ_WRITE);
$spy->currentDate = new DateTime('2018-01-10 01:23:45');
$week = $dateCalculator->weekToDate();
.... Assertions
}
Testing the Untestable
• Make sure we test against different dates using a
phpunit dataprovider
Testing the Untestable
/**
* @dataProvider testDateCalculatorWeekProvider
**/
public function testDateCalculatorWeek($baseline, $expectedResult) {
$dateCalculator = new class($baseline) extends dateCalculator {
public function __construct($baseline) {
// parent::__construct();
$this->currentDate = new DateTime($baseline);
}
};
$week = $dateCalculator->weekToDate();
.... Assertions
}
Testing the Untestable
• Mockery
• https://github.com/mockery/mockery
• AspectMock
• https://github.com/Codeception/AspectMock
Testing the Untestable
• Mocking the Filesystem
• https://github.com/mikey179/vfsStream
Testing the Untestable
• Assertions for HTML Markup
• https://github.com/stevegrunwell/phpunit-markup-assertions
Who am I?
Mark Baker
@Mark_Baker
https://github.com/MarkBaker
http://uk.linkedin.com/pub/mark-baker/b/572/171
http://markbakeruk.net

Mais conteúdo relacionado

Mais procurados

Apex Testing and Best Practices
Apex Testing and Best PracticesApex Testing and Best Practices
Apex Testing and Best PracticesJitendra Zaa
 
Intro to TDD and BDD
Intro to TDD and BDDIntro to TDD and BDD
Intro to TDD and BDDJason Noble
 
Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015CiaranMcNulty
 
Pitfalls Of Tdd Adoption by Bartosz Bankowski
Pitfalls Of Tdd Adoption by Bartosz BankowskiPitfalls Of Tdd Adoption by Bartosz Bankowski
Pitfalls Of Tdd Adoption by Bartosz BankowskiAgileee
 
VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)Rob Hale
 
Unit Testing Done Right
Unit Testing Done RightUnit Testing Done Right
Unit Testing Done RightBrian Fenton
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Unit testing legacy code
Unit testing legacy codeUnit testing legacy code
Unit testing legacy codeLars Thorup
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummiesHarry Potter
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven DevelopmentDhaval Dalal
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesDavid Rodenas
 
Angular Unit Testing NDC Minn 2018
Angular Unit Testing NDC Minn 2018Angular Unit Testing NDC Minn 2018
Angular Unit Testing NDC Minn 2018Justin James
 
Unit Testing Best Practices
Unit Testing Best PracticesUnit Testing Best Practices
Unit Testing Best PracticesTomaš Maconko
 
Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications nispas
 
Working Effectively with Legacy Code: Lessons in Practice
Working Effectively with Legacy Code: Lessons in PracticeWorking Effectively with Legacy Code: Lessons in Practice
Working Effectively with Legacy Code: Lessons in PracticeAmar Shah
 
Write testable code in java, best practices
Write testable code in java, best practicesWrite testable code in java, best practices
Write testable code in java, best practicesMarian Wamsiedel
 

Mais procurados (20)

Apex Testing and Best Practices
Apex Testing and Best PracticesApex Testing and Best Practices
Apex Testing and Best Practices
 
Intro to TDD and BDD
Intro to TDD and BDDIntro to TDD and BDD
Intro to TDD and BDD
 
Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015
 
Pitfalls Of Tdd Adoption by Bartosz Bankowski
Pitfalls Of Tdd Adoption by Bartosz BankowskiPitfalls Of Tdd Adoption by Bartosz Bankowski
Pitfalls Of Tdd Adoption by Bartosz Bankowski
 
VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)VT.NET 20160411: An Intro to Test Driven Development (TDD)
VT.NET 20160411: An Intro to Test Driven Development (TDD)
 
Unit Testing Done Right
Unit Testing Done RightUnit Testing Done Right
Unit Testing Done Right
 
Grails Spock Testing
Grails Spock TestingGrails Spock Testing
Grails Spock Testing
 
Unit test-using-spock in Grails
Unit test-using-spock in GrailsUnit test-using-spock in Grails
Unit test-using-spock in Grails
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Unit testing legacy code
Unit testing legacy codeUnit testing legacy code
Unit testing legacy code
 
Google mock for dummies
Google mock for dummiesGoogle mock for dummies
Google mock for dummies
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
 
Angular Unit Testing NDC Minn 2018
Angular Unit Testing NDC Minn 2018Angular Unit Testing NDC Minn 2018
Angular Unit Testing NDC Minn 2018
 
Unit Testing Best Practices
Unit Testing Best PracticesUnit Testing Best Practices
Unit Testing Best Practices
 
Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications Automated testing of ASP .Net Core applications
Automated testing of ASP .Net Core applications
 
Working Effectively with Legacy Code: Lessons in Practice
Working Effectively with Legacy Code: Lessons in PracticeWorking Effectively with Legacy Code: Lessons in Practice
Working Effectively with Legacy Code: Lessons in Practice
 
Write testable code in java, best practices
Write testable code in java, best practicesWrite testable code in java, best practices
Write testable code in java, best practices
 
Unit tests and TDD
Unit tests and TDDUnit tests and TDD
Unit tests and TDD
 

Semelhante a Testing the Untestable

Advance unittest
Advance unittestAdvance unittest
Advance unittestReza Arbabi
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Software Testing
Software TestingSoftware Testing
Software TestingAdroitLogic
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Unit testing in php
Unit testing in phpUnit testing in php
Unit testing in phpSudar Muthu
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
Software testing ... who’s responsible is it?
Software testing ... who’s responsible is it?Software testing ... who’s responsible is it?
Software testing ... who’s responsible is it?Manjula03809891
 
Software testing ... who is responsible for it?
Software testing ... who is responsible for it?Software testing ... who is responsible for it?
Software testing ... who is responsible for it?Manjula Piyumal
 
Agile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayAgile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayJordi Pradel
 
Unit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - KenyaUnit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - KenyaErick M'bwana
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1Yi-Huan Chan
 
Into The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsInto The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsOrtus Solutions, Corp
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherencearagozin
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignVictor Rentea
 
Test automation engineer
Test automation engineerTest automation engineer
Test automation engineerSadaaki Emura
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)vilniusjug
 

Semelhante a Testing the Untestable (20)

Advance unittest
Advance unittestAdvance unittest
Advance unittest
 
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Software Testing
Software TestingSoftware Testing
Software Testing
 
Unit testing
Unit testingUnit testing
Unit testing
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
Unit testing in php
Unit testing in phpUnit testing in php
Unit testing in php
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
Software testing ... who’s responsible is it?
Software testing ... who’s responsible is it?Software testing ... who’s responsible is it?
Software testing ... who’s responsible is it?
 
Software testing ... who is responsible for it?
Software testing ... who is responsible for it?Software testing ... who is responsible for it?
Software testing ... who is responsible for it?
 
Agile Software Testing the Agilogy Way
Agile Software Testing the Agilogy WayAgile Software Testing the Agilogy Way
Agile Software Testing the Agilogy Way
 
Unit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - KenyaUnit testing and mocking in Python - PyCon 2018 - Kenya
Unit testing and mocking in Python - PyCon 2018 - Kenya
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
 
Into The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applicationsInto The Box 2018 | Assert control over your legacy applications
Into The Box 2018 | Assert control over your legacy applications
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherence
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 
Test automation engineer
Test automation engineerTest automation engineer
Test automation engineer
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)
 

Mais de Mark Baker

Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to ProductionMark Baker
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to ProductionMark Baker
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to ProductionMark Baker
 
A Brief History of Elephpants
A Brief History of ElephpantsA Brief History of Elephpants
A Brief History of ElephpantsMark Baker
 
Aspects of love slideshare
Aspects of love slideshareAspects of love slideshare
Aspects of love slideshareMark Baker
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Mark Baker
 
A Brief History of ElePHPants
A Brief History of ElePHPantsA Brief History of ElePHPants
A Brief History of ElePHPantsMark Baker
 
Coding Horrors
Coding HorrorsCoding Horrors
Coding HorrorsMark Baker
 
Anonymous classes2
Anonymous classes2Anonymous classes2
Anonymous classes2Mark Baker
 
Anonymous Classes: Behind the Mask
Anonymous Classes: Behind the MaskAnonymous Classes: Behind the Mask
Anonymous Classes: Behind the MaskMark Baker
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Mark Baker
 
Coding Horrors
Coding HorrorsCoding Horrors
Coding HorrorsMark Baker
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Mark Baker
 
Giving birth to an ElePHPant
Giving birth to an ElePHPantGiving birth to an ElePHPant
Giving birth to an ElePHPantMark Baker
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsMark Baker
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsMark Baker
 
SPL - The Undiscovered Library - PHPBarcelona 2015
SPL - The Undiscovered Library - PHPBarcelona 2015SPL - The Undiscovered Library - PHPBarcelona 2015
SPL - The Undiscovered Library - PHPBarcelona 2015Mark Baker
 

Mais de Mark Baker (20)

Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to Production
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to Production
 
Deploying Straight to Production
Deploying Straight to ProductionDeploying Straight to Production
Deploying Straight to Production
 
A Brief History of Elephpants
A Brief History of ElephpantsA Brief History of Elephpants
A Brief History of Elephpants
 
Aspects of love slideshare
Aspects of love slideshareAspects of love slideshare
Aspects of love slideshare
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?
 
A Brief History of ElePHPants
A Brief History of ElePHPantsA Brief History of ElePHPants
A Brief History of ElePHPants
 
Coding Horrors
Coding HorrorsCoding Horrors
Coding Horrors
 
Anonymous classes2
Anonymous classes2Anonymous classes2
Anonymous classes2
 
Anonymous Classes: Behind the Mask
Anonymous Classes: Behind the MaskAnonymous Classes: Behind the Mask
Anonymous Classes: Behind the Mask
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?
 
Coding Horrors
Coding HorrorsCoding Horrors
Coding Horrors
 
Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?Does the SPL still have any relevance in the Brave New World of PHP7?
Does the SPL still have any relevance in the Brave New World of PHP7?
 
Giving birth to an ElePHPant
Giving birth to an ElePHPantGiving birth to an ElePHPant
Giving birth to an ElePHPant
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
SPL - The Undiscovered Library - PHPBarcelona 2015
SPL - The Undiscovered Library - PHPBarcelona 2015SPL - The Undiscovered Library - PHPBarcelona 2015
SPL - The Undiscovered Library - PHPBarcelona 2015
 

Último

Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 

Último (20)

Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 

Testing the Untestable

  • 2. Unit Tests are Great ! • Proof that your code does what it is supposed to do • Proof that refactoring code doesn’t break its functionality • Automated Regressions Tests • Verify that new code doesn’t break existing code • Unit Tests are a part of the documentation of the code
  • 3. TDD is Great ! • Writing tests helps design how the code should work • Write tests as we define the public methods • All green tests tell us when the coding is complete • Bugfixing • Write test for bug • Fix bug so that test passes
  • 5. Testing the Untestable • 100% Code Coverage is over-rated • Prioritise writing Tests for the code that needs testing • Diminishing returns
  • 6. Testing the Untestable • Test Doubles • Let the code run • Mock as little as possible • Database access • E-Mailing • Test values
  • 7. Testing the Untestable • Constructor does Real Work • Indirect Collaborators • Global State & Singletons • Class Does Too Much
  • 8. Testing the Untestable Constructor does Real Work • Difficulties • Creating/Initializing Collaborators • Communicating with other services, and logic to set up its own state • Forcing subclasses/mocks to inherit unwanted behaviour • Prevents instantiation or altering collaborators in the test.
  • 9. Testing the Untestable Constructor does Real Work • Warning Signs • new keyword in a constructor • Static method calls in a constructor • Anything more than argument validation and field assignment in constructors • Object not fully initialized after the constructor finishes • Control flow (conditional or looping logic) in a constructor • Separate Initialisation methods
  • 10. Testing the Untestable Constructor does Real Work • Why? • Inflexible and prematurely coupled design • Violates Single Responsibility Principle • Testing Directly is Difficult • Subclassing and Overriding to Test is Still Flawed • It Forces Collaborators on Us
  • 11. Testing the Untestable Indirect Collaborators • Difficulties • “Middle Men” make change difficult • Unnecessary complexity and code bloat
  • 12. Testing the Untestable Indirect Collaborators • Warning Signs • Objects are passed in but never used directly • Only used to get access to other objects • Suspicious names like context, environment, principal, container, or manager
  • 13. Testing the Untestable Indirect Collaborators • Why? • Hard to identify the collaborator methods that we need to mock • Necessary to create mocks that return other mocks
  • 14. Testing the Untestable Global State & Singletons • Difficulties • Global state mutated in one test can cause a subsequent or parallel test to fail unexpectedly. • Forcing subclasses/mocks to inherit unwanted behaviour • Prevents instantiation or altering collaborators in the test.
  • 15. Testing the Untestable Global State & Singletons • Warning Signs • Use of Singletons • Using Static Properties or Methods • Using Registries or Service Locators • Static Initialisation Blocks
  • 16. Testing the Untestable Global State & Singletons • Why? • Changes to global state can be made from anywhere • Unexpected initial state for individual tests
  • 17. Testing the Untestable • Class Does Too Much • Difficulties • Tests for individual Methods can’t easily be isolated from other methods
  • 18. Testing the Untestable • Class Does Too Much • Warning Signs • Class description uses the word “and” • Too many methods • Too many properties • Too many collaborators
  • 19. Testing the Untestable The ideal number of arguments for a function is zero (niladic). Next comes one (monadic) followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification—and then shouldn't be used anyway. Bob Martin – “Clean Code”
  • 20. Testing the Untestable public function __construct( MagentoFrameworkModelContext $context, MagentoFrameworkViewDesignInterface $design, MagentoFrameworkRegistry $registry, MagentoStoreModelAppEmulation $appEmulation, MagentoStoreModelStoreManagerInterface $storeManager, MagentoFrameworkAppRequestInterface $request, MagentoNewsletterModelTemplateFilter $filter, MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig, MagentoNewsletterModelTemplateFactory $templateFactory, MagentoFrameworkFilterFilterManager $filterManager, array $data = [] ) { parent::__construct($context, $design, $registry, $appEmulation, $storeManager, $data); $this->_storeManager = $storeManager; $this->_request = $request; $this->_filter = $filter; $this->_scopeConfig = $scopeConfig; $this->_templateFactory = $templateFactory; $this->_filterManager = $filterManager; }
  • 21. Testing the Untestable • Class Does Too Much • Why? • Difficult to modify behaviour of one responsibility without changing/breaking others • Muddled Responsibilities
  • 22. Testing the Untestable namespace reporting; class dateCalculator { protected $currentDate; public function __construct() { $this->currentDate = new DateTime(); } public function weekToDate() { $startDate = clone $this->currentDate; $startDate->modify('last monday'); return new dateRange( $startDate->modify('midnight'), (clone $this->currentDate)->modify('midnight') ); } }
  • 23. Testing the Untestable namespace reporting; class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { $dateCalculator = new dateCalculator(); $week = $dateCalculator->weekToDate(); $this->assertInstanceOf('reportingdateRange', $week); $this->assertInstanceOf('DateTime', $week->startDate); $this->assertEquals( DateTime::createFromFormat('Y-m-d|', '2018-01-08'), $week->startDate ); $this->assertInstanceOf('DateTime', $week->endDate); $this->assertEquals( DateTime::createFromFormat('Y-m-d|', '2018-01-10'), $week->endDate ); } }
  • 24. Testing the Untestable • Dependency Injection • Inject either a date value or a DateTime object into the constructor
  • 25. Testing the Untestable namespace reporting; class dateCalculator { protected $currentDate; public function __construct(string $date = 'now') { $this->currentDate = new DateTime($date); } public function weekToDate() { $startDate = clone $this->currentDate; $startDate->modify('last monday'); return new dateRange( $startDate->modify('midnight'), (clone $this->currentDate)->modify('midnight') ); } }
  • 26. Testing the Untestable namespace reporting; class dateCalculator { protected $currentDate; public function __construct(DateTime $dto) { $this->currentDate = $dto; } public function weekToDate() { $startDate = clone $this->currentDate; $startDate->modify('last monday'); return new dateRange( $startDate->modify('midnight'), (clone $this->currentDate)->modify('midnight') ); } }
  • 27. Testing the Untestable • Dependency Injection (Inversion of Control) • Inject either a date value or a DateTime object into the constructor • Not always an option if we can’t change the codebase • e.g. If we’re writing tests preparatory to refactoring • May require significant changes wherever the class we’re testing is used within the main codebase • Or introducing a Dependency Injection Container
  • 28. Testing the Untestable • In the case of DateTime, we can modify the the DateTime constructor • If we’re using namespacing
  • 29. Testing the Untestable class dateCalculator { protected $currentDate; public function __construct() { $this->currentDate = new DateTime("@" . time()); } .... }
  • 30. Testing the Untestable namespace reporting; function time() { return strtotime('2018-01-10 01:23:45'); } class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { $dateCalculator = new dateCalculator(); $week = $dateCalculator->weekToDate(); .... Assertions } }
  • 31. Testing the Untestable • In the case of DateTime, we can modify the the DateTime constructor • If we’re using namespacing • Overriding the time() function with a namespaced time() function • So we set our own value to be returned by a call to time()
  • 32. Testing the Untestable • Move the assignment of $currentDate and the instantiation of the DateTime to a separate method called from the constructor • We can then mock that new method in our tests
  • 33. Testing the Untestable class dateCalculator { protected $currentDate; protected function getCurrentDate() { return new DateTime(); } public function __construct() { $this->currentDate = $this->getCurrentDate(); } .... }
  • 34. Testing the Untestable class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { $dateCalculator = $this->getMockBuilder('reportingdateCalculator') ->setMethods(['getCurrentDate']) ->getMock(); $dateCalculator->expects($this->once()) ->method('getCurrentDate') ->will( $this->returnValue(new DateTime('2018-01-10 01:23:45')) ); $week = $dateCalculator->weekToDate(); .... Assertions } }
  • 35. Testing the Untestable • Or Use Reflection
  • 36. Testing the Untestable class dateCalculator { protected $currentDate; protected function getCurrentDate() { return new DateTime(); } public function __construct() { $this->currentDate = $this->getCurrentDate(); } .... }
  • 37. Testing the Untestable class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { $dateCalculator = $this->getMockBuilder('reportingdateCalculator') ->disableOriginalConstructor() ->setMethods(['getCurrentDate']) ->getMock(); $dateCalculator->expects($this->once()) ->method('getCurrentDate') ->will( $this->returnValue(new DateTime('2018-01-10 01:23:45')) ); .... } }
  • 38. Testing the Untestable class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { .... // now call the constructor $reflectedClass = new ReflectionClass('reportingdateCalculator'); $constructor = $reflectedClass->getConstructor(); $constructor->invoke($dateCalculator); $week = $dateCalculator->weekToDate(); .... Assertions } }
  • 39. Testing the Untestable • Anonymous Classes • http://php.net/manual/en/language.oop5.anonymous.php
  • 40. Testing the Untestable class dateCalculatorTest extends PHPUnitFrameworkTestCase { public function testDateCalculatorWeek() { $dateCalculator = new class() extends dateCalculator { public function __construct() { // parent::__construct(); $this->currentDate = new DateTime('2018-01-10 01:23:45'); } }; $week = $dateCalculator->weekToDate(); .... Assertions } }
  • 41. Testing the Untestable • https://github.com/MarkBaker/SpyMaster
  • 42. Testing the Untestable public function testDateCalculatorWeek() { $dateCalculator = new dateCalculator(); $spy = (new SpyMasterSpyMaster($dateCalculator)) ->infiltrate(SpyMasterSpyMaster::SPY_READ_WRITE); $spy->currentDate = new DateTime('2018-01-10 01:23:45'); $week = $dateCalculator->weekToDate(); .... Assertions }
  • 43. Testing the Untestable • Make sure we test against different dates using a phpunit dataprovider
  • 44. Testing the Untestable /** * @dataProvider testDateCalculatorWeekProvider **/ public function testDateCalculatorWeek($baseline, $expectedResult) { $dateCalculator = new class($baseline) extends dateCalculator { public function __construct($baseline) { // parent::__construct(); $this->currentDate = new DateTime($baseline); } }; $week = $dateCalculator->weekToDate(); .... Assertions }
  • 45. Testing the Untestable • Mockery • https://github.com/mockery/mockery • AspectMock • https://github.com/Codeception/AspectMock
  • 46. Testing the Untestable • Mocking the Filesystem • https://github.com/mikey179/vfsStream
  • 47. Testing the Untestable • Assertions for HTML Markup • https://github.com/stevegrunwell/phpunit-markup-assertions
  • 48. Who am I? Mark Baker @Mark_Baker https://github.com/MarkBaker http://uk.linkedin.com/pub/mark-baker/b/572/171 http://markbakeruk.net

Notas do Editor

  1. Problematic test only works on 10th January 2018
  2. Best solution is to modify the code to inject the date into the constructor, either as a date-recognisable string
  3. Or as a DateTime object This has the added advantage of allowing reports to be re-run for a particular historic date
  4. Using an anonymous class to extend the class being tested and override the constructor