Upload
chartjes
View
85
Download
1
Embed Size (px)
Citation preview
Learn To Test Like A Grumpy Programmer
Chris Hartjes SushinePHP 2017
Who is this guy and why
should I listen?• Long-time tester • Beard conveys authority • Twitter account is verified • PHP dev since 1998 • Wants to help you get
better!
Building BlocksIt’s Like Using Lego
It’s Like Lego!
• TDD encourages creating applications by combining units together like Legos
• Results in loosely-coupled modules
• Unit testing tools are no different
Assertions
• The backbone of unit testing
• Simple to understand
Assertions
• Unit tests (usually) usually have one or more assertions
• Proves that your expectation of an outcome is correct
The Simplest Test That Runs
Assertions
• $this->assertTrue(<some expression>)
• $this->assertFalse(<some expression>)
• $this->assertEquals(<value 1>, <value 2)
Assertions
Those three assertions will cover
99% of your unit testing needs
Code Kata I
• Code katas are small coding exercises with known solutions
• Designed to turn certain programming practices into “muscle memory”
• Concept taken from Asian martial arts
Code Kata I
• FizzBuzz!
• great exercise for covering programming basics
• easily tested
Code Kata I
• make sure you create a directory to do your exercises in
• make sure you have Composer installed
• make sure you’ve installed PHPUnit using it
FizzBuzz• Take a collection of integers only
• If the integer is divisible by 3, change it to ‘Fizz’
• If the integer is divisible by 5, change it to ‘Buzz’
• If the integer is divisible by 3 and 5, change it to ‘FizzBuzz’
• Otherwise do not change the value
Data Providers
• Reduce the number of tests you write
• Modify test data sets without modifying test
Data Providers
• Modify test method to accept parameters matching the data you will provide
• Create a method that returns an array of arrays containing data
Code Kata II
• Your turn to do some TDD!
• Create an object that turns Arabic numbers into Roman Numerals
Code Kata II
• Use TDD to design your class
• Use data providers
• Get into writing code in an iterative way
Code Kata II1 -> I 2 -> II 3 -> III 4 -> IV
5 -> V 6 -> VI 7 -> VII 8 -> VIII
9 -> IX 10 -> X 40 -> XL 50 -> L
Dependency Management In Unit Tests
• Figure out your dependencies
• Figure out which ones need to be doubles
• “Inject” them for your code-under-test to use
Dependency Injection Techniques
• Globally-available containers
• Constructor injection
• Setter injection
Globally-available Containers
• Best for legacy code where refactoring to injection is difficult
• Can use $GLOBALS super global in a pinch
• Container / service locator usage very common
Constructor Injection
• Pass in dependencies at object creation
• Gets messy if many dependencies are required
• Can lead to __construct() doing too much work
Setter Injection
• “Less messy” than using constructors
• Refactoring to add get/set methods not overly intrusive
• Allows overriding of internally-created dependencies
Test Doubles
• Understanding them was the most difficult thing I had to learn
• Makes you understand how critical putting dependencies in specific states is
Types Of Test Doubles
• Classical definition is that there are five types
• Dummy objects, test stubs, test spies, test mocks, test fakes
Types Of Test Doubles
• PHPUnit-compatible test double tools tend to only use three
• Dummy objects, test stubs, test mocks
Dummy Object
• Stand-in for the real dependency
• Does not any functionality
• Only needs to ‘look like’ the real dependency
Dummy Object
$mock = Mockery::mock(‘Grumpy\Foo’);
Stubs
• ‘Dummy object’ but with defined methods
• Methods don’t need to return anything
• Satisfies any calls to the dependency where the response doesn’t matter
Stubs
$mock = Mockery::mock(‘Grumpy\Foo’); $mock->shouldReceive(‘bar’);
Mocks
• ‘Stub’ where return value for methods are set
• Most common test double you will use
Mocks
$mock = Mockery::mock(‘Grumpy\Foo’); $mock->shouldReceive(‘bar’)
->andReturn(false);
Test Doubles Considered Harmful
• Be careful to not fall in love with test doubles
• Having to create too many of them exposes tightly-coupled code
Test Doubles Considered Harmful
• Use them when you have a dependency that is difficult to use under normal circumstances
• Database connections and 3rd party API calls come to mind
A Simple Example
Code Kata III• Use TDD to add a method called getAllActive()
• Uses fetchAll() to get back a data set that includes id, email, and where is_active is set to 1 or 0
• Have at least 3 records, with 2 active
• You must manually filter out records in getAllActive()
• return results as array with just ‘id’ and ‘email’
Bonus Round!
Automation!(Help humans make fewer mistakes)
Deployments!(They should be trivial)
Opportunity Costs!(Make the cost of fixing bugs cheaper)
TDD Works!(Studies exist showing effectiveness)
Want To Learn More?
• https://grumpy-learning.com
• @grmpyprogrammer on Twitter