This document summarizes recent discussions and thinking around unit testing, that should become the foundation for a handbook:
- outlining a common unit testing approach
- that offers practical guidelines for all ForgeRock software.
- which can be an aid to helping community to write unit tests.
Focus on writing typical unit tests where the focus is on writing individual classes, and to try to avoid situations where multiple components are involved.
It is good practice to ensure that all code written should have associated unit tests.
Use the following tools
- TestNG as the overall unit testing framework
- FEST Fluent Assertions to make tests compact and more readable
- Mockito to help to fake up objects, rather than having to load in complete contexts
- Checkstyle to check coding styles and conventions
- EMMA or Clover for code coverage
- Jenkins for continuous integration
Developing Unit Tests
Write down guidelines and good practices for writing unit tests,
Some simple rules:
- really write unit-tests, not functional, not system, not integration tests
- try to keep everything in a single unit (inside the class)
- test one thing at a time - a single test purpose
- a test must not have impact on other tests - isolation
- test must not be dependent on other tests
- focus on writing tests for public api
- tests should not be dependent on timing (no sleeps, wait on timers, etc.)
- avoid loading in multiple components (client + config + core server)
- use mock objects to present contexts (fake it up like stubs)
- make tests compact and more readable
- keep it simple
Unit tests are split into 'short' and 'long' tests. Short tests must in total take less than one hour, preferably much less.
A unit test should comprise of:
- preamble (before,setup)
- execute test purpose
- verify (assert) that it happened
- set verdict
- postamble (after,cleanup,teardown)
Tests Suite Structure and Layout
Tests layout should mirror source code.
Try to share. There are already some common classes, currently available in OpenDJ, that could be made available with some refactoring to other components:
- unit test base class (http://sources.forgerock.org/browse/opendj/trunk/opendj3/opendj-build-tools/opendj-testng-support/src/main/java/org/opendj/buildtools/testng/OpenDJTestCase.java?r=HEAD) which attempts to null out any left over references in test objects once the test has completed (don't depend on developers to do this themselves).
- test listener (http://sources.forgerock.org/browse/opendj/trunk/opendj3/opendj-build-tools/opendj-testng-support/src/main/java/org/opendj/buildtools/testng/OpenDJTestListener.java?r=HEAD) which dumps current progress stats, memory usage, and other info.