Learn To Test Like A Grumpy Programmer - 3 hour workshop

Preview:

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

• chartjes@grumpy-learning.com

Recommended