🧱 Testing Strategy
Unit test design is the discipline of creating small, isolated, repeatable tests that verify the correctness of individual units of code—usually functions, classes, or methods. Good unit test design ensures your codebase is reliable, easy to refactor, and safe to evolve.
Unit test design — definition
Section titled “Unit test design — definition”Unit test design defines how to structure, isolate, and validate small pieces of code so that each test checks one behavior, runs fast, and fails for a clear reason. It ensures correctness at the lowest level of the system.
It answers:
- What behavior does this unit provide?
- How do we verify it works in all scenarios?
- How do we isolate it from external dependencies?
Why unit test design matters
Section titled “Why unit test design matters”Good unit tests:
- Catch bugs early
- Enable safe refactoring
- Improve code quality
- Document expected behavior
- Reduce regression risk
- Increase developer confidence
- Support clean architecture and SOLID principles
Poor unit tests become brittle, slow, and hard to maintain.
Core principles of unit test design
Section titled “Core principles of unit test design”- Isolation — test one unit, mock everything else
- Determinism — tests must produce the same result every run
- Single assertion — each test verifies one behavior
- AAA pattern — Arrange → Act → Assert
- Fast execution — tests should run in milliseconds
- Clear naming — describe behavior, not implementation
- Mocking — replace external dependencies
- Coverage of edge cases — test boundaries and failure paths
- Repeatability — no randomness, no external state
These principles ensure tests are reliable and maintainable.
What a good unit test looks like
Section titled “What a good unit test looks like”1. Focused
Section titled “1. Focused”Tests one behavior, not multiple.
2. Isolated
Section titled “2. Isolated”No database, network, file system, or external services.
3. Readable
Section titled “3. Readable”Clear Arrange → Act → Assert structure.
4. Meaningful
Section titled “4. Meaningful”Tests business behavior, not implementation details.
5. Stable
Section titled “5. Stable”Doesn’t break when refactoring internal code.
6. Fast
Section titled “6. Fast”Runs in milliseconds.
Unit test design patterns
Section titled “Unit test design patterns”1. AAA (Arrange–Act–Assert)
Section titled “1. AAA (Arrange–Act–Assert)”The most common structure.
2. Given–When–Then
Section titled “2. Given–When–Then”Behavior-driven variant of AAA.
3. Test doubles
Section titled “3. Test doubles”- Mocks
- Stubs
- Fakes
- Spies
4. Parameterized tests
Section titled “4. Parameterized tests”Test multiple inputs with one test definition.
5. Fixture setup
Section titled “5. Fixture setup”Reusable setup for complex objects.
6. Builders
Section titled “6. Builders”Create test objects cleanly without clutter.
Common mistakes in unit test design
Section titled “Common mistakes in unit test design”- Testing multiple behaviors in one test
- Mocking too much or too little
- Testing private methods
- Using real databases or external services
- Writing fragile tests tied to implementation details
- Overusing asserts
- Not testing edge cases
- Poor naming (e.g.,
Test1,ShouldDoThing)
Unit test naming conventions
Section titled “Unit test naming conventions”Good names describe behavior:
GenerateSummary_ShouldReturnEmptySummary_WhenNoTasksExistCalculateScore_ShouldThrowException_WhenInputIsInvalidSendReminder_ShouldPublishMessage_WhenMemberIsActive
Names should reflect business behavior, not internal logic.
Example
Section titled “Example”If you apply unit test design to a Daily Scrum application:
DailySummaryGeneratorTests
Section titled “DailySummaryGeneratorTests”GenerateSummary_ShouldIncludeCompletedTasksGenerateSummary_ShouldExcludeInactiveMembersGenerateSummary_ShouldHandleEmptySession
PdfExporterTests
Section titled “PdfExporterTests”Export_ShouldGeneratePdfBytesExport_ShouldThrow_WhenSummaryIsNull
NotificationServiceTests
Section titled “NotificationServiceTests”SendReminder_ShouldPublishMessageSendReminder_ShouldNotSend_WhenMemberIsInactive
Mocks would replace:
- Repositories
- Message bus
- PDF library
- Email/SMS providers
This keeps tests fast, isolated, and reliable.
Unit test design workflow (practical)
Section titled “Unit test design workflow (practical)”- Identify the unit’s responsibilities
- List behaviors and edge cases
- Write tests using AAA or Given–When–Then
- Mock external dependencies
- Assert one behavior per test
- Review for readability and isolation
- Refactor tests when refactoring code
Takeaway
Section titled “Takeaway”Unit test design defines how to write small, isolated, fast, and meaningful tests that verify individual behaviors. Good unit tests are readable, deterministic, and focused on business logic—not implementation details.