Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Unit testing - the hard parts

1,163 views

Published on

Unit testing has entered the main stream. It is generally considered best practice to have a high level of unit test code coverage, and to ideally write tests before the code, via Test Driven Development.

However, some code is just plain difficult to test. The cost of effort of adding the tests may seem to outweigh the benefits. In this session, we will do a quick review of the benefits of unit tests, but focus on how to test tricky code, such as that static and private methods, and legacy code in general.

Examples are in Java, but the principals are language agnostic.

Published in: Software

Unit testing - the hard parts

  1. 1. Shaun Abram Unit Testing The hard parts October 10th, 2015
  2. 2. Shaun Abram 2 Test Obsessed? How much do you know… Test coverage Dependency Injection Mock vs stubs Testing private or static methods Test driven development
  3. 3. Shaun Abram 3 What is a unit test? A piece of code that executes a specific functionality (‘unit’) in the code, and Confirms behavior or result is as expected Determines if code is ‘fit for use’ Does it do what the developer intended? Before, we manually verified, but not easily repeatable.
  4. 4. Shaun Abram 4 Why unit test? Economics $ but also… Drive design Create defensive code against bad input Act as safety buffers for regression bugs Provide documentation Clean code Less bugs
  5. 5. Shaun Abram 5 What is a unit?  A class? A method? A single path through a method?  The smallest testable part of an application.  A single functional use case.
  6. 6. Shaun Abram 6 What makes a good unit test? Provides benefit! Readable, Understandable, Maintainable Independent run in any order, no DB or File access Consistent / deterministic Runs fast Tests a single logical concept in the system
  7. 7. Shaun Abram 7 Unit testing limitations  Can not prove the absence of bugs  Lot’s of code (x3-5)  Some things difficult to test
  8. 8. Shaun Abram 8 Dependency Injection
  9. 9. 9
  10. 10. 10 Dependency Injection  Useful for testing – inject test doubles  Also helps reduce coupling
  11. 11. Shaun Abram 11 Test Doubles Mocks Stubs Dummies Spies Fakes
  12. 12. Shaun Abram 12 Test Doubles Mocks Stubs Dummies Spies Fakes
  13. 13. Shaun Abram 13 Test Doubles: Mocks Mocks: An overloaded term! uses behavior verification objects pre-programmed with expectations
  14. 14. 14
  15. 15. 15  Mocks use behavior verification  Can specify how to respond when called  Roll your own?
  16. 16. Shaun Abram 16 Test Doubles Mocks Stubs Dummies Spies Fakes
  17. 17. Shaun Abram 17 Test Doubles: Stubs ‘stubs out’ or provides a simplified version of the implementation for the purposes of testing
  18. 18. 18
  19. 19. 19  Stubs can use state or behavior verification  Provides a useful approach for test fixture configurability
  20. 20. Shaun Abram 20 Test Doubles Mocks Stubs Dummies Spies Fakes
  21. 21. Shaun Abram 21 Test Doubles: Dummies A very dumb class! Contains next to nothing - enough to compile Pass when you don’t expect to be used
  22. 22. 22  Use dummies with state or behavior verification  Can create as inner class  Can replicate with mocks
  23. 23. Shaun Abram 23 Unit Testing – the tricky parts Legacy code Privates Statics
  24. 24. Shaun Abram 24 General approach to testing legacy code 1) Start with coarse grained tests No modifications Strict and rigid Detect regressions Short term bridges - delete
  25. 25. Shaun Abram 25 General approach to testing legacy code 1) Start with coarse grained tests 2) Add finer grained tests Incrementally add more unit start gently refactoring Use TDD – if possible Test from 1) should protect you
  26. 26. Shaun Abram 26 General approach to testing legacy code 1) Start with coarse grained tests 2) Add finer grained tests 3) Continuously refactor Use patterns such as Extract Method/Class Move Method/Field tease apart methods (>10 lines smells)
  27. 27. Shaun Abram 27 Unit Testing – the tricky parts Legacy code Privates Statics
  28. 28. Shaun Abram 28 How do you test private methods? Indirectly! Best tested via public interface But sometimes… Legacy code With limited capability to refactor, or adding a safety net before refactoring A public method calls several private methods, each with complex logic
  29. 29. Shaun Abram 29 Testing Private Methods 1. Refactor 2. Change the visibility Bad practice Public API? Very bad practice! Internal & stepping stone -> lesser evil Java private -> package; .Net protected or internal? Document (@VisibleForTesting)
  30. 30. Shaun Abram 30 Testing Private Methods 1. Refactor 2. Change the visibility 3. Use Reflection No code modification, but… 4. Other options… Testing frameworks InternalsVisibleToAttribute Private Accessors
  31. 31. Shaun Abram 31 Testing static methods
  32. 32. 32
  33. 33. 33
  34. 34. 34
  35. 35. Shaun Abram 35 Testing static methods DI ideal But sometimes not pragmatic
  36. 36. 36
  37. 37. 37 Refactor to wrap the static call in an instance method Which can then be mocked…
  38. 38. 38
  39. 39. 39
  40. 40. 40
  41. 41. Shaun Abram 41 Testing static methods Refactor – use DI Wrap static call in a instance method Use a mocking framework?
  42. 42. Shaun Abram 42 Test Driven Development
  43. 43. Shaun Abram 43 Test Driven Development
  44. 44. Shaun Abram 44 Test Driven Development
  45. 45. Shaun Abram 45 Test Driven Development
  46. 46. Shaun Abram 46 Test Driven Development
  47. 47. Shaun Abram 47 Test Driven Development Red - Green – Refactor: the TDD Mantra No new functionality without a failing test No refactoring without passing tests
  48. 48. Shaun Abram 48 Test Driven Development Example…
  49. 49. Shaun Abram 49 Test Driven Development Example… Create a StringCalculator class with an add method which takes a comma separate String of numbers and returns their sum. Example input Result 0 1 1 2 2 1,2 3 1,2,100 103
  50. 50. Refactor?
  51. 51. Refactor?
  52. 52. These tests act like the original developer looking over your shoulder and advising you, long after that developer has left… These tests act like the original developer looking over your shoulder and advising you, long after that developer has left…
  53. 53. Shaun Abram 71 Recommended reading Growing Object-Oriented Software, Guided by Tests Freeman & Pryce Test Driven Development Kent Beck Refactoring: Improving the Design of Existing Code Martin Fowler, Kent Beck et. al. Effective Unit Testing Lasse Koskela
  54. 54. Shaun Abram 72 Recommended reading Unit Test Best Practices - https://wiki.tlcinternal.com/display/TD/Unit+Test+Best+Practices Mocks Arent Stubs - http://www.martinfowler.com/articles/mocksArentStubs.html

×