Skip to content

Test practices

Ivan Shapovalov edited this page Dec 13, 2017 · 18 revisions
  1. Keep tests small and fast

  2. Try to Write one test-condition per test method

  3. Use the strongest assertions possible

    In order of decreasing strength, assertions fall into the falling categories:

    • strongest assertions - asserting on the return value of a method;
    • strong assertions - verifying that vital dependent mock objects were interacted with correctly;
    • weak assertions - verifying that non-vital dependent mock objects (such as a logger) were interacted with correctly;
    • non-existent assertions.
  4. Use the most appropriate assertion methods

    • Use assertTrue(classUnderTest.methodUnderTest()) rather than assertEquals(true, classUnderTest.methodUnderTest());
    • Use assertEquals(expectedReturnValue, classUnderTest.methodUnderTest()) rather than assertTrue(classUnderTest .methodUnderTest().equals(expectedReturnValue));
    • Use assertEquals(expectedCollection, classUnderTest.getCollection()) rather than asserting on the collection's size and each of the collection's members.
  5. Put assertion parameters in the proper order

    For example, use assertEquals(expected, actual) rather than assertEquals(actual, expected).

    Remember that assertThat(actual, expected).

  6. Use assertions with message in case of multiple assertions in one method

    For example, use assertEquals(message, expected, actual) in integration tests.

  7. Use exact matching when using a mocking framework

    For example, avoid using Mockito's methods that start with any; prefer configuring and verifying exact parameter values.

  8. Name unit tests using a convention that includes the method and condition being tested

    Test methods' names within the test case should describe what they test:

    • testLoggingEmptyMessage()
    • testLoggingNullMessage()
    • testLoggingWarningMessage()
    • testLoggingErrorMessage()
    • createEmployee_NullId_ShouldThrowException
    • createEmployee_NegativeId_ShouldThrowException
    • testCreateEmployee_DuplicateId_ShouldThrowException

    Proper naming helps code readers understand each test's purpose.

  9. Ensure that test classes exist in the same Java package as the production class under test

    When in the same package as the production class being tested, test classes can use package-private classes and invoke package-private methods.

  10. Ensure that test code is separated from production code

    The default folder structure in a Maven project does this - production code exists in the src/main/java folder and test code exists in the src/test/java folder. Even if you don't use Maven, put test code and production code in different folders.

  11. Do not initialize in a unit test class constructor; use an @Before method instead

    If a failure occurs during a test class constructor, an AssertionFailedError occurs and the stack trace is not very informative; in particular, the stack trace does not include the original error's location. On the other hand, if a failure occurs during an @Before method, all details about the failure's location are available.

    JUnits lifecycle:

    • Create a different testclass instance for each test method
    • Repeat for each testclass instance: call setup + call the testmethod
  12. Do not use static not final members in a test class

    Static members make unit test methods dependent. Don't use them! Instead, strive to write test methods that are completely independent.

  13. In test classes, do not declare that methods throw any particular type of exception

    Test methods that declare that they throw one particular type of exception are brittle because they must be changed whenever the method under test changes.

  14. Do not use Thread.sleep in unit tests

    When a unit test uses Thread.sleep it does not reliably indicate a problem in the production code. For example, such a test can fail because it is run on a machine that is slower than usual. Aim for unit tests that fail if and only if the production code is broken.

    Rather than using Thread.sleep in a unit test, refactor the production code to allow the injection of a mock object that can simulate the success or failure of the potentially long-running operation that must normally be waited for.

  15. Don't assume the order in which tests within a test case run

    Running the tests on different platforms and Java VMs may therefore yield different results, unless your tests are designed to run in any order.

  16. Call a superclass's setUp() and tearDown() methods when subclassing

    setUp() should call super.setUp() to ensure that all environment of super class are running.

  17. Do not load data from hard-coded locations on a filesystem

  18. Document tests in javadoc

  19. Avoid visual inspection

    Testing servlets, user interfaces, and other systems that produce complex output is often left to visual inspection. Visual inspection -- a human inspecting output data for errors -- requires patience, the ability to process large quantities of information, and great attention to detail: attributes not often found in the average human being. Below are some basic techniques that will help reduce the visual inspection component of your test cycle.

From

Clone this wiki locally