Simple testable code

1,835 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,835
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
23
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • How it all started...I was doing TDD and felt that my code could have been simpler. So I started to think about how to make simpler code while still being able to unit test it. Started a few months ago, so still work in progress, but I want to share what I have concluded so far. Who does refactoring? Who does unit testing? Who does TDD?
  • Software evolves. You will have to go back to the crappy code. Simplicity and testability for maintainability. For fun!
  • As I mentioned, I was doing TDD and was not very satisfied with the results. I'm not saying that TDD is bad, but I want to highlight some problems I have with TDD: Tests direct the design...but is it the simplest design or is it a local minima. Unit tests are often seen as a substitute for thinking...I need to change this, let's change it, check if anything is broken. Unit tests are safety nets, but they have holes...better not to fall. It is not because you are doing TDD that you write good code. TDD with bad test code is dangerous.
  •   Starting point for the reflection.
  • Clean Code is good, but sometimes goes too far. Clean code is more about rules than mindset. I have a problem with the whole software craftmanship...you are not doing TDD then you are not a professional programmer. So I warn you, I'm not a professional programmer, but still getting paid to program.
  • You chose not to go the the session on refactoring...there you go all you need to know :) Writing simple code is good. Evolving simple code is not as easy. That is were refactoring comes into play. Refactoring plays a role in keeping the code simple after each evolution. Unit tests allows refactoring with a safety net. So we need unit tests!
  • Why test in isolation? control: the option to provoke some hard to produce scenarios in real life. to test edge cases. stability: want to investigate real test failures. So we want to test class in isolation...how do we isolate?
  • Show dependencies. Show testable version. Show unit test.
  • That explains why test code can slow down. Test code is fragile! Can we write better tests...tests that would not have to change everytime the production code changes. Test code has to be coupled with the class interface/methods. Test code should not be coupled with the implementation details. Not an easy task...
  • First, keep test code minimal and keep test code simple.
  • When injecting dependencies to a class, you can choose what to inject.
  • This is the hard part... Stop verifying everything you can!
  • I've used EasyMock for years...here is why I switched. Do I care to verify all interactions? Maybe I just care about the result. Do I care if the configuration is accessed 1 or 5 times? Do I want to check all interaction in all tests?
  • Default behavior. Change if needed for a single test. Assert what is tested.
  • Side note... Pattern that both create simple code and easily testable code. Stateless classes.
  • Simple testable code

    1. 1. simple testable code Félix-Étienne Trépanier developer @wajam http://musicdrivendevelopment.com
    2. 2. _why? <ul><li>maintainability </li></ul><ul><li>and </li></ul><ul><li>evolution </li></ul>
    3. 3. ingredients not recipe <ul><li>think     |     follow </li></ul>
    4. 4. coding process <ul><li>understand </li></ul><ul><li>--- </li></ul><ul><li>apply </li></ul>
    5. 5. <ul><li>guard rails design and programming </li></ul><ul><li>even if tested,  bad code kills  </li></ul><ul><li>bad unit test  slows you down </li></ul>
    6. 6. what and how <ul><li>TDD is very similar to getting things done with small children around. I just ask myself, &quot;Now what was I trying to do?&quot; every 5 minutes. </li></ul><ul><li>@ carinmeier </li></ul>
    7. 7. <ul><li>production code </li></ul>focus on...
    8. 8. core values <ul><li>simplicity over flexibility </li></ul><ul><li>concreteness over abstraction </li></ul><ul><li>soft-coupled tests   over  full code coverage </li></ul><ul><li>test aware dev   over  test first dev </li></ul>
    9. 9. simple code <ul><li>Aesthetic simplicity </li></ul><ul><ul><li>clean </li></ul></ul><ul><ul><li>formatted </li></ul></ul><ul><li>Cognitive simplicity </li></ul><ul><ul><li>clear concepts </li></ul></ul><ul><ul><li>logically organized </li></ul></ul><ul><ul><li>No unecessary </li></ul></ul><ul><ul><li>indirection </li></ul></ul><ul><ul><li>small state space </li></ul></ul>
    10. 10. clean code no duplicate code precise and explicit consistent single purpose artifacts
    11. 11. simple code <ul><li>values are simpler than object </li></ul><ul><li>data structures are simpler than classes </li></ul><ul><li>stateless is simpler than stateful </li></ul>
    12. 12. references <ul><ul><li>Clean Code: A Handbook of Agile Software Craftsmanship, Robert C. Martin </li></ul></ul><ul><ul><li>Simple Made Easy, Rich Hickey,   http://www.infoq.com/presentations/Simple-Made-Easy </li></ul></ul><ul><ul><li>The Master, The Expert, The Programmer, Zed Shaw,  http://zedshaw.com/essays/master_and_expert.html </li></ul></ul>
    13. 13. refactoring can save you by @alex_normand
    14. 14. test in isolation <ul><li>speed </li></ul><ul><li>control </li></ul><ul><li>stability </li></ul>
    15. 15. all about dependencies <ul><li>The key to write testable code is to inject some of the class dependencies via constructor ,  method parameters (or setter methods). </li></ul><ul><li>In the test code, test objects are passed to the class under test. </li></ul>
    16. 17. static dependencies <ul><li>Example: MessageSender.java </li></ul><ul><li>The problem is not to depend on concrete classes, but to have static dependencies. </li></ul><ul><li>The new operator is static. </li></ul>
    17. 18. test code paradox <ul><li>test code is strongly coupled to the production code </li></ul>
    18. 19. test code is code! <ul><li>use test libraries </li></ul><ul><li>keep test code clean and simple </li></ul>
    19. 20. use the right test object <ul><li>dynamic mock : Provided by unit test libraries such as Mockito. Simple to use and limit the amount of test code to a minimum. </li></ul><ul><li>production code : Add dependencies to the production code. Easier with behavior-less classes such as data holder. </li></ul><ul><li>hand coded mock : May be needed if behavior to mock is complex. Can be really painful to maintain. </li></ul>
    20. 21. assert behavior not implementation <ul><ul><li>Testing implementation makes the test code fragile </li></ul></ul><ul><ul><li>Verify return values and mandatory side effects </li></ul></ul><ul><ul><li>Avoid asserting more than needed </li></ul></ul><ul><ul><li>One assert per test? </li></ul></ul>
    21. 22. easy with EasyMock
    22. 23. assert only what is needed
    23. 24. stateless <ul><li>Example: Statefull/StatelessProcessor.java </li></ul><ul><li>Stateless classes have no state space. </li></ul><ul><li>Stateless classes have do not worry about multithreading. </li></ul><ul><li>Stateless classes are simpler to setup for test. </li></ul>
    24. 25. summary <ul><ul><li>aesthetic simplicity </li></ul></ul><ul><ul><li>cognitive simplicity </li></ul></ul><ul><ul><li>refactoring to keep code simple </li></ul></ul><ul><ul><li>inject dependencies </li></ul></ul><ul><ul><li>minimal test code </li></ul></ul><ul><ul><li>behavior validation </li></ul></ul>

    ×