Skip to content

Commit c6906eb

Browse files
chrisdpurcellclaude
andcommitted
feat(test-driver): add non-unit test design principles
Section 8 covers how universal test design principles shift for integration, contract, security, e2e, and UI tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5d2759c commit c6906eb

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

  • plugins/test-driver/skills/test-design

plugins/test-driver/skills/test-design/SKILL.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,37 @@ assert len(users) == 3
174174
expected_user_count = 3 # admin + two test users created in arrange
175175
assert len(users) == expected_user_count
176176
```
177+
178+
## 8. Non-Unit Test Design
179+
180+
Sections 1-7 apply universally, but some principles shift weight when writing non-unit tests.
181+
182+
### Integration Tests
183+
184+
Relax isolation (Section 1): the point of integration tests is verifying that components work together. Use real dependencies where feasible (test database, actual HTTP client, real service wiring). Keep test independence (each test sets up its own state), but don't mock the interactions you're trying to test.
185+
186+
Assert on observable outcomes across boundaries: data persisted correctly, response includes data assembled from multiple components, side effects propagated through the real dependency chain. Avoid asserting on internal state of intermediate components.
187+
188+
### Contract Tests
189+
190+
Test the shape, not the content. Assert on response structure (required fields present, correct types, proper status codes, expected content-type headers, error response format). Use schema validation (jsonschema, pydantic model parsing) rather than value equality.
191+
192+
Contract tests should pass regardless of what data is in the system. If a contract test breaks when test data changes, it's testing values, not shape.
193+
194+
### Security Tests
195+
196+
Each test represents one attack vector. Write the test as an attacker would attempt the attack: SQL injection in a user input field, manipulated auth tokens, requests without credentials, accessing another user's resources via ID enumeration.
197+
198+
Assert that the attack fails gracefully: proper HTTP error code (401/403, not 500), no sensitive data leaked in error messages or response bodies, no state corruption from the malicious input.
199+
200+
### E2E Tests
201+
202+
Test user-facing workflows from entry point to final result. Minimize mocking: the value of E2E tests is proving the full stack works together. Accept slower execution as the cost of this confidence.
203+
204+
Focus on critical paths (authenticate, perform primary action, verify result) rather than exhaustive feature coverage. A few high-quality E2E tests covering the main workflows are worth more than dozens covering edge cases.
205+
206+
### UI Tests
207+
208+
Test what the user sees and does, not implementation details. Click buttons, fill forms, navigate between screens, verify visible outcomes (text content, element visibility, enabled/disabled state).
209+
210+
Use accessibility identifiers or object names for element lookup, not CSS selectors or internal widget hierarchy. If a test breaks because the widget tree changed but the user experience didn't, the test is too tightly coupled to implementation.

0 commit comments

Comments
 (0)