$30 off During Our Annual Pro Sale. View Details »

Grumpy Testing Patterns

Grumpy Testing Patterns

Slides from my "Grumpy Testing Patterns" talk that I gave at PHP Australia Conference on April 15, 2016

Chris Hartjes

April 14, 2016
Tweet

More Decks by Chris Hartjes

Other Decks in Technology

Transcript

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

    View Slide

  2. View Slide

  3. View Slide

  4. Personal Opinions Ahead

    View Slide

  5. This isn’t about shaming people

    View Slide

  6. Testing has been around almost as
    long as computer science itself

    View Slide

  7. It pre-dates the rise of the internet

    View Slide

  8. View Slide

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

    View Slide

  10. 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?

    View Slide

  11. View Slide

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

    View Slide

  13. View Slide

  14. View Slide

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

    View Slide

  16. 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

    View Slide

  17. 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

    View Slide

  18. View Slide

  19. View Slide

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

    View Slide

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

    View Slide

  22. View Slide

  23. 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

    View Slide

  24. View Slide

  25. View Slide

  26. View Slide

  27. View Slide

  28. Small objects with few methods

    View Slide

  29. View Slide

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

    View Slide

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

    View Slide

  32. 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

    View Slide

  33. 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?

    View Slide

  34. View Slide

  35. View Slide

  36. View Slide

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

    View Slide

  38. View Slide

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

    View Slide

  40. Not all smelly code is wrong

    View Slide

  41. Other things I see people doing

    View Slide

  42. View Slide

  43. View Slide

  44. View Slide

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

    View Slide

  46. View Slide

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

    View Slide

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

    View Slide

  49. 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”

    View Slide

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

    View Slide

  51. Not all smelly tests are wrong

    View Slide

  52. They represent things to keep an
    eye on going forward

    View Slide

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

    View Slide

  54. “The tools are hard to use”

    View Slide

  55. The problem isn’t the tools

    View Slide

  56. The problem is
    unrealistic expectations

    View Slide

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

    View Slide

  58. Grumpy’s 4 Steps
    To Test Mastery

    View Slide

  59. Step The First:
    Figure out your dependencies

    View Slide

  60. Step The Second:
    Figure out your expected outcome

    View Slide

  61. Step The Third:
    Write the test like everything already works

    View Slide

  62. Step The Last:
    Write code until the test passes

    View Slide

  63. Want to learn more?
    Search Github

    View Slide

  64. Really.
    Best place ever to find tests.

    View Slide

  65. https://github.com/opencfp/opencfp

    View Slide

  66. “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.”

    View Slide

  67. View Slide

  68. Handling The
    Weird Stuff

    View Slide

  69. Understanding Test Doubles

    View Slide

  70. (people call them mocks)

    View Slide

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

    View Slide

  72. Creating doubles ONLY WHEN
    REQUIRED is a good practice

    View Slide

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

    View Slide

  74. 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

    View Slide

  75. 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?

    View Slide

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

    View Slide

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

    View Slide

  78. View Slide

  79. View Slide

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

    View Slide

  81. View Slide

  82. Mockery is awesome
    Kahlan is awesome

    View Slide

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

    View Slide

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

    View Slide

  85. Verifying code got executed in your
    tests is EASY

    View Slide

  86. You can use XDebug
    or new native support

    View Slide

  87. Code coverage reports are
    criminally underused

    View Slide

  88. I know we covered
    a lot of stuff

    View Slide

  89. Maybe too much?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide