Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Smelly Tests

27601bca8f38e75cbcf9d2dc843f0b32?s=47 Chris Hartjes
September 09, 2015

Smelly Tests

A rapid-fire look at the overall concepts surrounding writing effective unit tests and some tips on how to avoid tests that are as smelly as the code they are trying to protect

27601bca8f38e75cbcf9d2dc843f0b32?s=128

Chris Hartjes

September 09, 2015
Tweet

Transcript

  1. Even Chris sometimes writes… Smelly Tests Chris Hartjes Pacific Northwest

    PHP September 12, 2015
  2. None
  3. – talk description “You're now writing unit tests for your

    code...but you can't help but wonder if you are writing them the Right Way(tm). Given that learning to write good tests is no different from learning to write good code, it's inevitable that we make mistakes as we learn to create effective unit test suites.”
  4. This isn’t about shaming people

  5. By writing tests you are doing more than the vast

    majority of PHP developers
  6. Testing has been around almost as long as computer science

    itself
  7. It pre-dates the rise of the internet

  8. None
  9. It’s never too late to care about automated tests for

    your application
  10. So you’ve decided to write tests ❖ Is your code

    ready to test? ❖ Do you understand the testing tools? ❖ Do you understand common testing patterns?
  11. None
  12. What Do I Like To See? ❖ Dependency injection in

    use ❖ Small objects with few methods ❖ Bootstrapping that allows for easy overriding
  13. None
  14. None
  15. Don’t Lose Control ❖ Dependencies you cannot control means tests

    you cannot write ❖ Untested code can lead to weird bugs and unanticipated behaviour
  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 refactoring towards using globally- available containers
  17. Dependency Managermane 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
  18. None
  19. None
  20. Taming Side Effects ❖ in-memory databases using SQLite ❖ in-memory

    file systems using vfsStream ❖ “dependency overloading” using Mockery
  21. In-Memory Databases ❖ Eliminates the side effect of modifying common

    databases ❖ Much better control over initial data sets
  22. None
  23. In-Memory Filesystems ❖ great for tests that need to read

    and/or write files ❖ no need to write code to clean up files after testing
  24. None
  25. None
  26. None
  27. None
  28. Small objects with few methods

  29. None
  30. – some grumpy developer speaking to you “Using Test-Driven Development

    tends to result in large numbers of objects with small numbers of methods. Single responsibility principle in action!”
  31. None
  32. None
  33. – me “Again, your tests smell because your code smells.

    No. Really.”
  34. 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
  35. 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?
  36. None
  37. None
  38. None
  39. For those counting along: 24 lines of setup 5 lines

    of tests
  40. None
  41. For those counting along: 24 lines of setup 5 lines

    of tests for 7 lines of code
  42. Not all smelly code is wrong

  43. Other things I see people doing

  44. None
  45. None
  46. None
  47. – a parent who hates repeating himself to his children

    “DO YOU NOT NOTICE HOW SIMILAR ALL THESE TESTS ARE?!?.”
  48. None
  49. – guy who never wishes for clones of himself “Just

    like duplicated code can be bad, duplicated tests can be bad.”
  50. What else do I see that I don’t like?

  51. Don’t Do 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”
  52. – developer who shouldn’t manage people “I’m sure I missed

    your favourite underused technique that is actually just lazy.”
  53. Not all smelly tests are wrong

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

  55. Do You Understand The Tools? ❖ Do you know how

    to use the testing framework ❖ Do you know how test doubles work?
  56. “The tools are hard to use”

  57. Personal Opinions Ahead

  58. The problem isn’t the tools

  59. The problem is unrealistic expectations

  60. Tests are code you write to prove your other code

    is right
  61. Grumpy’s 4 Steps To Test Mastery

  62. Step The First: Figure out your dependencies

  63. Step The Second: Figure out you expected outcome

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

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

  66. Want to learn more? Search Github

  67. Really. Best place ever to find tests.

  68. https://github.com/opencfp/opencfp

  69. –Chris Hartjes “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.”
  70. None
  71. Handling The Weird Stuff

  72. Understanding Test Doubles

  73. (people call them mocks)

  74. Test Doubles – husband of the most patient woman in

    the world “Use them when you have a dependency that is not under your control that needs to be in a specific state.”
  75. Creating doubles ONLY WHEN REQUIRED is a good practice

  76. So What Should We Double? ❖ database connections ❖ code

    that calls 3rd party API’s ❖ code that has side effects
  77. 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
  78. 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?
  79. – some guy who knows a thing or two about

    testing “As an aside, consider the use of contract-style tests as part of your integration test suite”
  80. Weird Stuff To Test ❖ dependencies that you cannot inject

    without risky refactoring ❖ getters and setters ❖ how to verify execution of specific code
  81. None
  82. None
  83. Using “Overloading” ❖ can override almost anything ❖ the overrides

    are globally available… ❖ …so annotate tests to run in separate process
  84. None
  85. Mockery is awesome

  86. Getters and Setters Considered Harmful?

  87. Having to test that a non-public method works is a

    testing smell
  88. Having to test the contents and/or state of a protected

    attribute is a test smell
  89. Verifying code got executed in your tests is EASY

  90. You can use XDebug or new native support

  91. None
  92. Code coverage reports are criminally underused

  93. I know we covered a lot of stuff

  94. Maybe too much?

  95. Shameless Self-Promotion http://grumpy-testing.com http://grumpy-phpunit.com

  96. Ways To Get In Touch ❖ email: chartjes@grumpy-learning.com ❖ Twitter:

    @grmpyprogrammer ❖ IRL: actually speak to me, I won’t hurt you
  97. https://speakerdeck.com/ grumpycanuck/smelly-tests