Code smells in general indicate symptoms that indicate deeper problems in source code. But it works… These just hurt maintainability.

Eager Tests

  • This is a test that tests too many things. See Testing Principles
  • Separate test code into separate test methods

Lazy Tests

  • Multiple tests test the same functionality or behaviour
  • These use the same test fixture

Mystery Guest

  • When a test depends on some external resource like a file containing data. Therefore, the test is no longer self contained.
  • This also introduces hidden dependancies

External Resources

  • Inline Resource: Basically here, incorporate some external resource in the test code to avoid external dependancies
  • Setup External Resource: If you actually need an external resource like a database, make the test set it up, and tear it down
  • Make Resources Unique: Use unique resource names and unique identifiers.

Resource Optimism

  • This is when test code makes optimistic assumptions about the state of external resources and cause non-deterministic testing behaviour
  • This causes flakiness
  • Use the external resource stuff to fix

Test Run War

  • Tests fail when multiple people run tests at the same time due to resource interference

General Fixture

  • We don’t want things to be too general
  • Large setup fixtures also make tests run more slowly
  • Put the bare minimum in there and then any other specific setup stuff in the test itself

Assertion Roulette

  • This comes from having a number of assertions that have no explanation
  • This leads to us not knowing which assertion is causing a failure

Assertion Explanation

Assertions in the JUnit framework have an optional first argument to give an explanatory message to the user when the assertion fails.

Indirect Testing

  • A test class should be the counterpart of production code. When a test class starts to perform tests on other objects, we have issues
  • This usually happens because it is too costly or hard to test a class so we try to workaround and test indirectly
  • Such indirection can be moved to the appropriate test class by applying Extract Method followed by Move Method on that part of the test

For Testers Only

  • When a production class contains methods that are only used by test methods, these methods either (1) are not needed and can be removed, or (2) are only needed to set up a fixture for testing
  • We can move these things into a subclass in the test code (just for testing)

Sensitive Equality

  • Don’t always test equality by mapping to a string
  • Use an equality method instead to assert a proper equality
  • You can construct a new object containing the expected value and assert an equality between the two values

Test Duplication

  • There can be duplication of code in the same test class
  • Parts that set up test fixtures are prone to this
  • Test implication is a special case. Test A and B cover the same production code, and A fails if and only if B fails.

Additional Smells

  • Redundant assertions
  • Unknown tests
  • Empty tests
  • Duplicate assertions