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