swe-workflow-skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/VERSION +1 -0
- package/bin/cli.mjs +44 -0
- package/catalog.json +225 -0
- package/commands/role.md +34 -0
- package/hooks/session-start.mjs +118 -0
- package/install.mjs +318 -0
- package/package.json +47 -0
- package/roles.json +194 -0
- package/scripts/resolve.mjs +296 -0
- package/skills/accessibility-design/SKILL.md +128 -0
- package/skills/accessibility-design/evals/evals.json +51 -0
- package/skills/accessibility-design/references/accessibility-patterns.md +321 -0
- package/skills/api-design/SKILL.md +144 -0
- package/skills/api-design/evals/evals.json +48 -0
- package/skills/api-design/references/rest-conventions.md +147 -0
- package/skills/api-design/templates/api-spec.md +156 -0
- package/skills/architecture-design/SKILL.md +86 -0
- package/skills/architecture-design/evals/evals.json +44 -0
- package/skills/architecture-design/references/clean-architecture.md +147 -0
- package/skills/architecture-design/references/component-principles.md +129 -0
- package/skills/architecture-design/references/principles.md +81 -0
- package/skills/architecture-design/references/solid-principles.md +106 -0
- package/skills/architecture-design/templates/adr.md +63 -0
- package/skills/architecture-documentation/SKILL.md +126 -0
- package/skills/architecture-documentation/evals/evals.json +44 -0
- package/skills/architecture-documentation/references/abstraction-levels.md +91 -0
- package/skills/architecture-documentation/references/diagram-tooling.md +141 -0
- package/skills/architecture-documentation/templates/architecture-doc.md +171 -0
- package/skills/bug-investigating/SKILL.md +133 -0
- package/skills/bug-investigating/evals/evals.json +56 -0
- package/skills/bug-investigating/references/common-bugs.md +62 -0
- package/skills/bug-investigating/references/debugging-patterns.md +94 -0
- package/skills/cicd-pipeline/SKILL.md +87 -0
- package/skills/cicd-pipeline/evals/evals.json +34 -0
- package/skills/cicd-pipeline/references/pipeline-patterns.md +206 -0
- package/skills/cicd-pipeline/templates/github-actions.md +206 -0
- package/skills/code-reviewing/SKILL.md +92 -0
- package/skills/code-reviewing/evals/evals.json +62 -0
- package/skills/code-reviewing/references/error-handling.md +108 -0
- package/skills/code-reviewing/references/review-checklist.md +144 -0
- package/skills/configuration-strategy/SKILL.md +109 -0
- package/skills/configuration-strategy/evals/evals.json +41 -0
- package/skills/configuration-strategy/references/config-patterns.md +161 -0
- package/skills/containerization/SKILL.md +90 -0
- package/skills/containerization/evals/evals.json +36 -0
- package/skills/containerization/references/dockerfile-patterns.md +168 -0
- package/skills/containerization/templates/dockerfile.md +154 -0
- package/skills/data-modeling/SKILL.md +83 -0
- package/skills/data-modeling/evals/evals.json +43 -0
- package/skills/data-modeling/references/conventions.md +57 -0
- package/skills/data-modeling/templates/schema.md +120 -0
- package/skills/dependency-impact-analysis/SKILL.md +113 -0
- package/skills/dependency-impact-analysis/evals/evals.json +41 -0
- package/skills/dependency-impact-analysis/references/impact-patterns.md +150 -0
- package/skills/dependency-management/SKILL.md +161 -0
- package/skills/dependency-management/evals/evals.json +48 -0
- package/skills/dependency-management/references/evaluation-checklist.md +127 -0
- package/skills/deployment-checklist/SKILL.md +132 -0
- package/skills/deployment-checklist/evals/evals.json +58 -0
- package/skills/deployment-checklist/references/pre-deploy-gates.md +91 -0
- package/skills/deployment-repo/SKILL.md +190 -0
- package/skills/deployment-repo/evals/evals.json +44 -0
- package/skills/deployment-repo/references/deployment-repo-patterns.md +258 -0
- package/skills/deployment-repo/references/version-compatibility.md +227 -0
- package/skills/deployment-repo/templates/deployment-repo-structure.md +226 -0
- package/skills/effort-estimation/SKILL.md +95 -0
- package/skills/effort-estimation/evals/evals.json +32 -0
- package/skills/effort-estimation/references/estimation-methods.md +154 -0
- package/skills/feature-planning/SKILL.md +84 -0
- package/skills/feature-planning/evals/evals.json +44 -0
- package/skills/feature-planning/templates/plan.md +55 -0
- package/skills/feature-planning/templates/task.md +26 -0
- package/skills/frontend-architecture/SKILL.md +154 -0
- package/skills/frontend-architecture/evals/evals.json +34 -0
- package/skills/frontend-architecture/references/component-patterns.md +264 -0
- package/skills/frontend-architecture/templates/folder-structure.md +203 -0
- package/skills/git-workflow/SKILL.md +127 -0
- package/skills/git-workflow/evals/evals.json +44 -0
- package/skills/git-workflow/references/conventions.md +142 -0
- package/skills/git-workflow/templates/pull-request.md +57 -0
- package/skills/gitops-delivery/SKILL.md +319 -0
- package/skills/gitops-delivery/evals/evals.json +44 -0
- package/skills/gitops-delivery/references/gitops-patterns.md +478 -0
- package/skills/gitops-delivery/templates/gitops-config.md +196 -0
- package/skills/incident-response/SKILL.md +130 -0
- package/skills/incident-response/evals/evals.json +55 -0
- package/skills/incident-response/references/communication-templates.md +134 -0
- package/skills/incident-response/references/severity-levels.md +77 -0
- package/skills/incident-response/templates/incident-timeline.md +57 -0
- package/skills/infrastructure-as-code/SKILL.md +86 -0
- package/skills/infrastructure-as-code/evals/evals.json +33 -0
- package/skills/infrastructure-as-code/references/iac-patterns.md +179 -0
- package/skills/infrastructure-as-code/templates/terraform-module.md +158 -0
- package/skills/metrics-and-okrs/SKILL.md +113 -0
- package/skills/metrics-and-okrs/evals/evals.json +33 -0
- package/skills/metrics-and-okrs/references/metric-catalog.md +90 -0
- package/skills/metrics-and-okrs/templates/okr-document.md +61 -0
- package/skills/ml-experiment-tracking/SKILL.md +96 -0
- package/skills/ml-experiment-tracking/evals/evals.json +32 -0
- package/skills/ml-experiment-tracking/references/tracking-tools.md +127 -0
- package/skills/ml-model-deployment/SKILL.md +106 -0
- package/skills/ml-model-deployment/evals/evals.json +34 -0
- package/skills/ml-model-deployment/references/serving-patterns.md +162 -0
- package/skills/ml-pipeline-design/SKILL.md +162 -0
- package/skills/ml-pipeline-design/evals/evals.json +34 -0
- package/skills/ml-pipeline-design/references/pipeline-components.md +174 -0
- package/skills/observability-design/SKILL.md +162 -0
- package/skills/observability-design/evals/evals.json +52 -0
- package/skills/observability-design/references/logging-patterns.md +229 -0
- package/skills/observability-design/references/slo-framework.md +151 -0
- package/skills/observability-design/templates/slo-document.md +80 -0
- package/skills/performance-optimization/SKILL.md +83 -0
- package/skills/performance-optimization/evals/evals.json +47 -0
- package/skills/performance-optimization/references/bottleneck-patterns.md +256 -0
- package/skills/performance-optimization/references/concurrency.md +101 -0
- package/skills/prd-writing/SKILL.md +109 -0
- package/skills/prd-writing/evals/evals.json +33 -0
- package/skills/prd-writing/references/prd-examples.md +132 -0
- package/skills/prd-writing/templates/prd.md +71 -0
- package/skills/prd-writing/templates/rfc.md +79 -0
- package/skills/project-documentation/SKILL.md +104 -0
- package/skills/project-documentation/evals/evals.json +48 -0
- package/skills/project-documentation/references/contributing-guide.md +100 -0
- package/skills/project-documentation/templates/changelog.md +59 -0
- package/skills/project-documentation/templates/readme.md +121 -0
- package/skills/project-proposal/SKILL.md +90 -0
- package/skills/project-proposal/evals/evals.json +31 -0
- package/skills/project-proposal/references/proposal-examples.md +140 -0
- package/skills/project-proposal/templates/proposal.md +76 -0
- package/skills/project-review/SKILL.md +111 -0
- package/skills/project-review/evals/evals.json +42 -0
- package/skills/refactoring/SKILL.md +90 -0
- package/skills/refactoring/evals/evals.json +44 -0
- package/skills/refactoring/references/transformations.md +132 -0
- package/skills/retrospective/SKILL.md +157 -0
- package/skills/retrospective/evals/evals.json +34 -0
- package/skills/retrospective/references/facilitation-guide.md +130 -0
- package/skills/retrospective/templates/post-mortem.md +121 -0
- package/skills/rollback-strategy/SKILL.md +116 -0
- package/skills/rollback-strategy/evals/evals.json +55 -0
- package/skills/rollback-strategy/references/rollback-patterns.md +125 -0
- package/skills/rollback-strategy/templates/rollback-plan.md +69 -0
- package/skills/security-audit/SKILL.md +146 -0
- package/skills/security-audit/evals/evals.json +66 -0
- package/skills/security-audit/references/owasp-top-10.md +167 -0
- package/skills/security-audit/templates/security-report.md +79 -0
- package/skills/skill-router/SKILL.md +171 -0
- package/skills/skill-router/evals/evals.json +39 -0
- package/skills/strategic-review/SKILL.md +106 -0
- package/skills/strategic-review/evals/evals.json +42 -0
- package/skills/strategic-review/templates/full-review-prompt.md +84 -0
- package/skills/tdd-workflow/SKILL.md +147 -0
- package/skills/tdd-workflow/evals/evals.json +58 -0
- package/skills/tdd-workflow/references/test-quality.md +71 -0
- package/skills/technical-debt-review/SKILL.md +113 -0
- package/skills/technical-debt-review/evals/evals.json +41 -0
- package/skills/technical-debt-review/references/debt-taxonomy.md +124 -0
- package/skills/technical-debt-review/templates/debt-audit.md +85 -0
- package/skills/test-data-strategy/SKILL.md +129 -0
- package/skills/test-data-strategy/evals/evals.json +49 -0
- package/skills/test-data-strategy/references/data-generation-patterns.md +341 -0
- package/skills/test-suite-design/SKILL.md +137 -0
- package/skills/test-suite-design/evals/evals.json +69 -0
- package/skills/test-suite-design/references/test-infrastructure.md +175 -0
- package/skills/test-suite-design/references/testing-pyramid.md +140 -0
- package/skills/ui-ux-design/SKILL.md +117 -0
- package/skills/ui-ux-design/evals/evals.json +35 -0
- package/skills/ui-ux-design/references/interaction-patterns.md +145 -0
- package/skills/ui-ux-design/templates/screen-spec.md +97 -0
- package/skills/verification-before-completion/SKILL.md +85 -0
- package/skills/verification-before-completion/evals/evals.json +53 -0
- package/skills/writing-skills/SKILL.md +87 -0
- package/skills/writing-skills/evals/evals.json +41 -0
- package/skills/writing-skills/references/pressure-testing.md +69 -0
- package/uninstall.mjs +182 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Technical Debt Audit
|
|
2
|
+
|
|
3
|
+
**Codebase / Service**: [Name]
|
|
4
|
+
**Date**: [DATE]
|
|
5
|
+
**Reviewed by**: [Name(s)]
|
|
6
|
+
**Review scope**: [Whole codebase / specific module / specific time period]
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Executive Summary
|
|
11
|
+
|
|
12
|
+
[2-3 sentences: overall health assessment and top priority]
|
|
13
|
+
|
|
14
|
+
**Overall health**: [Green / Yellow / Red]
|
|
15
|
+
- Green: Debt is manageable, team moves at full speed
|
|
16
|
+
- Yellow: Debt is noticeable, slowing sprint velocity
|
|
17
|
+
- Red: Debt is critical, actively blocking features or causing incidents
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Hotspots
|
|
22
|
+
|
|
23
|
+
| File / Module | Debt types | Severity | Churn (last 90d) | Notes |
|
|
24
|
+
|---------------|-----------|---------|-----------------|-------|
|
|
25
|
+
| [path/to/file] | Complexity, Test | High | 23 changes | God class with 800 lines |
|
|
26
|
+
| | | | | |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Debt Inventory
|
|
31
|
+
|
|
32
|
+
### Critical — Address Immediately
|
|
33
|
+
|
|
34
|
+
| Item | Type | Location | Description | Effort |
|
|
35
|
+
|------|------|---------|-------------|--------|
|
|
36
|
+
| | | | | |
|
|
37
|
+
|
|
38
|
+
### High — Schedule This Quarter
|
|
39
|
+
|
|
40
|
+
| Item | Type | Location | Description | Effort | Prerequisite |
|
|
41
|
+
|------|------|---------|-------------|--------|-------------|
|
|
42
|
+
| | | | | | |
|
|
43
|
+
|
|
44
|
+
### Medium — Address Opportunistically
|
|
45
|
+
|
|
46
|
+
| Item | Type | Location | Description |
|
|
47
|
+
|------|------|---------|-------------|
|
|
48
|
+
| | | | |
|
|
49
|
+
|
|
50
|
+
### Accepted Debt — Won't Address
|
|
51
|
+
|
|
52
|
+
| Item | Reason for accepting |
|
|
53
|
+
|------|---------------------|
|
|
54
|
+
| | |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Remediation Roadmap
|
|
59
|
+
|
|
60
|
+
### This Sprint (Quick Wins)
|
|
61
|
+
- [ ] [Item]: [Owner] — est. [X hours]
|
|
62
|
+
- [ ] [Item]: [Owner] — est. [X hours]
|
|
63
|
+
|
|
64
|
+
### Next Quarter
|
|
65
|
+
- [ ] [Item]: requires [prerequisite]. est. [X weeks]. Owner: [Name]
|
|
66
|
+
- [ ] [Item]: requires [prerequisite]. est. [X weeks]. Owner: [Name]
|
|
67
|
+
|
|
68
|
+
### Strategic Investment (requires planning)
|
|
69
|
+
- [Item]: est. [X months]. Needs: [team buy-in / dedicated sprint / architecture design]
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Metrics to Track Progress
|
|
74
|
+
|
|
75
|
+
| Metric | Current | Target | Measurement |
|
|
76
|
+
|--------|---------|--------|-------------|
|
|
77
|
+
| Test coverage (critical paths) | [X%] | [Y%] | [How measured] |
|
|
78
|
+
| Average function length (hotspot files) | [X lines] | [Y lines] | [How measured] |
|
|
79
|
+
| Bug rate from [module] | [X/month] | [Y/month] | [How measured] |
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Next Review Date
|
|
84
|
+
|
|
85
|
+
[Date — typically 1 quarter from now]
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-data-strategy
|
|
3
|
+
description: "Design and generate test data — factories, synthetic data, property-based testing, boundary analysis, contract testing, load scenarios, GDPR-safe data. Triggers: test data, synthetic data, fake data, factory, seed data, fixtures, property-based testing, fuzz testing, boundary values, contract testing, Pact, load test data, anonymize, GDPR test data."
|
|
4
|
+
model: sonnet
|
|
5
|
+
allowed-tools: Read, Grep, Glob, Write, Edit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Test Data Strategy
|
|
9
|
+
|
|
10
|
+
Design and generate the data that powers tests. Bad test data causes false confidence (tests pass but bugs hide) and false alarms (tests fail on irrelevant data quirks). Good test data is realistic, covers edge cases, and respects privacy.
|
|
11
|
+
|
|
12
|
+
## Scope Boundary
|
|
13
|
+
|
|
14
|
+
This skill designs **what data** to create and **how** to create it. For **how to structure tests** (naming, pyramid, framework setup), use `test-suite-design`. For **test-first implementation**, use `tdd-workflow`.
|
|
15
|
+
|
|
16
|
+
## Workflow
|
|
17
|
+
|
|
18
|
+
### Step 1: Assess Data Needs
|
|
19
|
+
|
|
20
|
+
For the feature or system under test, identify:
|
|
21
|
+
|
|
22
|
+
- **What entities are involved?** (Users, orders, products, transactions)
|
|
23
|
+
- **What relationships matter?** (User has many orders, order has many items)
|
|
24
|
+
- **What data states exist?** (Active user, suspended user, deleted user)
|
|
25
|
+
- **What are the boundary values?** (Empty, one item, max items, zero price, max price)
|
|
26
|
+
- **What constitutes invalid data?** (Missing required fields, wrong types, out-of-range values)
|
|
27
|
+
- **Is production data available for reference?** (Understand real distributions)
|
|
28
|
+
- **Are there privacy constraints?** (GDPR, HIPAA, PCI — cannot use real customer data)
|
|
29
|
+
|
|
30
|
+
### Step 2: Choose the Right Strategy
|
|
31
|
+
|
|
32
|
+
Different testing needs require different data strategies:
|
|
33
|
+
|
|
34
|
+
| Strategy | Best For | When to Use |
|
|
35
|
+
|----------|----------|-------------|
|
|
36
|
+
| **Factories** | Unit/integration tests | Most tests — deterministic, focused, fast |
|
|
37
|
+
| **Property-based testing** | Algorithmic code, parsers, serialization | When exhaustive example testing is impractical |
|
|
38
|
+
| **Boundary value analysis** | Validation, calculations, range checks | Any function with numeric or string limits |
|
|
39
|
+
| **Synthetic data generation** | Load testing, staging environments | When you need volume or realistic distributions |
|
|
40
|
+
| **Contract testing** | Service-to-service boundaries | When multiple services agree on a data format |
|
|
41
|
+
| **Snapshot testing** | Complex outputs (API responses, renders) | When output is large and changes infrequently |
|
|
42
|
+
|
|
43
|
+
See [references/data-generation-patterns.md](references/data-generation-patterns.md) for implementation of each strategy.
|
|
44
|
+
|
|
45
|
+
### Step 3: Design Factory Architecture
|
|
46
|
+
|
|
47
|
+
For most applications, factories are the backbone of test data. Design them in layers:
|
|
48
|
+
|
|
49
|
+
**Layer 1 — Build functions** (create plain objects in memory):
|
|
50
|
+
```
|
|
51
|
+
buildUser({ role: 'admin' }) → { id: '...', name: '...', role: 'admin', ... }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Layer 2 — Create functions** (insert into database and return):
|
|
55
|
+
```
|
|
56
|
+
createUser({ role: 'admin' }) → User record in DB
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Layer 3 — Scenario builders** (create a complete test scenario):
|
|
60
|
+
```
|
|
61
|
+
createCheckoutScenario() → { user, cart with 3 items, valid payment method, applied discount }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Layer 3 is the key insight most teams miss. Complex tests need complete scenarios, not individual entities assembled ad-hoc in every test.
|
|
65
|
+
|
|
66
|
+
### Step 4: Define Boundary Values
|
|
67
|
+
|
|
68
|
+
For every input that has limits, test:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
┌─────────────────────────────────┐
|
|
72
|
+
Below min │ Min │ Nominal │ Max │ Above max
|
|
73
|
+
└─────────────────────────────────┘
|
|
74
|
+
Invalid Edge Valid Edge Invalid
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For each input, create test data for:
|
|
78
|
+
- **Below minimum** (invalid: -1 for quantity, empty string for name)
|
|
79
|
+
- **At minimum** (edge: 0 or 1, single character)
|
|
80
|
+
- **Nominal** (typical valid value)
|
|
81
|
+
- **At maximum** (edge: 255 characters, max integer)
|
|
82
|
+
- **Above maximum** (invalid: 256 characters, overflow value)
|
|
83
|
+
- **Special values** (null, undefined, NaN, Infinity, empty array, whitespace-only string)
|
|
84
|
+
|
|
85
|
+
### Step 5: Implement Property-Based Tests
|
|
86
|
+
|
|
87
|
+
For functions where example-based tests can't cover the input space, use property-based testing:
|
|
88
|
+
|
|
89
|
+
Instead of `test("sorts [3,1,2] to [1,2,3]")`, assert the property: "for ANY array, sort(arr) produces a result where every element is ≤ the next."
|
|
90
|
+
|
|
91
|
+
Properties to look for:
|
|
92
|
+
- **Roundtrip**: `deserialize(serialize(x)) === x`
|
|
93
|
+
- **Idempotence**: `f(f(x)) === f(x)` (e.g., normalization, formatting)
|
|
94
|
+
- **Invariants**: `sort(arr).length === arr.length` (no elements lost or added)
|
|
95
|
+
- **Commutativity**: `f(a, b) === f(b, a)` (order independence)
|
|
96
|
+
- **Oracle**: `myFunction(x) === referenceImplementation(x)` (compare against known-good)
|
|
97
|
+
|
|
98
|
+
See [references/data-generation-patterns.md](references/data-generation-patterns.md) for framework-specific implementation.
|
|
99
|
+
|
|
100
|
+
### Step 6: Handle Privacy and Compliance
|
|
101
|
+
|
|
102
|
+
When test data must resemble production data but cannot contain real PII:
|
|
103
|
+
|
|
104
|
+
**Never copy production data to test environments unmasked.** Instead:
|
|
105
|
+
|
|
106
|
+
1. **Use factories for most tests** — no real data involved, no compliance risk
|
|
107
|
+
2. **Generate synthetic data for staging** — realistic distributions without real identities
|
|
108
|
+
3. **Mask production data only when necessary** — anonymize PII before copying to lower environments
|
|
109
|
+
4. **Version control your data generation seeds** — for reproducible test runs
|
|
110
|
+
5. **Audit test environments** — ensure no real PII leaked into test databases
|
|
111
|
+
|
|
112
|
+
See [references/data-generation-patterns.md](references/data-generation-patterns.md) for privacy-safe generation patterns.
|
|
113
|
+
|
|
114
|
+
### Step 7: Design Load Test Data
|
|
115
|
+
|
|
116
|
+
Load testing requires different data characteristics:
|
|
117
|
+
|
|
118
|
+
- **Volume**: Thousands or millions of records, not tens
|
|
119
|
+
- **Variety**: Realistic distribution of data states (not all active users)
|
|
120
|
+
- **Uniqueness**: Unique identifiers to prevent constraint violations during concurrent loads
|
|
121
|
+
- **Pre-seeded**: Data must exist before the test runs (not created during the test)
|
|
122
|
+
- **Cleanable**: Easy to identify and remove after the test (`test_` prefix, specific date ranges)
|
|
123
|
+
|
|
124
|
+
## Principles Applied
|
|
125
|
+
|
|
126
|
+
- **KISS**: Start with factories. Add property-based testing for algorithmic code. Add synthetic generation for load tests. Don't build everything on day one.
|
|
127
|
+
- **DRY**: Centralize factories in a shared test helpers directory. Every test file should import from the same factory, not define its own.
|
|
128
|
+
- **YAGNI**: Don't build a synthetic data pipeline for unit tests. Factories are sufficient for 90% of test data needs.
|
|
129
|
+
- **Functional Independence**: Test data setup should be self-contained per test. Never depend on data created by another test.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "test-data-strategy",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "I'm building an e-commerce API with users, products, orders, and payments. I need to set up test data for our test suite — unit tests, integration tests, and we'll eventually need load testing data. We're using TypeScript, Prisma, and PostgreSQL. Design the test data strategy.",
|
|
7
|
+
"expected_output": "Should design a 3-layer factory architecture (build/create/scenario), define boundary values for key fields, set up Faker for realistic data, and outline the load test data generation approach.",
|
|
8
|
+
"assertions": [
|
|
9
|
+
"Designs layered factories (build → create → scenario)",
|
|
10
|
+
"Creates factories for all key entities (user, product, order, payment)",
|
|
11
|
+
"Defines scenario builders for complex test setups (checkout scenario)",
|
|
12
|
+
"Identifies boundary values for price (0, negative, max), quantity (0, 1, max), and user roles",
|
|
13
|
+
"Uses Faker with a fixed seed for reproducibility",
|
|
14
|
+
"Separates unit test data (in-memory) from integration test data (database)",
|
|
15
|
+
"Outlines load test data generation as a separate concern",
|
|
16
|
+
"Addresses referential integrity across related factories"
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": 2,
|
|
21
|
+
"prompt": "I have a function that validates and normalizes email addresses. It handles international domains, plus addressing (user+tag@), case normalization, and various edge cases. How do I test this thoroughly? Example-based tests feel insufficient.",
|
|
22
|
+
"expected_output": "Should recommend property-based testing for this kind of input-space-heavy function, define key properties (roundtrip, normalization idempotence), and supplement with explicit boundary values.",
|
|
23
|
+
"assertions": [
|
|
24
|
+
"Recommends property-based testing (fast-check or Hypothesis)",
|
|
25
|
+
"Defines the idempotence property: normalize(normalize(email)) === normalize(email)",
|
|
26
|
+
"Defines the preservation property: normalizing a valid email doesn't invalidate it",
|
|
27
|
+
"Supplements with explicit boundary examples for known edge cases",
|
|
28
|
+
"Tests special characters, unicode domains, maximum-length emails",
|
|
29
|
+
"Does NOT rely solely on hand-picked examples",
|
|
30
|
+
"Provides working property-based test code"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": 3,
|
|
35
|
+
"prompt": "Our QA team is using a copy of our production database for testing. This has real customer data including names, emails, and credit card tokens. We're a fintech startup and our compliance officer is concerned. How do we fix this without losing test quality?",
|
|
36
|
+
"expected_output": "Should recommend transitioning to factories for most tests, synthetic generation for staging, and masked production data only for specific data-shape-dependent scenarios. Should be specific about what data to mask and how.",
|
|
37
|
+
"assertions": [
|
|
38
|
+
"Identifies this as a compliance violation (PII in test environments)",
|
|
39
|
+
"Recommends factories for unit and integration tests (no real data needed)",
|
|
40
|
+
"Recommends synthetic data generation for staging",
|
|
41
|
+
"If production data is needed, recommends masking with specific techniques per field type",
|
|
42
|
+
"Provides concrete masking examples (emails, names, card tokens)",
|
|
43
|
+
"Warns against just copying and 'finding/replacing' — proper masking tools needed",
|
|
44
|
+
"Suggests separating the transition into phases (don't try to replace everything at once)",
|
|
45
|
+
"Does NOT just say 'don't use production data' without providing alternatives"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# Data Generation Patterns
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
- Factory patterns by language
|
|
5
|
+
- Property-based testing frameworks
|
|
6
|
+
- Synthetic data generation
|
|
7
|
+
- Contract testing patterns
|
|
8
|
+
- Privacy-safe data patterns
|
|
9
|
+
- Load test data patterns
|
|
10
|
+
|
|
11
|
+
## Factory Patterns by Language
|
|
12
|
+
|
|
13
|
+
### JavaScript/TypeScript (with Faker.js)
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { faker } from '@faker-js/faker';
|
|
17
|
+
|
|
18
|
+
// Layer 1: Build (in-memory objects)
|
|
19
|
+
export function buildUser(overrides: Partial<User> = {}): User {
|
|
20
|
+
return {
|
|
21
|
+
id: faker.string.uuid(),
|
|
22
|
+
name: faker.person.fullName(),
|
|
23
|
+
email: faker.internet.email(),
|
|
24
|
+
role: 'member',
|
|
25
|
+
active: true,
|
|
26
|
+
createdAt: faker.date.past(),
|
|
27
|
+
...overrides,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function buildOrder(overrides: Partial<Order> = {}): Order {
|
|
32
|
+
return {
|
|
33
|
+
id: faker.string.uuid(),
|
|
34
|
+
userId: faker.string.uuid(),
|
|
35
|
+
items: [buildOrderItem(), buildOrderItem()],
|
|
36
|
+
total: 0, // calculated below
|
|
37
|
+
status: 'pending',
|
|
38
|
+
createdAt: new Date(),
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Layer 2: Create (persisted to database)
|
|
44
|
+
export async function createUser(overrides: Partial<User> = {}): Promise<User> {
|
|
45
|
+
const data = buildUser(overrides);
|
|
46
|
+
return db.users.create({ data });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Layer 3: Scenario builders
|
|
50
|
+
export async function createCheckoutScenario() {
|
|
51
|
+
const user = await createUser({ active: true });
|
|
52
|
+
const products = await Promise.all([
|
|
53
|
+
createProduct({ price: 1999 }),
|
|
54
|
+
createProduct({ price: 3499 }),
|
|
55
|
+
]);
|
|
56
|
+
const cart = await createCart({ userId: user.id, items: products });
|
|
57
|
+
const paymentMethod = await createPaymentMethod({ userId: user.id });
|
|
58
|
+
|
|
59
|
+
return { user, products, cart, paymentMethod };
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Python (with Faker + factory_boy)
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import factory
|
|
67
|
+
from faker import Faker
|
|
68
|
+
|
|
69
|
+
fake = Faker()
|
|
70
|
+
|
|
71
|
+
# Layer 1: Build
|
|
72
|
+
def build_user(**overrides):
|
|
73
|
+
defaults = {
|
|
74
|
+
"id": fake.uuid4(),
|
|
75
|
+
"name": fake.name(),
|
|
76
|
+
"email": fake.email(),
|
|
77
|
+
"role": "member",
|
|
78
|
+
"active": True,
|
|
79
|
+
"created_at": fake.date_time_this_year(),
|
|
80
|
+
}
|
|
81
|
+
return {**defaults, **overrides}
|
|
82
|
+
|
|
83
|
+
# Layer 2: Create (with factory_boy + SQLAlchemy)
|
|
84
|
+
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|
85
|
+
class Meta:
|
|
86
|
+
model = User
|
|
87
|
+
sqlalchemy_session = session
|
|
88
|
+
|
|
89
|
+
name = factory.LazyFunction(fake.name)
|
|
90
|
+
email = factory.LazyFunction(fake.email)
|
|
91
|
+
role = "member"
|
|
92
|
+
active = True
|
|
93
|
+
|
|
94
|
+
# Usage:
|
|
95
|
+
admin = UserFactory(role="admin")
|
|
96
|
+
inactive = UserFactory(active=False)
|
|
97
|
+
|
|
98
|
+
# Layer 3: Scenario
|
|
99
|
+
def create_checkout_scenario(session):
|
|
100
|
+
user = UserFactory(active=True)
|
|
101
|
+
products = [ProductFactory(price=1999), ProductFactory(price=3499)]
|
|
102
|
+
cart = CartFactory(user=user, items=products)
|
|
103
|
+
return {"user": user, "products": products, "cart": cart}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Property-Based Testing Frameworks
|
|
107
|
+
|
|
108
|
+
### JavaScript: fast-check
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import fc from 'fast-check';
|
|
112
|
+
|
|
113
|
+
// Roundtrip property: JSON parse/stringify
|
|
114
|
+
test('JSON roundtrip preserves data', () => {
|
|
115
|
+
fc.assert(
|
|
116
|
+
fc.property(fc.jsonValue(), (value) => {
|
|
117
|
+
expect(JSON.parse(JSON.stringify(value))).toEqual(value);
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Invariant: sort preserves length
|
|
123
|
+
test('sort preserves array length', () => {
|
|
124
|
+
fc.assert(
|
|
125
|
+
fc.property(fc.array(fc.integer()), (arr) => {
|
|
126
|
+
expect([...arr].sort((a, b) => a - b).length).toBe(arr.length);
|
|
127
|
+
})
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Custom arbitrary for domain objects
|
|
132
|
+
const userArbitrary = fc.record({
|
|
133
|
+
name: fc.string({ minLength: 1, maxLength: 100 }),
|
|
134
|
+
email: fc.emailAddress(),
|
|
135
|
+
age: fc.integer({ min: 0, max: 150 }),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('user validation accepts all valid users', () => {
|
|
139
|
+
fc.assert(
|
|
140
|
+
fc.property(userArbitrary, (user) => {
|
|
141
|
+
expect(validateUser(user).isValid).toBe(true);
|
|
142
|
+
})
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Python: Hypothesis
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from hypothesis import given, strategies as st
|
|
151
|
+
|
|
152
|
+
# Roundtrip
|
|
153
|
+
@given(st.text())
|
|
154
|
+
def test_encode_decode_roundtrip(s):
|
|
155
|
+
assert decode(encode(s)) == s
|
|
156
|
+
|
|
157
|
+
# Invariant
|
|
158
|
+
@given(st.lists(st.integers()))
|
|
159
|
+
def test_sort_preserves_length(lst):
|
|
160
|
+
assert len(sorted(lst)) == len(lst)
|
|
161
|
+
|
|
162
|
+
# Custom strategy
|
|
163
|
+
user_strategy = st.fixed_dictionaries({
|
|
164
|
+
"name": st.text(min_size=1, max_size=100),
|
|
165
|
+
"email": st.emails(),
|
|
166
|
+
"age": st.integers(min_value=0, max_value=150),
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
@given(user_strategy)
|
|
170
|
+
def test_user_validation(user):
|
|
171
|
+
result = validate_user(user)
|
|
172
|
+
assert result.is_valid
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Synthetic Data Generation
|
|
176
|
+
|
|
177
|
+
### For staging environments (Faker at scale)
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
import pandas as pd
|
|
181
|
+
from faker import Faker
|
|
182
|
+
|
|
183
|
+
fake = Faker()
|
|
184
|
+
Faker.seed(42) # Reproducible!
|
|
185
|
+
|
|
186
|
+
def generate_users(n=10000):
|
|
187
|
+
return pd.DataFrame([{
|
|
188
|
+
"id": f"usr_{i:06d}",
|
|
189
|
+
"name": fake.name(),
|
|
190
|
+
"email": fake.email(),
|
|
191
|
+
"country": fake.country_code(),
|
|
192
|
+
"signup_date": fake.date_between("-2y", "today"),
|
|
193
|
+
"plan": fake.random_element(["free", "pro", "enterprise"]),
|
|
194
|
+
"active": fake.boolean(chance_of_getting_true=85),
|
|
195
|
+
} for i in range(n)])
|
|
196
|
+
|
|
197
|
+
def generate_orders(users_df, avg_orders_per_user=5):
|
|
198
|
+
orders = []
|
|
199
|
+
for _, user in users_df.iterrows():
|
|
200
|
+
n_orders = max(0, int(fake.random.gauss(avg_orders_per_user, 2)))
|
|
201
|
+
for _ in range(n_orders):
|
|
202
|
+
orders.append({
|
|
203
|
+
"id": fake.uuid4(),
|
|
204
|
+
"user_id": user["id"],
|
|
205
|
+
"amount": round(fake.random.uniform(5, 500), 2),
|
|
206
|
+
"status": fake.random_element(["completed", "pending", "refunded"]),
|
|
207
|
+
"created_at": fake.date_between(user["signup_date"], "today"),
|
|
208
|
+
})
|
|
209
|
+
return pd.DataFrame(orders)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Statistical distributions for realistic data
|
|
213
|
+
|
|
214
|
+
Don't use uniform random for everything. Real data has distributions:
|
|
215
|
+
- User activity → Power law (few super-active users, long tail of inactive)
|
|
216
|
+
- Transaction amounts → Log-normal (many small, few large)
|
|
217
|
+
- Time of day → Bimodal (peaks in morning and evening)
|
|
218
|
+
- Geographic → Clustered (real users aren't uniformly distributed)
|
|
219
|
+
|
|
220
|
+
Use numpy or scipy for realistic distributions:
|
|
221
|
+
```python
|
|
222
|
+
import numpy as np
|
|
223
|
+
|
|
224
|
+
# Log-normal transaction amounts (mean ~$50, long tail to $10K)
|
|
225
|
+
amounts = np.random.lognormal(mean=3.9, sigma=1.2, size=10000)
|
|
226
|
+
amounts = np.clip(amounts, 1, 10000).round(2)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Contract Testing Patterns
|
|
230
|
+
|
|
231
|
+
### Pact (consumer-driven contracts)
|
|
232
|
+
|
|
233
|
+
Contract testing verifies that two services agree on the data format at their boundary, without requiring both to be running.
|
|
234
|
+
|
|
235
|
+
**Consumer side** (the service that CALLS the API):
|
|
236
|
+
```javascript
|
|
237
|
+
const { PactV3 } = require('@pact-foundation/pact');
|
|
238
|
+
|
|
239
|
+
const provider = new PactV3({ consumer: 'OrderService', provider: 'UserService' });
|
|
240
|
+
|
|
241
|
+
test('get user by ID', async () => {
|
|
242
|
+
provider
|
|
243
|
+
.given('user 42 exists')
|
|
244
|
+
.uponReceiving('a request for user 42')
|
|
245
|
+
.withRequest({ method: 'GET', path: '/users/42' })
|
|
246
|
+
.willRespondWith({
|
|
247
|
+
status: 200,
|
|
248
|
+
body: { id: 42, name: string('Jane'), email: email() },
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
await provider.executeTest(async (mockServer) => {
|
|
252
|
+
const user = await userClient.getUser(42, mockServer.url);
|
|
253
|
+
expect(user.name).toBe('Jane');
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Provider side** (the service that SERVES the API):
|
|
259
|
+
```javascript
|
|
260
|
+
const { Verifier } = require('@pact-foundation/pact');
|
|
261
|
+
|
|
262
|
+
test('verify contracts', async () => {
|
|
263
|
+
await new Verifier({
|
|
264
|
+
providerBaseUrl: 'http://localhost:3000',
|
|
265
|
+
pactUrls: ['./pacts/orderservice-userservice.json'],
|
|
266
|
+
stateHandlers: {
|
|
267
|
+
'user 42 exists': async () => { await createUser({ id: 42, name: 'Jane' }); },
|
|
268
|
+
},
|
|
269
|
+
}).verifyProvider();
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Privacy-Safe Data Patterns
|
|
274
|
+
|
|
275
|
+
### Strategy selection
|
|
276
|
+
|
|
277
|
+
| Scenario | Recommended Approach |
|
|
278
|
+
|----------|---------------------|
|
|
279
|
+
| Unit tests | Factories (no real data involved) |
|
|
280
|
+
| Integration tests | Factories + test database (created fresh per suite) |
|
|
281
|
+
| Staging environment | Synthetic generation at scale |
|
|
282
|
+
| Performance testing | Synthetic with realistic distributions |
|
|
283
|
+
| Bug reproduction | Masked production subset (anonymize PII first) |
|
|
284
|
+
|
|
285
|
+
### Masking techniques
|
|
286
|
+
|
|
287
|
+
| Data Type | Masking Method |
|
|
288
|
+
|-----------|---------------|
|
|
289
|
+
| Email | `john.doe@company.com` → `user_a1b2@test.example.com` |
|
|
290
|
+
| Name | `John Doe` → `Person_82947` or Faker-generated name |
|
|
291
|
+
| Phone | `555-123-4567` → `555-000-XXXX` |
|
|
292
|
+
| SSN | `123-45-6789` → `XXX-XX-6789` (keep last 4 if needed) |
|
|
293
|
+
| Address | Replace with Faker address in same country/region |
|
|
294
|
+
| Credit card | `4111...1234` → `4111...0000` (keep BIN, zero out rest) |
|
|
295
|
+
| Date of birth | Shift by random offset (preserve age distribution) |
|
|
296
|
+
|
|
297
|
+
### Deterministic seeding for reproducibility
|
|
298
|
+
|
|
299
|
+
Always seed random generators in test data scripts:
|
|
300
|
+
```python
|
|
301
|
+
Faker.seed(42)
|
|
302
|
+
np.random.seed(42)
|
|
303
|
+
random.seed(42)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Commit the seed value. Tests using seeded factories produce the same data every run, making failures reproducible.
|
|
307
|
+
|
|
308
|
+
## Load Test Data Patterns
|
|
309
|
+
|
|
310
|
+
### Pre-seeding for load tests (k6 example)
|
|
311
|
+
|
|
312
|
+
```javascript
|
|
313
|
+
// data/users.json — pre-generated, committed or generated in CI
|
|
314
|
+
// Generate with: node scripts/generate-load-test-data.js > data/users.json
|
|
315
|
+
|
|
316
|
+
import { SharedArray } from 'k6/data';
|
|
317
|
+
|
|
318
|
+
const users = new SharedArray('users', function () {
|
|
319
|
+
return JSON.parse(open('./data/users.json'));
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
export default function () {
|
|
323
|
+
const user = users[__VU % users.length]; // Each VU gets a different user
|
|
324
|
+
const res = http.post('https://api.example.com/login', JSON.stringify({
|
|
325
|
+
email: user.email,
|
|
326
|
+
password: user.password,
|
|
327
|
+
}));
|
|
328
|
+
check(res, { 'login succeeded': (r) => r.status === 200 });
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Data volume guidelines
|
|
333
|
+
|
|
334
|
+
| Test Type | Typical Data Volume |
|
|
335
|
+
|-----------|-------------------|
|
|
336
|
+
| Smoke test | 10-50 records |
|
|
337
|
+
| Load test | 10K-100K records |
|
|
338
|
+
| Stress test | 100K-1M records |
|
|
339
|
+
| Soak test | 100K records, sustained over hours |
|
|
340
|
+
|
|
341
|
+
Generate data before the test run, not during. Creating data during a load test contaminates the results (you're measuring data creation speed, not application performance).
|