# Test driven development
Test driven development (TDD) is a software engineering practice where you write the tests *before* you write any application code. This method attempts to ensure:
1. You are testing the code you intend to write.
2. You can execute [[unit tests]] for the application code immediately.
3. You can refactor your code or add new features later knowing that you've protected yourself from accidentally introducing bugs by running [[system tests]].
## Benefits
**Code coverage**: Whether this is important in the grand scheme of things is up for debate, but at the very least TDD ensures that you test all of the features that you create.
**Requirement clarity**: By knowing what to test, you gain a better understanding of the actual requirements of the feature.
**"Keep it simple, stupid"**: The tests help enforce guardrails for the feature. Basically, you should only do *enough* to make the test pass.
**Stability / enhanced debugging**: Having all of the tests upfront should prevent unintended bugs from introducing a new feature or refactoring code.
## Disadvantages
**False security**: A bad test is a bad test. Just because you wrote it doesn't make it worthwhile. For a test to be good, it should model the *expected behavior* of the application, not necessarily a specific instruction.
**Time consuming**: Engineers just want to write the application code! I know it's not just me. Writing tests does not get me out of the bed in the morning. Writing all of the tests upfront means it's going to take longer to ship the feature.
**Maintenance**: Requirements change = test change = feature change. Following TDD can add more overhead. It's a tradeoff.
## How to implement TDD
The typical pattern for test driven development follows the "red, green, refactor" methodology.
- **Red**: You write a test for the functionality you want. At this point, the test will fail and throw an error. If it doesn't fail, you probably wrote the test wrong.
- **Green**: You write just enough code to make the test pass. The goal is to get feedback that your test and code is aligned. This step is not about writing the final or best code.
- **Refactor**: You revise the code to improve structure, readability, performance, etc. The nice thing about refactoring at this point is that you have a test to fall back on and ensure it works properly.