test-impl
(Optional, high-risk flow) Implement test files from the test-design artifact. Depends on /sdd:test-design and runs inside an active pipeline.
Files2
View on GitHubSKILL.mdskills/test-impl/SKILL.md
GitHubTest Implementation — Optional
Optional step in the high-risk flow. Implements the test files designed by /sdd:test-design, following its artifact. Runs inside an active pipeline.
Depends on /sdd:test-design: this step reads .specwork/_test/<slug>-test-design.md and refuses to run if it is missing. Run /sdd:test-design first. Being optional, you may also skip this step and go straight to /sdd:commit.
When to Use
- After
/sdd:test-designhas written its artifact, within an active pipeline - To implement the designed unit / integration / E2E tests
Usage
/sdd:test-impl # implement test files for the pipeline branch
/sdd:test-impl PROJ-1234 # explicit ticket ID
Requires: an active pipeline (.specwork/) with implementation changes, and a completed /sdd:test-design (its artifact at .specwork/_test/<slug>-test-design.md).
Hard Rules — Behavior-Based Assertions
Generated tests must verify behavior, not just that code doesn't explode. Before writing any test method, read the implementation file you are testing and extract concrete facts:
| Facet | What to extract | Asserted with |
|---|---|---|
| Return value | Type, fields populated, derived computations (e.g. status = OPEN when count >= threshold) |
assertThat(result.getStatus()).isEqualTo(OPEN); — concrete value |
| Persistence | repository.save(...) / entityManager.persist(...) calls — what entity, which fields are set |
verify(repository).save(argThat(c -> c.getName().equals("X"))); |
| Events / messages | applicationEventPublisher.publishEvent(...), sqsTemplate.send(...), kafkaTemplate.send(...) |
verify(publisher).publishEvent(any(ConsentCreatedEvent.class)); |
| Outbound calls | Feign client / RestTemplate invocations — endpoint, payload shape |
verify(feignClient).fetchUser(eq(userId)); |
| Exceptions | Specific exception class thrown for which input | assertThatThrownBy(...).isInstanceOf(NotFoundException.class).hasMessageContaining("..."); |
Forbidden patterns
These assertions are defects — they pass even when the behavior is wrong:
assertThat(result).isNotNull(); // says nothing about behavior
verify(repository).save(any()); // doesn't validate WHAT was saved
assertThat(result.getItems()).isNotEmpty(); // doesn't check content
A non-null check is acceptable only as a precondition before a content assertion on the same value:
assertThat(result).isNotNull();
assertThat(result.getStatus()).isEqualTo(OPEN); // ← the real assertion
Pre-authoring read
For each class whose test you are about to write:
- Read the public methods being tested
- Note the return type and any computed/derived values
- List every collaborator invocation that mutates state (
save,publishEvent,send, etc.) - Note the exception types thrown and the conditions
Write the test methods only after this extraction. If you cannot determine the concrete value an implementation produces (truly dynamic — e.g. depends on a UUID or Instant.now()), assert against the shape (regex match, field present, type correct), not nullity.
For frontend tests, the equivalent extraction: which props the component renders into the DOM, which callbacks it fires with what arguments, which network requests it triggers (MSW handler). Assertions target visible text, accessible roles, or recorded callback arguments — never just "the component rendered".
Requires: /sdd:test-design first (reads its artifact). Next step: /sdd:commit.