Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

This page covers some common testing best practices and anti-patterns.

Best Practices

Be Test-Driven

Follow the Test-Driven Development Test Cycle.

First, come up with an initial list of end to end, component/service and/or unit tests that will be needed to show that the user story, requirement or improvement works as expected or issue has been fixed.

Then for each one:

  1. Add a test
  2. Run all tests and see if the new test fails
  3. Write the code
  4. Run the tests until they pass
  5. Refactor the code as needed
  6. Move on to the next test

Be Behavior-Driven

Test behaviors, not methods or lines of code.

Write each test following the Behavior-Driven Development structure, i.e., Given/When/Then. In other words make sure each test:

  • First provides a clear context in which it will be run (given)
  • Performs the operation to be tested (when)
  • Asserts that the expected outcomes have been met (then)

Use Clear Names

Tests should have names that clearly indicate the behavior being tested. For instance, catalogReturnsMetacardIdWhenIngestSucceeds or errorIsReturnedWhenInvalidUserNameIsProvided.

Positive and Negative Testing

Always remember to tests all positive and negative test scenarios and ensure that the proper results (error code, exception, message, etc.) are returned.

Some error scenarios are extremely difficult to test using end-to-end or component/service tests, which makes testing all exception scenarios at the unit test level even more critical.

Assertions and Validations

When writing a test, always:

  • Assert that the expected value is returned
  • Assert that the object under test is in the expected state
  • Verify that the mocked dependencies were called/not called as expected
  • Verify that all the mocked dependencies that were called were called with the right parameters
  • Have just enough assertions and verifications to prove that the test passes, but no less

Never assert or verify the same behavior in more than one test.

Mock Dependencies

Use Proper Clean Up Mechanisms

Smells

Tests Difficult to Name

Too Many Dependencies

Dependencies Difficult to Mock

Anti-Patterns

Sleeps

Sleeps in tests should be avoided as they open the door to timing issues and race conditions, slow tests down and are a major cause of test flakiness.

Some options to avoid sleeps in tests include:

  • Replaced the sleep with an active wait loop (a.k.a., polling), i.e., wait until a condition has been met before moving on
  • Use external synchronization, i.e., use existing class notification mechanism to know it has reached a certain state before continuing
  • Refactor the code under test to eliminate concurrency
  • Use external dependency calls or side-effects as synchronization points in the tests

Changing Method Visibility

  • No labels