Test-Driven Development workflow including Red-Green-Refactor cycle, error recovery, and when to write different test types.
npx claudepluginhub sumanpapanaboina1983/adlc-accelerator-kit-pluginsThis skill uses the workspace's default tool permissions.
| Gate | Threshold | Status |
Executes strict TDD workflow: test specification, failing unit tests (RED), implementation (GREEN), refactor with 80% coverage thresholds and complexity triggers. Use for TDD cycles.
Enforces TDD red-green-refactor cycle: test spec/design, failing unit tests, failure verification, 80% line coverage, refactoring on complexity/length triggers.
Test-Driven Development guidance. Use when writing code, implementing features, or fixing bugs in projects that follow TDD methodology. Provides the Red-Green-Refactor cycle structure.
Share bugs, ideas, or general feedback.
| Gate | Threshold | Status |
|---|---|---|
| Compile | 0 errors | REQUIRED |
| Tests | 100% pass (0 failures) | REQUIRED |
| Coverage | ≥ 80% line coverage | REQUIRED |
| Checkstyle | 0 violations | REQUIRED (if configured) |
⛔ BLOCKING: TDD workflow is NOT complete until ALL gates pass.
Before starting ANY TDD cycle, verify JaCoCo is configured:
grep -l "jacoco-maven-plugin" pom.xml
If NOT configured, add it FIRST to pom.xml:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals><goal>prepare-agent</goal></goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals><goal>report</goal></goals>
</execution>
<execution>
<id>check</id>
<phase>verify</phase>
<goals><goal>check</goal></goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
⛔ Do NOT start TDD without coverage configuration in place.
┌──────────────────┐
│ RED │
│ Write a failing │
│ test │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ GREEN │
│ Write minimal │
│ code to pass │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ REFACTOR │
│ Improve code │
│ keeping green │
└────────┬─────────┘
│
└─────────────────┐
│
Repeat for ▼
next behavior ◄──┘
@Test
void should_createTodo_whenValidRequest() {
// Given
CreateTodoRequest request = new CreateTodoRequest("New Todo");
// When
TodoResponse response = todoService.create(request);
// Then
assertThat(response.id()).isNotNull();
assertThat(response.title()).isEqualTo("New Todo");
assertThat(response.completed()).isFalse();
}
Run: mvn test -Dtest=TodoServiceTest#should_createTodo_whenValidRequest
Expected output: FAIL (method doesn't exist yet)
public TodoResponse create(CreateTodoRequest request) {
Todo todo = new Todo();
todo.setTitle(request.title());
todo.setCompleted(false);
todo.setCreatedAt(Instant.now());
Todo saved = todoRepository.save(todo);
return new TodoResponse(
saved.getId(),
saved.getTitle(),
saved.isCompleted(),
saved.getCreatedAt()
);
}
Run: mvn test -Dtest=TodoServiceTest#should_createTodo_whenValidRequest
Expected output: PASS
// REFACTOR: Extract mapping to private method
public TodoResponse create(CreateTodoRequest request) {
Todo todo = buildTodoFromRequest(request);
Todo saved = todoRepository.save(todo);
return toResponse(saved);
}
private Todo buildTodoFromRequest(CreateTodoRequest request) {
Todo todo = new Todo();
todo.setTitle(request.title());
todo.setCompleted(false);
todo.setCreatedAt(Instant.now());
return todo;
}
private TodoResponse toResponse(Todo todo) {
return new TodoResponse(
todo.getId(),
todo.getTitle(),
todo.isCompleted(),
todo.getCreatedAt()
);
}
Run: mvn test (all tests)
Expected output: ALL PASS
ATTEMPT 1:
- Read error message carefully
- Identify likely cause
- Make targeted fix
- Run test
ATTEMPT 2 (if still failing):
- Read FULL stack trace
- Check related code (imports, dependencies)
- Make targeted fix
- Run test
ATTEMPT 3 (if still failing):
- Use diagnostic commands (grep, read configs)
- Check error→fix patterns in verification skill
- Make targeted fix
- Run test
AFTER 3 ATTEMPTS:
- STOP
- Summarize what you've tried
- Ask developer for guidance
Do NOT:
DO:
When: Testing individual methods/classes in isolation Tool: JUnit 5 + Mockito Speed: Milliseconds Example: Service method logic
@ExtendWith(MockitoExtension.class)
class TodoServiceTest {
@Mock TodoRepository repository;
@InjectMocks TodoService service;
@Test
void should_returnTodo_whenExists() {
when(repository.findById(1L)).thenReturn(Optional.of(todo));
TodoResponse result = service.findById(1L);
assertThat(result.title()).isEqualTo("Test");
}
}
When: Testing Spring components with partial context Tool: @WebMvcTest, @DataJdbcTest Speed: 1-2 seconds Example: Controller HTTP handling, Repository queries
@WebMvcTest(TodoController.class)
class TodoControllerTest {
@Autowired MockMvc mockMvc;
@MockBean TodoService service;
@Test
void should_return200_whenGetAll() throws Exception {
mockMvc.perform(get("/api/v1/todos"))
.andExpect(status().isOk());
}
}
When: Testing full request flow with real dependencies Tool: @SpringBootTest + Testcontainers Speed: 5-10 seconds Example: Full create→retrieve flow
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Testcontainers
class TodoIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
@Test
void should_createAndRetrieveTodo() {
// Full flow with real DB
}
}
/\
/ \ Integration (10%)
/────\ - Slow, expensive
/ \ - Test critical flows
/────────\
/ \ Slice Tests (20%)
/ ───── \ - Controller, Repository
/ \ - Medium speed
/────────────────\
Unit (70%)
- Fast, focused
- Test all logic
| Layer | Target | What to Test |
|---|---|---|
| Service | 80%+ | All business logic, edge cases, error paths |
| Controller | All endpoints | Happy path, validation errors, not found |
| Repository | Custom queries | Complex queries, edge cases |
| DTOs | Validation | All validation rules |
Before declaring any implementation complete, you MUST verify coverage:
# Generate coverage report
mvn test jacoco:report
# Check coverage in browser
open target/site/jacoco/index.html
| Metric | Minimum | Action if Below |
|---|---|---|
| Line Coverage | 80% | Add more tests |
| Branch Coverage | 75% | Test if/else paths |
| Method Coverage | 80% | Test all public methods |
Run coverage report:
mvn test jacoco:report
Check percentage:
target/site/jacoco/index.htmltarget/site/jacoco/jacoco.xmlIf below 80%:
Only then declare done
⛔ NEVER mark complete with coverage < 80%
A pre-completion hook enforces this requirement automatically.
For each test:
should_X_whenY()❌ Write code → Write tests → Hope they pass
✓ Write test → See it fail → Write code → See it pass
// ❌ Testing implementation details
verify(repository).save(any());
assertThat(service.getCache().size()).isEqualTo(1);
// ✓ Testing observable behavior
assertThat(result.id()).isNotNull();
assertThat(service.findById(id)).isEqualTo(expected);
// ❌ Testing multiple behaviors
@Test void testTodoOperations() {
// create, update, delete, find all in one test
}
// ✓ One behavior per test
@Test void should_createTodo_whenValidRequest() { }
@Test void should_updateTodo_whenExists() { }
@Test void should_deleteTodo_whenExists() { }
❌ Write 500 lines → Run tests → 47 failures
✓ Write test → Run → Write code → Run → Refactor → Run