How can we meet the Objective? (Goals)

Why follow these Principles?
Test Smells

symptoms, impacts, or causes?

Tests Should Help Us Understand the System

Tests can show us how the code is supposed to work

Tests as Documentation - automated tests act as a form of documentation 


Write Tests First (TDD)

tests save us a lot of debugging effort

Writing the tests before we write the code forces the code to be designed for testability


Hard-to-Test Code

symptoms - hard to test code

impact -  we cannot easily verify the quality of the code in an automated way


Highly Coupled Code,
Asynchronous Code,
Untestable Test Code


Tests Should Require Minimal Maintenance as the System Evolves Around Them

Robust Test - write tests in a way that the number of tests impacted by code changes is small


Communicate Intent

Intent-Revealing Names

should be apparent which inputs result in which outputs


Fragile Test

symptoms - frequently, tests that used to pass are now failing after a change

impact - increases the cost of test maintenance

causes -

Interface Sensitivity,
Behavior Sensitivity,
Data Sensitivity,
Context Sensitivity,
Overspecified Software,
Sensitive Equality,
Fragile Fixture


Tests Should Reduce (and Not Introduce) Risk

Safety Net - tests allow us to make changes more safely, can take chances on different code changes

Do No Harm - the tests should not introduce new kinds of problems


Verify One Condition Per Test

makes Defect Localization easier

prevents missing a test when an assertion fails

does not have to mean one assertion


Conditional Test Logic

symptom - may not produce symptoms, but it should be suspicious to the reader

impact - difficult to know what a test is going to do, how do we know that it will actually detect the bugs it is intended to catch


Flexible Test,
Conditional Verification Logic,
Production Logic in Test,
Complex Teardown,
Multiple Test Conditions


Tests Should Be Easy to Run

Fully Automated Test - tests that can be run without manual intervention 

Self-Checking Test - the test verifies the outcome and communications pass/fail

*Repeatable Test - the test can be run multiple times and get the same result, without intervention


Keep Tests Independent

An Independent Test can be run by itself

Interacting Tests or Erratic tests tend to fail in a group and can be harder to debug

Independent Tests give better Defect Localization


Erratic Test

symptom - one or more tests giving different results depending on when or who is running them

impact - tempted to remove it (Lost Test), may obscure other problems

causes -

Interacting Tests,
Interacting Test Suites,
Lonely Test,
Resource Leakage,
Resource Optimism,
Unrepeatable Test,
Test Run War,
Nondeterministic Test


Tests Should Help Us Improve Quality

Tests as Specification - tests enable us to specify the behavior in various scenarios captured in a form we can execute

Bug Repellent - tests keep bugs from crawling back into our code

Defect Localization - if our tests are small, we can pinpoint bugs pretty fast with tests based on which test failed


Keep Test Logic Out of Production Code

production code should not contain any conditional statements of the "if testing then" sort that is running alternative logic or preventing certain logic from running

it should not contain any test logic

if the system behaves differently under test, how can we be certain the production code actually works?

test hooks could cause software to fail in production!


Developers Not Writing Tests

symptom - we hear they aren't or have observed production bugs

impact - creates tech debt, will take longer and longer to  add new functionality


Not Enough Time,
Hard-to-Test Code,
Wrong Test Automation Strategy


Tests Should Be Easy to Write and Maintain

Simple Test - tests should be small and test one thing at a time

Expressive Tests - build up a library of domain-specific testing language

Separation of Concerns - keep test code separate from production code


Ensure Commensurate Effort and Responsibility

the amount of effort to write or modify tests should not exceed the effort to implement the corresponding functionality 

the tools required to write or maintain the test should require no more expertise than the tools used to implement the functionality


Obscure Test

symptom - having trouble understanding what behavior a test is verifying

impact - makes tests harder to understand and therefore maintain


Eager Test,
Mystery Guest,
General Fixture,
Irrelevant Information,
Hard-Coded Test Data,
Indirect Testing

Click to zoom