www.nickokiss.com
Production code
       Purpose:
          Meet business (functional) requirements
          Meet non-functional (system)
 ...
Production code
        Purpose:
           Meet business (functional) requirements
           Meet non-functional (system...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
3 steps



Prepare an input

Call a method

Check an output
3 steps (5 steps)

Set up

Prepare an input

Call a method

Check an output

Tear down
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Execution time - be fast

Why is it so important?


Frequent execution
   Several times per day [Test-after development]
 ...
Execution time - be fast

What are the good numbers?



Expected average execution time in unit testing
   Single test: <2...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Consistent
Multiple invocations of the test should consistently return true or
consistently return false, provided no chan...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Atomic




Only two possible results: Pass or Fail
No partially successful tests
A test fails -> The whole suite fails
Bro...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Single responsibility

One test should be responsible for one scenario only.


Test behaviour, not methods:

   One method...
Single responsibility
    One method, multiple behaviours


testMethod(){                 testMethodCheckBehaviour1(){
   ...
Single responsibility
  Behaviour1 = condition1 + condition2 + condition3
  Behaviour2 = condition4 + condition5


testMet...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Tests isolation
Tests should be independent from one another


  Different execution order - the same results

  No state ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Environment isolation
Unit tests should be isolated from any environmental influences




       Database access
       We...
Environment isolation
Production code: A class heavily uses the
environment




            myMethod() {
              ......
Environment isolation
                     Under unit testing: It doesn't work!




testMyMethod() {          myMethod() {...
Environment isolation
                     Solution: Use mocks




testMyMethod() {         myMethod() {
  ...            ...
Environment isolation
     Solution: Use mocks




Advantages:
   No test logic in production code
   Fast
   Easy to writ...
Environment isolation
     Solution: Use mocks




Java mocking libraries (open source):
   EasyMock [ www.easymock.org ]
...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Classes isolation



The less methods are executed by the test, the better
                                    (better cod...
Classes isolation



           BUT:

high code coverage is a must
                      (ideally 100%)
Classes isolation

  The less methods are
  executed by the test, the
  better
  (better code maintenance)

              ...
Classes isolation
Let's come back to our previous example to ilustrate the
problem

Step 0: The class under test has no de...
Classes isolation
Let's come back to our previous example to ilustrate the
problem

Step 1: The class depends on some othe...
Classes isolation
Let's come back to our previous example to ilustrate the
problem

Step 2: Dependencies of dependencies
Classes isolation
Let's come back to our previous example to ilustrate the
problem

Step 3: Dependencies of dependencies o...
Classes isolation
Let's come back to our previous example to ilustrate the
problem

Step 4, 5, 6,...
Classes isolation
Conclusion: Mocking the environment is not enough
Classes isolation
Solution: Mock dependencies!
Classes isolation
Solution: Mock dependencies!
Classes isolation


Can be hard if code is not testable



How to write testable code?

   Don't call constructors inside ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Fully automated
No manual steps involved into testing.

     Automated tests execution
     Automated results gathering
  ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Self-descriptive



Unit test = development level documentation



Unit test = method specification
               which i...
Self-descriptive
Unit test must be easy to read and understand



     Variable names
     Method names
     Class names  ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
No conditional logic
Correctly written test contains no "if" or "switch"
statements.


No uncertainty
   All input values ...
No conditional logic
    One test, multiple conditions


testMethodBeforeOrAfter(){     testMethodBefore(){
     ...      ...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
No loops
High quality test contains no "while", "do-while" or "for"
statements.



Typical scenarios involving loops:

   ...
No loops

 Case 1: Hundreds of repetitions

If some logic in a test has to be repeated hundreds of
times, it probably mean...
No loops

Case 2: A few repetitions


Repeating things several times is OK, but then it's better to
type the code explicit...
No loops

Case 3: Unknown number of repetitions


If you don't know how many times you want to repeat the
code and it make...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
No exception catching

Catch an exception only if it's expected

Catch only expected type of an exception

Catch expected ...
Catching expected exception



testThrowingMyException(){
    try {
      myMethod(param);
      fail("MyException expecte...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Assertions

Use various types of assertions provided by a testing
framework

Create your own assertions to check more
comp...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Informative assertion messages
By reading an assertion message only, one should be
able to recognize the problem.


It's a...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
No test logic in production code

Separate unit tests and production code

Don't create methods/fields used only by unit t...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Separation per business module

Create suites of tests per business module

Use hierarchical approach

Decrease the execut...
Unit testing best practices

3 steps                 No conditional logic
Fast                    No loops
Consistent     ...
Separation per type

Keep unit tests separated from integration tests

   Different purpose of execution

   Different fre...
Thank you!


                Find out more on:

http://www.nickokiss.com/2009/09/unit-testing.html




                   ...
Upcoming SlideShare
Loading in...5
×

Unit testing best practices

24,900

Published on

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

No Downloads
Views
Total Views
24,900
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
1,033
Comments
0
Likes
37
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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×