Slide 1

Slide 1 text

Grumpy Testing Patterns Chris Hartjes PHP Australia Conference April 15, 2016

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Personal Opinions Ahead

Slide 5

Slide 5 text

This isn’t about shaming people

Slide 6

Slide 6 text

Testing has been around almost as long as computer science itself

Slide 7

Slide 7 text

It pre-dates the rise of the internet

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

It’s never too late to care about automated tests for your application

Slide 10

Slide 10 text

So you’ve decided to write tests ❖ Is your code ready to test? ❖ Do you understand the testing tools? ❖ Do you understand some common testing patterns?

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

What Do I Like To See? ❖ Dependency injection in use ❖ Small objects with few methods ❖ Bootstrapping that allows for easy overriding

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Don’t Lose Control ❖ Dependencies you cannot control means tests you cannot write ❖ Untested code can lead to weird bugs and unanticipated behaviour

Slide 16

Slide 16 text

How To Control Dependencies ❖ Think of your program flow as “message passing” ❖ Refactor code to create required dependencies outside of where they are used ❖ No shame in incremental refactoring towards testability

Slide 17

Slide 17 text

Dependency Management As “Message Passing” ❖ Architect your application so results and dependencies flow through it ❖ Keep “side effects” to a minimum ❖ Give opportunities for tests to create doubles of dependencies that need to be in specific states

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Taming Side Effects ❖ in-memory databases using SQLite ❖ in-memory file systems using vfsStream ❖ “dependency overloading” using Mockery

Slide 21

Slide 21 text

In-Memory Databases ❖ Eliminates the side effect of modifying common databases ❖ Much better control over initial data sets

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

In-Memory Filesystems ❖ great for tests that need to read and/or write files ❖ no need to write code to clean up data after testing

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

Small objects with few methods

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

“Using Test-Driven Development tends to result in large numbers of objects with small numbers of methods. Single responsibility principle in action!”

Slide 31

Slide 31 text

“Again, your tests suck because your code sucks. No. Really.”

Slide 32

Slide 32 text

How To Detect Smelly Code ❖ Your tests require extensive setup steps ❖ Your code to set dependencies fills your editor screen ❖ It’s extremely difficult to tell if you’re getting the expected results

Slide 33

Slide 33 text

Extensive Setup Steps ❖ Does your app have complicated bootstrapping? ❖ Does it rely on hard-coded values for configuration options? ❖ How hard is it to swap out dependencies?

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

For those counting along: 24 lines of setup 5 lines of tests

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

For those counting along: 24 lines of setup 5 lines of tests for 7 lines of code

Slide 40

Slide 40 text

Not all smelly code is wrong

Slide 41

Slide 41 text

Other things I see people doing

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

“DO YOU NOT NOTICE HOW SIMILAR ALL THESE TESTS ARE?!?.”

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

“Just like duplicated code can be bad, duplicated tests can be bad.”

Slide 48

Slide 48 text

What else do I see that I don’t like?

Slide 49

Slide 49 text

Avoid These ❖ conditional statements in your tests! ❖ loops in your tests! ❖ creating a test double of the thing you are testing just so “the damn thing works”

Slide 50

Slide 50 text

“I’m sure I missed your favourite underused technique that is actually just lazy.”

Slide 51

Slide 51 text

Not all smelly tests are wrong

Slide 52

Slide 52 text

They represent things to keep an eye on going forward

Slide 53

Slide 53 text

Do You Understand The Tools? ❖ Do you know how to use the testing framework ❖ Do you know how test doubles work?

Slide 54

Slide 54 text

“The tools are hard to use”

Slide 55

Slide 55 text

The problem isn’t the tools

Slide 56

Slide 56 text

The problem is unrealistic expectations

Slide 57

Slide 57 text

Tests are code you write to prove your other code is right

Slide 58

Slide 58 text

Grumpy’s 4 Steps To Test Mastery

Slide 59

Slide 59 text

Step The First: Figure out your dependencies

Slide 60

Slide 60 text

Step The Second: Figure out your expected outcome

Slide 61

Slide 61 text

Step The Third: Write the test like everything already works

Slide 62

Slide 62 text

Step The Last: Write code until the test passes

Slide 63

Slide 63 text

Want to learn more? Search Github

Slide 64

Slide 64 text

Really. Best place ever to find tests.

Slide 65

Slide 65 text

https://github.com/opencfp/opencfp

Slide 66

Slide 66 text

“There are too many examples of well-written tests and clear instructions for people to claim ignorance of how to write tests or use the tools to execute them.”

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

Handling The Weird Stuff

Slide 69

Slide 69 text

Understanding Test Doubles

Slide 70

Slide 70 text

(people call them mocks)

Slide 71

Slide 71 text

Test Doubles “Use them when you have a dependency that is not under your control that needs to be in a specific state.”

Slide 72

Slide 72 text

Creating doubles ONLY WHEN REQUIRED is a good practice

Slide 73

Slide 73 text

So What Should We Double? ❖ database connections ❖ code that calls 3rd party API’s ❖ code that has side effects

Slide 74

Slide 74 text

Database Connections? ❖ does your unit test REALLY need to make sure the database is working ❖ lets you control the expected responses in terms of result sets or record ID’s

Slide 75

Slide 75 text

3rd Party API’s? ❖ API use could be restricted (rate-limited, sandboxed for tests, pay-per-use) ❖ Again, are we in the business of testing their API or testing our code?

Slide 76

Slide 76 text

“As an aside, consider the use of contract-style tests as part of your integration test suite”

Slide 77

Slide 77 text

Weird Stuff To Test ❖ dependencies that you cannot inject without risky refactoring ❖ getters and setters ❖ how to verify execution of specific code

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

No content

Slide 80

Slide 80 text

Using “Monkey Patching” ❖ can override almost anything ❖ the overrides are globally available… ❖ …so annotate tests to run in separate process

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

Mockery is awesome Kahlan is awesome

Slide 83

Slide 83 text

Having to test that a non-public method works is a testing smell

Slide 84

Slide 84 text

Having to test the contents and/or state of a protected attribute is a test smell

Slide 85

Slide 85 text

Verifying code got executed in your tests is EASY

Slide 86

Slide 86 text

You can use XDebug or new native support

Slide 87

Slide 87 text

Code coverage reports are criminally underused

Slide 88

Slide 88 text

I know we covered a lot of stuff

Slide 89

Slide 89 text

Maybe too much?

Slide 90

Slide 90 text

Shameless Self-Promotion https://leanpub.com/minimumviabletests http://grumpy-phpunit.com

Slide 91

Slide 91 text

Ways To Get In Touch ❖ email: [email protected] ❖ Twitter: @grmpyprogrammer ❖ IRL: actually speak to me, I won’t hurt you

Slide 92

Slide 92 text

https://speakerdeck.com/ grumpycanuck/smelly-tests https://joind.in/14937