When adding a feature, it is easy to focus on getting the new code working and discover later that a change has broken existing behavior. Test-driven development (TDD) puts a small automated test before the code it verifies. The test specifies expected component behavior and gives the developer a check while implementing it. section 2.1 section 1.2.1
Work in a short cycle:
- Write a failing unit test that describes the behavior to implement. section 2.1
- Write just enough application code to make the test pass. section 2.1
- Refactor the code so it remains understandable and maintainable. section 2.1
The tests are low-level specifications: developers write them to describe and verify individual components. Acceptance tests serve a different audience. They express whether a feature works as intended in business-facing terms. In a behavior-driven development approach, acceptance criteria can guide the feature from the top down while unit tests describe the behavior needed from each component. section 2.1 section 2.6
public class WhenTransferringInternationalFunds {
@Test
public void should_transfer_funds_to_a_local_account() {...}
@Test
public void should_transfer_funds_to_a_different_bank() {...}
...
@Test
public void should_deduct_fees_as_a_separate_transaction() {...}
...
}
These bank-transfer test names state specific expected behaviors, such as transferring to another bank and deducting fees separately. They make a more useful low-level specification than a broad test name alone. section 2.1
Readable unit and integration tests can also become technical living documentation for developers maintaining the code. TDD is associated with cleaner, easier-to-change code and fewer defects, but adopting it does not automatically guarantee those results. section 16.5.4 section 1.2.1














