Redundant Coverage

Justin Searls edited this page Aug 13, 2015 · 5 revisions

Redundant coverage is a testing anti-pattern which describes the situation in which the behavior of a particular production code path is depended on by multiple tests. It's one (of several) examples in which greater code coverage is not a universally good thing.

Redundant coverage is problematic because a single desired change in a given bit of production code might result in a need to change numerous tests, who would otherwise fail (and as a false negative, at that).

For instance, if a system has a unit DeterminesAdulthood which determines if a user is of majority age, and a later requirement changes the age of majority from 18 to 21, then any test which both exercises DeterminesAdulthood and cares about whether users are adults may be impacted by the change.

This anti-pattern becomes a systemic problem under very common architectural patterns, such as in a multi-layered web application server like Ruby on Rails. If the above example had been implemented as a predicate method adult? on a User model, then a typical Rails test suite would be expected to redundantly cover User#adult? in User's model test, controller test, and integration test, as well as in the analogous tests of any domain objects which depend on User (which in a Rails application, is typically "all of them")

As a point of test design, then, finding a way to minimize redundant code coverage is considered a worthwhile goal. An advantage of London-school TDD is that its isolation test suites tend to significantly reduce redundant coverage; often, units in such systems are tested exactly twice: in their symmetrical unit test and in an integrated SAFE test.