A test is trustworthy when its result changes your behavior. If it fails, you believe a real bug may exist and investigate. If it passes, you can stop manually testing or debugging “just in case.” A test that is routinely ignored when red, or doubted when green, is not providing its intended value. section 7.1 section 1.8
Trust is one of three qualities of a good test, alongside readability and maintainability. They reinforce each other: a test that cannot be understood is difficult to fix, and a test that changes painfully or constantly will eventually be neglected. Without trusted tests, refactoring and other important changes become harder because the safety signal is missing. section 7.0 section 1.11
Treat a failure as untrustworthy until you can establish why it happened. A failing test may indicate:
- A real production bug—the one failure reason that validates the test’s warning. section 7.2
- A bug in the test, producing a false failure. section 7.2
- An out-of-date expectation after functionality changed, a conflict with another test, or unpredictable flakiness. section 7.2
Passing tests need scrutiny too. A test with no assertions, unclear intent, multiple exit points, frequent changes, or proximity to flaky tests cannot be fully trusted. Avoid making expected values dynamically or copying production logic into the test: both add complexity, increase the chance of test bugs, and make failures slower to understand. section 7.6 section 7.6
Test the test with a deliberate defect
One practical confidence check is to temporarily introduce a small defect in the behavior under test. For example, remove the line that adds a failed password-rule error. A test intended to detect invalid passwords should then fail; restore the line and confirm that it passes again. Seeing the expected red result demonstrates that the test can catch the problem it claims to cover. section 2.5.2
Listing 2.4 Adding a bug
const verifyPassword = (input, rules) => {
const errors = [];
rules.forEach(rule => {
const result = rule(input);
if (!result.passed) {
// errors.push(`error ${result.reason}`); #1
}
});
return errors;
};
#1 We've accidentally commented out this line.
Inspect the missing error-collection line used to verify that a password-validation test fails for the expected reason. section 2.5.2
Trustworthiness is not identical to test level. Unit and component tests are fast, simple, and less flaky, but alone may not show that the whole application works. End-to-end tests offer stronger whole-system confidence, but are slower, harder to maintain and debug, and more flaky. Use a mix rather than relying exclusively on either extreme. section 10.2.2 section 10.5
Keep high-level coverage focused. A few end-to-end tests for important functionality can provide broad confidence, while variations are often cheaper to prove at lower levels. When flaky tests remain, isolate them so they can run separately; then fix them, move their coverage to a less flaky level, or delete them. section 10.2.1 section 7.6













