Slide 1

Slide 1 text

Learn To Test Like A Grumpy Programmer PHP Australia Conference April 14, 2016

Slide 2

Slide 2 text

Who is this guy and why should I listen? • Long-time tester • Beard conveys authority • PHP dev since 1998 • Wants to help you get better!

Slide 3

Slide 3 text

5 W’s (and one H)

Slide 4

Slide 4 text

Who Should Test? • developers looking for stable deployments • developers looking to increase ability to change • developers looking to go home on time

Slide 5

Slide 5 text

Stable Deployments AUTOMATE AUTOMATE AUTOMATE

Slide 6

Slide 6 text

Stable Deployment • Exposes poor deployment practices • Exposes brittle application architectures • Promotes “automation-first” thinking

Slide 7

Slide 7 text

Confidence In Changes • Did that new feature break an old one? • Did the refactoring break working code? • Did we miss an opportunity to move forward?

Slide 8

Slide 8 text

Confidence In Changes • Removing technical debt is always scary • Increases reliance on automated systems • Forces thinking about more than just code

Slide 9

Slide 9 text

Go Home On Time • Production pushes will go smoother • Eliminates “stick around just in case” deployments • Makes deployments a non-issue

Slide 10

Slide 10 text

What Is TDD? • Design Tool • Style Enforcer • Hard-to-shake Coding Habit

Slide 11

Slide 11 text

Design Tool • Tests as working examples of code • Forces you to concentrate on interfaces and API’s

Slide 12

Slide 12 text

Design Tool • Limits work in progress • Exposes awkward code earlier • Exposes dependencies for code earlier

Slide 13

Slide 13 text

Code In A Specific Style • Impossible to build fast-running unit tests for tightly-coupled code • Modules of code end up like LEGO bricks • “Ports and Adapters” • Dependencies become crystal clear

Slide 14

Slide 14 text

You Can’t Go Back • “How do I test this thing?” • “How do I use this thing?” • “How can I change this thing without breaking it?”

Slide 15

Slide 15 text

You Can’t Go Back • You stop using 3rd party tools without tests • You start re-evaluating how you build code for others • You pay much more attention to interfaces and API’s

Slide 16

Slide 16 text

Where Do You Write Tests? • In development environments • As part of the NORMAL development process • When not prototyping

Slide 17

Slide 17 text

Done By Developers • Cheapest time to find bugs is during development • TDD is an incredibly effective design process • Studies have proven it’s effectiveness

Slide 18

Slide 18 text

Not When Prototyping • No need to write tests when you are experimenting • Once you’ve committed to the idea then TDD takes over to design interfaces and API’s

Slide 19

Slide 19 text

Studies Prove It’s Value • 15% to 30% more development time • 40% to 90% fewer bugs (http://research.microsoft.com/en-us/groups/ese/nagappan_tdd.pdf)

Slide 20

Slide 20 text

“For just one extra day a week you can have 90% fewer bugs show up in production!”

Slide 21

Slide 21 text

When Are Tests Written? • During initial development of functionality • Whenever a bug is reported and needs to be fixed • “Test-after” an anti-pattern but sometimes required

Slide 22

Slide 22 text

During Initial Development • Tests force you to write code in a certain way • Lost opportunity costs are a real thing • Burnout from having to work overtime to fix bugs is a real thing

Slide 23

Slide 23 text

Test-after Considered Harmful • Tests that are decoupled from the act of creating the code are often brittle • Brittle tests are hard to maintain, often randomly failing • Randomly failing tests get ignored

Slide 24

Slide 24 text

Opportunity Costs X vs. 10X vs. 1000X

Slide 25

Slide 25 text

Why Write Tests? • TDD encourages modular code with explicit dependencies • Refactoring and other sweeping changes impossible to do quickly without tests • Tests are stealth documentation on how to use your code

Slide 26

Slide 26 text

Modular Code • TDD makes you focus on loosely-coupled code because of the focus on dependency management • Tightly-coupled code impossible to test without committing huge resources to “monkey-patching” tools or additional infrastructure • The intent of modular code is very clear

Slide 27

Slide 27 text

Refactoring Much Easier • How would you check if your code works with a newer version of PHP? • How could you check if your code works after massive search-and-replace for PSR-2 fixes • How could you test replacing DB calls with calls to a JSON API?

Slide 28

Slide 28 text

Tests As Stealth Documentation • “Write tests as if the code is already working” • They show which dependencies are necessary • They show how the code is actually used

Slide 29

Slide 29 text

Building Blocks It’s Like Using Lego

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Assertions • The backbone of unit testing • Simple to understand

Slide 32

Slide 32 text

Assertions • Unit tests (usually) usually have one or more assertions • Proves that your expectation of an outcome is correct

Slide 33

Slide 33 text

The Simplest Test That Runs

Slide 34

Slide 34 text

Assertions • $this->assertTrue() • $this->assertFalse() • $this->assertEquals(,

Slide 35

Slide 35 text

Assertions Those three assertions will cover 99% of your unit testing needs

Slide 36

Slide 36 text

Test Doubles • Understanding them was the most difficult thing I had to learn • Makes you understand how critical putting dependencies in specific states is

Slide 37

Slide 37 text

Test Doubles • Used as a substitute for the dependencies your code need • Set to a specific state depending on the scenario • Understanding Dependency Injection required

Slide 38

Slide 38 text

Dependency Injection In Unit Tests • Figure out your dependencies • Figure out which ones need to be doubles • “Inject” them for your code-under-test to use

Slide 39

Slide 39 text

Dependency Injection Techniques • Globally-available containers • Constructor injection • Setter injection

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

Constructor Injection • Pass in dependencies at object creation • Gets messy if many dependencies are required • Can lead to __construct() doing too much work

Slide 42

Slide 42 text

Setter Injection • “Less messy” than using constructors • Refactoring to add get/set methods not overly intrusive • Allows overriding of internally-created dependencies

Slide 43

Slide 43 text

Types Of Test Doubles • Classical definition is that there are five types • Dummy objects, test stubs, test spies, test mocks, test fakes

Slide 44

Slide 44 text

Types Of Test Doubles • PHPUnit-compatible test double tools tend to only use three • Dummy objects, test stubs, test mocks

Slide 45

Slide 45 text

Dummy Object • Stand-in for the real dependency • Does not any functionality • Only needs to ‘look like’ the real dependency

Slide 46

Slide 46 text

Dummy Object $mock = Mockery::mock(‘Grumpy\Foo’);

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Stubs $mock = Mockery::mock(‘Grumpy\Foo’); $mock->shouldReceive(‘bar’);

Slide 49

Slide 49 text

Mocks • ‘Stub’ where return value for methods are set • Most common test double you will use

Slide 50

Slide 50 text

Mocks $mock = Mockery::mock(‘Grumpy\Foo’); $mock->shouldReceive(‘bar’) ->andReturn(false);

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

Code Kata I • FizzBuzz! • great exercise for covering programming basics • easily tested

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

FizzBuzz • Take a collection of integers • 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

Slide 57

Slide 57 text

FizzBuzz

Slide 58

Slide 58 text

FizzBuzz

Slide 59

Slide 59 text

FizzBuzz

Slide 60

Slide 60 text

FizzBuzz

Slide 61

Slide 61 text

FizzBuzz

Slide 62

Slide 62 text

FizzBuzz

Slide 63

Slide 63 text

FizzBuzz

Slide 64

Slide 64 text

FizzBuzz

Slide 65

Slide 65 text

FizzBuzz

Slide 66

Slide 66 text

FizzBuzz

Slide 67

Slide 67 text

FizzBuzz

Slide 68

Slide 68 text

Data Providers • Reduce the number of tests you write • Modify test data sets without modifying test

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

Data Providers

Slide 71

Slide 71 text

Data Providers

Slide 72

Slide 72 text

Data Providers

Slide 73

Slide 73 text

Code Kata II • Your turn to do some TDD! • Create an object that turns arabic numbers into Roman Numerals

Slide 74

Slide 74 text

Code Kata II • Use TDD to design your class • Use data providers • Get into writing code in an iterative way

Slide 75

Slide 75 text

Code Kata II 1 -> I 2 -> II 3 -> III 4 -> IV 5 -> V 6 -> VI 7 -> VII 8 -> VIII 9 -> IX 10 -> X 40 -> XL 50 -> L

Slide 76

Slide 76 text

Test Doubles In Action • Replacing “real” dependencies with ones we place in a specific state • Allows us to write tests for code that speaks to data sources and web services

Slide 77

Slide 77 text

Test Doubles In Action

Slide 78

Slide 78 text

Test Doubles In Action

Slide 79

Slide 79 text

Test Doubles In Action

Slide 80

Slide 80 text

Test Doubles In Action

Slide 81

Slide 81 text

A Simple Example

Slide 82

Slide 82 text

A Simple Example

Slide 83

Slide 83 text

A Simple Example

Slide 84

Slide 84 text

A Simple Example

Slide 85

Slide 85 text

Code Kata III • Use TDD to add a method called getAllActive() • Uses fetchAll() to get back a data set that includes id, email, and is_active 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’

Slide 86

Slide 86 text

Code Kata III

Slide 87

Slide 87 text

Code Kata III

Slide 88

Slide 88 text

Code Kata IV • Time to tie it all together! • Create some doubles • Create some assertions • Write a “working” app the TDD way

Slide 89

Slide 89 text

Code Kata IV • Let’s create WidgetTrend • Hit a remote API that gives us the price of various widgets in real time • Store the widget prices in a database

Slide 90

Slide 90 text

Code Kata IV http://127.0.0.1/api/widget/{name of widget}

Slide 91

Slide 91 text

Code Kata IV Save info in a table called ‘widgettracker’ id | name | price | date

Slide 92

Slide 92 text

Code Kata IV • write a test that uses an object that calls the API and then stores the value in the database • you will need a test double for the class that calls the API • you will need a test double for the class that stores information in the database

Slide 93

Slide 93 text

Code Kata IV • Remember to start off with a test that assumes your code is working • Don’t be afraid to explore things until you’ve decided what your code’s interfaces look like. Prototyping is not the time for tests! • Focus on things one test at a time, don’t look ahead to future functionality. Your tests will let you go back and rework things and tell you if you broke something in the process

Slide 94

Slide 94 text

Just The Beginning • Learn the basics • Get into the TDD rhythm • Dig into other testing tools and techniques

Slide 95

Slide 95 text

Thank you! Question time? https://joind.in/talk/62de8