Unit testing best practices

31,159 views

Published on

Published in: Technology, Business
1 Comment
51 Likes
Statistics
Notes
  • More than 5000 IT Certified ( SAP,Oracle,Mainframe,Microsoft and IBM Technologies etc...)Consultants registered. Register for IT courses at http://www.todaycourses.com Most of our companies will help you in processing H1B Visa, Work Permit and Job Placements
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
31,159
On SlideShare
0
From Embeds
0
Number of Embeds
1,833
Actions
Shares
0
Downloads
1,291
Comments
1
Likes
51
Embeds 0
No embeds

No notes for slide

Unit testing best practices

  1. 1. www.nickokiss.com
  2. 2. Production code Purpose: Meet business (functional) requirements Meet non-functional (system) requirements Code Tests code Purpose: Testing Documentation Specification
  3. 3. Production code Purpose: Meet business (functional) requirements Meet non-functional (system) requirements Code Tests code Purpose: Testing Documentation Specification Different Different purpose = best practices
  4. 4. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  5. 5. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  6. 6. 3 steps Prepare an input Call a method Check an output
  7. 7. 3 steps (5 steps) Set up Prepare an input Call a method Check an output Tear down
  8. 8. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  9. 9. Execution time - be fast Why is it so important? Frequent execution Several times per day [Test-after development] Several times per hour [Test driven development] Every few minutes [IDE - Execute after save] Execution in groups 10 tests = Execution time x 10 100 tests = Execution time x 100 Weak link: a slow test slows the whole suite
  10. 10. Execution time - be fast What are the good numbers? Expected average execution time in unit testing Single test: <200ms Small suite: <10s All tests suite: <10min
  11. 11. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  12. 12. Consistent Multiple invocations of the test should consistently return true or consistently return false, provided no changes was made on code. What code can cause problems? Date currentDate = new Date(); int value = random.nextInt(100); How to deal with this? Mocks Dependency injection
  13. 13. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  14. 14. Atomic Only two possible results: Pass or Fail No partially successful tests A test fails -> The whole suite fails Broken window effect
  15. 15. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  16. 16. Single responsibility One test should be responsible for one scenario only. Test behaviour, not methods: One method, multiple behaviours Multiple tests One behaviour, multiple methods One test A method calls private and protected methods A method calls very simple public methods (Especially: getters, setters, value objects, simple constructors) Multiple asserts in the same test - acceptable as long as they check the same behaviour
  17. 17. Single responsibility One method, multiple behaviours testMethod(){ testMethodCheckBehaviour1(){ ... ... assertTrue(behaviour1); assertTrue(behaviour1); assertTrue(behaviour2); } assertTrue(behaviour3); testMethodCheckBehaviour2(){ } ... assertTrue(behaviour2); } testMethodCheckBehaviour3(){ ... assertTrue(behaviour3); }
  18. 18. Single responsibility Behaviour1 = condition1 + condition2 + condition3 Behaviour2 = condition4 + condition5 testMethodCheckBehaviours(){ testMethodCheckBehaviour1(){ ... assertTrue ... (condition1); assertTrue assertTrue(condition1); (condition2); assertTrue assertTrue(condition2); (condition3); assertTrue(condition3); ... assertTrue } (condition4); testMethodCheckBehaviour2(){ assertTrue(condition5); ... } assertTrue(condition4); assertTrue(condition5); }
  19. 19. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  20. 20. Tests isolation Tests should be independent from one another Different execution order - the same results No state sharing Instance variables JUnit - separated TestNG - shared
  21. 21. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  22. 22. Environment isolation Unit tests should be isolated from any environmental influences Database access Webservices calls JNDI look up Environment variables Property files System date and time
  23. 23. Environment isolation Production code: A class heavily uses the environment myMethod() { ... ... ... }
  24. 24. Environment isolation Under unit testing: It doesn't work! testMyMethod() { myMethod() { ... ... myClass.myMethod ... (...) ... ... } }
  25. 25. Environment isolation Solution: Use mocks testMyMethod() { myMethod() { ... ... myClass.myMethod ... (...) ... ... } }
  26. 26. Environment isolation Solution: Use mocks Advantages: No test logic in production code Fast Easy to write Easy to re-use
  27. 27. Environment isolation Solution: Use mocks Java mocking libraries (open source): EasyMock [ www.easymock.org ] JMock [ www.jmock.org ] Mockito [ www.mockito.org ]
  28. 28. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  29. 29. Classes isolation The less methods are executed by the test, the better (better code maintenance) The less tests execute the method the better (better tests maintenance)
  30. 30. Classes isolation BUT: high code coverage is a must (ideally 100%)
  31. 31. Classes isolation The less methods are executed by the test, the better (better code maintenance) high code coverage is a must (ideally 100%) The less tests execute the method the better (better tests maintenance)
  32. 32. Classes isolation Let's come back to our previous example to ilustrate the problem Step 0: The class under test has no dependencies
  33. 33. Classes isolation Let's come back to our previous example to ilustrate the problem Step 1: The class depends on some other classes
  34. 34. Classes isolation Let's come back to our previous example to ilustrate the problem Step 2: Dependencies of dependencies
  35. 35. Classes isolation Let's come back to our previous example to ilustrate the problem Step 3: Dependencies of dependencies of dependencies
  36. 36. Classes isolation Let's come back to our previous example to ilustrate the problem Step 4, 5, 6,...
  37. 37. Classes isolation Conclusion: Mocking the environment is not enough
  38. 38. Classes isolation Solution: Mock dependencies!
  39. 39. Classes isolation Solution: Mock dependencies!
  40. 40. Classes isolation Can be hard if code is not testable How to write testable code? Don't call constructors inside a method. Use factories or dependency injection Use interfaces
  41. 41. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  42. 42. Fully automated No manual steps involved into testing. Automated tests execution Automated results gathering Automated decision making (success or failure) Automated results distribution Email IM System tray icon Dashboard web page IDE integration Lava lamps
  43. 43. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  44. 44. Self-descriptive Unit test = development level documentation Unit test = method specification which is always up to date
  45. 45. Self-descriptive Unit test must be easy to read and understand Variable names Method names Class names } No conditional logic Self-descriptive No loops
  46. 46. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  47. 47. No conditional logic Correctly written test contains no "if" or "switch" statements. No uncertainty All input values should be known Method behaviour should be predictible Expected output should be strict Split the test into two (or more) tests instead of adding "if" or "switch" statement.
  48. 48. No conditional logic One test, multiple conditions testMethodBeforeOrAfter(){ testMethodBefore(){ ... before = true; if (before) { assertTrue(behaviour1); assertTrue(behaviour1); } } else if (after) { testMethodAfter(){ assertTrue(behaviour2); after = true; } else { //now assertTrue(behaviour2); assertTrue(behaviour3); } } testMethodNow(){ } before = false; after = false; assertTrue(behaviour3); }
  49. 49. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  50. 50. No loops High quality test contains no "while", "do-while" or "for" statements. Typical scenarios involving loops: Hundreds of repetitions A few repetitions Unknown number of repetitions
  51. 51. No loops Case 1: Hundreds of repetitions If some logic in a test has to be repeated hundreds of times, it probably means that the test is too complicated and should be simplified.
  52. 52. No loops Case 2: A few repetitions Repeating things several times is OK, but then it's better to type the code explicitly without loops.You can extract the code which needs to be repeated into method and invoke it a few times in a row.
  53. 53. No loops Case 3: Unknown number of repetitions If you don't know how many times you want to repeat the code and it makes you difficult to avoid loops, it's very likely that your test is incorrect and you should rather focus on specifying more strict input data.
  54. 54. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  55. 55. No exception catching Catch an exception only if it's expected Catch only expected type of an exception Catch expected exception and call "fail" method Let other exceptions go uncatched
  56. 56. Catching expected exception testThrowingMyException(){ try { myMethod(param); fail("MyException expected"); } catch(MyException ex) { //OK } }
  57. 57. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  58. 58. Assertions Use various types of assertions provided by a testing framework Create your own assertions to check more complicated, repetitive conditions Reuse your assertion methods Loops inside assertions can be a good practice
  59. 59. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  60. 60. Informative assertion messages By reading an assertion message only, one should be able to recognize the problem. It's a good practice to include business logic information into assertion message. Assertion messages: Improve documentation of the code Inform about the problem in case of test failure
  61. 61. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in Classes isolation production code Fully automated Separation per business Self-descriptive module Separation per type
  62. 62. No test logic in production code Separate unit tests and production code Don't create methods/fields used only by unit tests Use "Dependency Injection"
  63. 63. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  64. 64. Separation per business module Create suites of tests per business module Use hierarchical approach Decrease the execution time of suites by splitting them into smaller ones (per sub-module) Small suites can be executed more frequently
  65. 65. Unit testing best practices 3 steps No conditional logic Fast No loops Consistent No exception catching Atomic Assertions Single responsibility Informative assertion Tests isolation messages Environment isolation No test logic in production Classes isolation code Fully automated Separation per business Self-descriptive module Separation per type
  66. 66. Separation per type Keep unit tests separated from integration tests Different purpose of execution Different frequency of execution Different time of execution Different action in case of failure
  67. 67. Thank you! Find out more on: http://www.nickokiss.com/2009/09/unit-testing.html www.nickokiss.com

×