ace-test 0.6.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.
- checksums.yaml +7 -0
- data/.ace-defaults/nav/protocols/agent-sources/ace-test.yml +19 -0
- data/.ace-defaults/nav/protocols/guide-sources/ace-test.yml +19 -0
- data/.ace-defaults/nav/protocols/tmpl-sources/ace-test.yml +11 -0
- data/.ace-defaults/nav/protocols/wfi-sources/ace-test.yml +19 -0
- data/CHANGELOG.md +169 -0
- data/LICENSE +21 -0
- data/README.md +40 -0
- data/Rakefile +12 -0
- data/handbook/agents/mock.ag.md +164 -0
- data/handbook/agents/profile-tests.ag.md +132 -0
- data/handbook/agents/test.ag.md +99 -0
- data/handbook/guides/SUMMARY.md +95 -0
- data/handbook/guides/embedded-testing-guide.g.md +261 -0
- data/handbook/guides/mocking-patterns.g.md +464 -0
- data/handbook/guides/quick-reference.g.md +46 -0
- data/handbook/guides/test-driven-development-cycle/meta-documentation.md +26 -0
- data/handbook/guides/test-driven-development-cycle/ruby-application.md +18 -0
- data/handbook/guides/test-driven-development-cycle/ruby-gem.md +19 -0
- data/handbook/guides/test-driven-development-cycle/rust-cli.md +18 -0
- data/handbook/guides/test-driven-development-cycle/rust-wasm-zed.md +19 -0
- data/handbook/guides/test-driven-development-cycle/typescript-nuxt.md +18 -0
- data/handbook/guides/test-driven-development-cycle/typescript-vue.md +19 -0
- data/handbook/guides/test-layer-decision.g.md +261 -0
- data/handbook/guides/test-mocking-patterns.g.md +414 -0
- data/handbook/guides/test-organization.g.md +140 -0
- data/handbook/guides/test-performance.g.md +353 -0
- data/handbook/guides/test-responsibility-map.g.md +220 -0
- data/handbook/guides/test-review-checklist.g.md +231 -0
- data/handbook/guides/test-suite-health.g.md +337 -0
- data/handbook/guides/testable-code-patterns.g.md +315 -0
- data/handbook/guides/testing/ruby-rspec-config-examples.md +120 -0
- data/handbook/guides/testing/ruby-rspec.md +87 -0
- data/handbook/guides/testing/rust.md +52 -0
- data/handbook/guides/testing/test-maintenance.md +364 -0
- data/handbook/guides/testing/typescript-bun.md +47 -0
- data/handbook/guides/testing/vue-firebase-auth.md +546 -0
- data/handbook/guides/testing/vue-vitest.md +236 -0
- data/handbook/guides/testing-philosophy.g.md +82 -0
- data/handbook/guides/testing-strategy.g.md +151 -0
- data/handbook/guides/testing-tdd-cycle.g.md +146 -0
- data/handbook/guides/testing.g.md +170 -0
- data/handbook/skills/as-test-create-cases/SKILL.md +24 -0
- data/handbook/skills/as-test-fix/SKILL.md +26 -0
- data/handbook/skills/as-test-improve-coverage/SKILL.md +22 -0
- data/handbook/skills/as-test-optimize/SKILL.md +34 -0
- data/handbook/skills/as-test-performance-audit/SKILL.md +34 -0
- data/handbook/skills/as-test-plan/SKILL.md +34 -0
- data/handbook/skills/as-test-review/SKILL.md +34 -0
- data/handbook/skills/as-test-verify-suite/SKILL.md +45 -0
- data/handbook/templates/e2e-sandbox-checklist.template.md +289 -0
- data/handbook/templates/test-case.template.md +56 -0
- data/handbook/templates/test-performance-audit.template.md +132 -0
- data/handbook/templates/test-responsibility-map.template.md +92 -0
- data/handbook/templates/test-review-checklist.template.md +163 -0
- data/handbook/workflow-instructions/test/analyze-failures.wf.md +120 -0
- data/handbook/workflow-instructions/test/create-cases.wf.md +675 -0
- data/handbook/workflow-instructions/test/fix.wf.md +120 -0
- data/handbook/workflow-instructions/test/improve-coverage.wf.md +370 -0
- data/handbook/workflow-instructions/test/optimize.wf.md +368 -0
- data/handbook/workflow-instructions/test/performance-audit.wf.md +17 -0
- data/handbook/workflow-instructions/test/plan.wf.md +323 -0
- data/handbook/workflow-instructions/test/review.wf.md +16 -0
- data/handbook/workflow-instructions/test/verify-suite.wf.md +343 -0
- data/lib/ace/test/version.rb +7 -0
- data/lib/ace/test.rb +10 -0
- metadata +152 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: workflow
|
|
3
|
+
title: Optimize Tests Workflow
|
|
4
|
+
purpose: Systematically improve test suite performance
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-03-12
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Optimize Tests Workflow
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
Systematically optimize test performance by:
|
|
15
|
+
1. Profiling to find slow tests
|
|
16
|
+
2. Identifying root causes
|
|
17
|
+
3. Applying appropriate fixes
|
|
18
|
+
4. Migrating tests to correct layers
|
|
19
|
+
5. Verifying improvements
|
|
20
|
+
|
|
21
|
+
## When to Use
|
|
22
|
+
|
|
23
|
+
- Test suite exceeds time budget
|
|
24
|
+
- After `ace-bundle wfi://test/verify-suite` identifies issues
|
|
25
|
+
- Before major releases
|
|
26
|
+
- When developer feedback loop feels slow
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
- Package has existing tests
|
|
31
|
+
- `ace-test` available
|
|
32
|
+
- Understanding of test layer decision (see guide)
|
|
33
|
+
|
|
34
|
+
## Workflow Steps
|
|
35
|
+
|
|
36
|
+
### Step 1: Establish Baseline
|
|
37
|
+
|
|
38
|
+
Profile current performance:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Run 3 times to account for variance
|
|
42
|
+
for i in 1 2 3; do
|
|
43
|
+
ace-test <package> --profile 10 2>&1 | tee profile-$i.txt
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
# Extract consistent slow tests
|
|
47
|
+
cat profile-*.txt | grep -E "^\s+[0-9]+\." | sort | uniq -c | sort -rn
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Record baseline:
|
|
51
|
+
- Total suite time: ___s
|
|
52
|
+
- Number of tests: ___
|
|
53
|
+
- Slowest test: ___ (___ms)
|
|
54
|
+
- Tests >100ms: ___
|
|
55
|
+
|
|
56
|
+
### Step 2: Categorize Slow Tests
|
|
57
|
+
|
|
58
|
+
For each slow test, identify the cause:
|
|
59
|
+
|
|
60
|
+
| Cause | Symptoms | Fix |
|
|
61
|
+
|-------|----------|-----|
|
|
62
|
+
| Subprocess spawn | `Open3`, `system()` in stack | Stub availability + execution |
|
|
63
|
+
| Real git operations | `git init`, `git commit` | Use MockGitRepo |
|
|
64
|
+
| Network calls | HTTP requests | WebMock stubs |
|
|
65
|
+
| Filesystem I/O | Large file operations | Use temp files, mock content |
|
|
66
|
+
| Sleep statements | Retry logic with delays | Stub `Kernel.sleep` |
|
|
67
|
+
| Zombie mocks | Stub exists but test still slow | Update stub target |
|
|
68
|
+
| Wrong layer | E2E test in unit folder | Move to e2e/ |
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Search for subprocess calls in test
|
|
72
|
+
ace-search "Open3\|system\(" <package>/test/
|
|
73
|
+
|
|
74
|
+
# Search for real git operations
|
|
75
|
+
ace-search "git init\|`git " <package>/test/
|
|
76
|
+
|
|
77
|
+
# Search for sleep
|
|
78
|
+
ace-search "sleep" <package>/test/
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Step 3: Apply Quick Wins
|
|
82
|
+
|
|
83
|
+
#### 3a: Add Missing Availability Stubs
|
|
84
|
+
|
|
85
|
+
Pattern found in many optimizations:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
# BEFORE: Stubs run but not available?
|
|
89
|
+
Runner.stub(:run, mock_result) do
|
|
90
|
+
subject.lint(file) # Calls available?() first!
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# AFTER: Stub entire chain
|
|
94
|
+
Runner.stub(:available?, true) do
|
|
95
|
+
Runner.stub(:run, mock_result) do
|
|
96
|
+
subject.lint(file)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### 3b: Stub Sleep in Retry Tests
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
# Add to test or helper
|
|
105
|
+
def with_stubbed_sleep
|
|
106
|
+
Kernel.stub :sleep, nil do
|
|
107
|
+
yield
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Use in tests
|
|
112
|
+
def test_retry_logic
|
|
113
|
+
with_stubbed_sleep do
|
|
114
|
+
result = subject.retry_operation(max: 3, delay: 1.0)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### 3c: Replace Real Git with MockGitRepo
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
# BEFORE: Real git (~150ms per init)
|
|
123
|
+
def setup
|
|
124
|
+
@repo_path = Dir.mktmpdir
|
|
125
|
+
system("git", "-C", @repo_path, "init")
|
|
126
|
+
# ...
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# AFTER: MockGitRepo (~0ms)
|
|
130
|
+
def setup
|
|
131
|
+
@repo = MockGitRepo.new
|
|
132
|
+
@repo.add_commit("abc123", message: "test", files: ["test.rb"])
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Step 4: Create Composite Helpers
|
|
137
|
+
|
|
138
|
+
When multiple tests need the same stubs, create a helper:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
# In test_helper.rb
|
|
142
|
+
module OptimizationHelpers
|
|
143
|
+
def with_mock_lint_context(validators: [:standardrb])
|
|
144
|
+
# Stub all validators as available
|
|
145
|
+
validators.each do |v|
|
|
146
|
+
runner = Ace::Lint::Atoms.const_get("#{v.to_s.capitalize}Runner")
|
|
147
|
+
runner.stub(:available?, true) do
|
|
148
|
+
runner.stub(:run, mock_lint_result) do
|
|
149
|
+
yield
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def mock_lint_result
|
|
156
|
+
Ace::Lint::Models::LintResult.new(
|
|
157
|
+
issues: [],
|
|
158
|
+
exit_code: 0,
|
|
159
|
+
output: "No issues found"
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Step 5: Migrate E2E Tests
|
|
166
|
+
|
|
167
|
+
For tests that need real subprocess/git/filesystem:
|
|
168
|
+
|
|
169
|
+
#### 5a: Identify E2E Candidates
|
|
170
|
+
|
|
171
|
+
Tests that should move to E2E:
|
|
172
|
+
- CLI output format validation
|
|
173
|
+
- Tool availability checking
|
|
174
|
+
- Full workflow with real dependencies
|
|
175
|
+
- Tests that are still slow after stubbing
|
|
176
|
+
|
|
177
|
+
#### 5b: Create E2E Test Directory
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Create E2E test scenario directory
|
|
181
|
+
mkdir -p <package>/test/e2e/TS-<AREA>-00N-<slug>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**scenario.yml:**
|
|
185
|
+
```yaml
|
|
186
|
+
test-id: TS-<AREA>-00N
|
|
187
|
+
title: <Descriptive Title>
|
|
188
|
+
area: <area>
|
|
189
|
+
package: <package>
|
|
190
|
+
priority: medium
|
|
191
|
+
requires:
|
|
192
|
+
tools: [<required-tools>]
|
|
193
|
+
|
|
194
|
+
setup:
|
|
195
|
+
- git-init
|
|
196
|
+
- copy-fixtures
|
|
197
|
+
- env:
|
|
198
|
+
PROJECT_ROOT_PATH: "."
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**TC-001-<scenario>.tc.md:**
|
|
202
|
+
```markdown
|
|
203
|
+
---
|
|
204
|
+
tc-id: TC-001
|
|
205
|
+
title: <Scenario>
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Objective
|
|
209
|
+
|
|
210
|
+
Validate <what this tests> with real dependencies.
|
|
211
|
+
|
|
212
|
+
## Steps
|
|
213
|
+
|
|
214
|
+
1. <step>
|
|
215
|
+
```bash
|
|
216
|
+
<command>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
2. Verify result
|
|
220
|
+
```bash
|
|
221
|
+
[ <assertion> ] && echo "PASS: <description>" || echo "FAIL: <description>"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Expected
|
|
225
|
+
|
|
226
|
+
- <assertion>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### 5c: Delete or Convert Original Test
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
# Option 1: Delete if fully covered by E2E
|
|
233
|
+
# Just remove the test method
|
|
234
|
+
|
|
235
|
+
# Option 2: Convert to mocked version
|
|
236
|
+
def test_cli_output_format
|
|
237
|
+
# Mock subprocess, test via API
|
|
238
|
+
mock_result = { output: "Expected format" }
|
|
239
|
+
Runner.stub(:execute, mock_result) do
|
|
240
|
+
result = subject.generate_output
|
|
241
|
+
assert_equal "Expected format", result
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Step 6: Pre-warm Caches
|
|
247
|
+
|
|
248
|
+
If package has caching:
|
|
249
|
+
|
|
250
|
+
```ruby
|
|
251
|
+
# In test_helper.rb, at load time (not in setup)
|
|
252
|
+
# Pre-warm availability caches
|
|
253
|
+
Ace::Package::ValidatorRegistry.available?(:tool_a)
|
|
254
|
+
Ace::Package::ValidatorRegistry.available?(:tool_b)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Step 7: Verify Improvements
|
|
258
|
+
|
|
259
|
+
Re-profile after changes:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
ace-test <package> --profile 10
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Compare to baseline:
|
|
266
|
+
- Total suite time: ___s -> ___s (___% improvement)
|
|
267
|
+
- Slowest test: ___ms -> ___ms
|
|
268
|
+
- Tests >100ms: ___ -> ___
|
|
269
|
+
|
|
270
|
+
### Step 8: Document Changes
|
|
271
|
+
|
|
272
|
+
Create retro or update test helper comments:
|
|
273
|
+
|
|
274
|
+
```ruby
|
|
275
|
+
# test_helper.rb
|
|
276
|
+
#
|
|
277
|
+
# Performance Optimizations Applied:
|
|
278
|
+
# - Pre-warm validator caches at startup (prevents subprocess on first access)
|
|
279
|
+
# - with_mock_lint_context helper stubs all validators
|
|
280
|
+
# - Real CLI tests moved to test/e2e/
|
|
281
|
+
#
|
|
282
|
+
# See: .ace-taskflow/.../retros/<timestamp>-<package>-test-optimization.md
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Common Optimization Patterns
|
|
286
|
+
|
|
287
|
+
### Pattern: Subprocess Stubbing
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
def with_stubbed_subprocess(output: "", status: 0)
|
|
291
|
+
mock_status = Object.new
|
|
292
|
+
mock_status.define_singleton_method(:success?) { status == 0 }
|
|
293
|
+
mock_status.define_singleton_method(:exitstatus) { status }
|
|
294
|
+
|
|
295
|
+
Open3.stub :capture3, [output, "", mock_status] do
|
|
296
|
+
yield
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Pattern: Git Stubbing
|
|
302
|
+
|
|
303
|
+
```ruby
|
|
304
|
+
def with_mock_git_repo
|
|
305
|
+
repo = MockGitRepo.new
|
|
306
|
+
yield repo
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def with_stubbed_git_status(clean: true)
|
|
310
|
+
Ace::Git::Atoms::StatusChecker.stub :clean?, clean do
|
|
311
|
+
yield
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Pattern: Config Stubbing
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
def with_stubbed_config(config_hash)
|
|
320
|
+
mock_config = Ace::Support::Config::Models::Config.wrap(config_hash)
|
|
321
|
+
Ace::Support::Config.stub :create, ->(*) { mock_config } do
|
|
322
|
+
yield
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Pattern: LLM Stubbing
|
|
328
|
+
|
|
329
|
+
```ruby
|
|
330
|
+
def with_mock_llm_response(content:)
|
|
331
|
+
mock_response = {
|
|
332
|
+
"choices" => [{ "message" => { "content" => content } }]
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
WebMock.stub_request(:post, /api\.anthropic\.com|api\.openai\.com/)
|
|
336
|
+
.to_return(body: mock_response.to_json)
|
|
337
|
+
|
|
338
|
+
yield
|
|
339
|
+
end
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Checklist
|
|
343
|
+
|
|
344
|
+
- [ ] Baseline established (3 runs)
|
|
345
|
+
- [ ] Slow tests categorized by cause
|
|
346
|
+
- [ ] Availability stubs added
|
|
347
|
+
- [ ] Sleep calls stubbed
|
|
348
|
+
- [ ] Real git replaced with mocks
|
|
349
|
+
- [ ] Composite helpers created
|
|
350
|
+
- [ ] E2E tests migrated
|
|
351
|
+
- [ ] Caches pre-warmed
|
|
352
|
+
- [ ] Improvements verified
|
|
353
|
+
- [ ] Changes documented
|
|
354
|
+
|
|
355
|
+
## Expected Results
|
|
356
|
+
|
|
357
|
+
| Before | After | Target |
|
|
358
|
+
|--------|-------|--------|
|
|
359
|
+
| 30s suite | <10s suite | 70%+ reduction |
|
|
360
|
+
| 5 tests >100ms | 0 tests >100ms | Zero violations |
|
|
361
|
+
| Flaky timing | Consistent | <10% variance |
|
|
362
|
+
|
|
363
|
+
## See Also
|
|
364
|
+
|
|
365
|
+
- [Test Performance Guide](guide://test-performance)
|
|
366
|
+
- [Test Layer Decision Guide](guide://test-layer-decision)
|
|
367
|
+
- [Test Mocking Patterns Guide](guide://test-mocking-patterns)
|
|
368
|
+
- [Verify Test Suite Workflow](wfi://test/verify-suite)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: workflow
|
|
3
|
+
title: Test Performance Audit Workflow
|
|
4
|
+
purpose: test performance audit workflow
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-03-12
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Test Performance Audit Workflow
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Run `ace-test --profile 20 $ARGUMENTS`.
|
|
15
|
+
2. Read `tmpl://test-performance-audit` and use it to structure findings.
|
|
16
|
+
3. Read `guide://test-performance` for optimization guidance.
|
|
17
|
+
4. Document slow tests, root causes, and proposed fixes.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: workflow
|
|
3
|
+
title: Plan Tests Workflow
|
|
4
|
+
purpose: Ensure comprehensive test coverage with tests at the right layer
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-03-12
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Plan Tests Workflow
|
|
11
|
+
|
|
12
|
+
## Purpose
|
|
13
|
+
|
|
14
|
+
Before writing code, plan what tests are needed at each layer. This prevents:
|
|
15
|
+
- Missing test coverage
|
|
16
|
+
- Tests at the wrong layer (slow unit tests, missing E2E)
|
|
17
|
+
- Duplicate testing of same behavior at multiple layers
|
|
18
|
+
|
|
19
|
+
This workflow embodies the **Test Planner** role (deciding WHAT and WHERE to test).
|
|
20
|
+
The **Test Writer** role (implementing tests) follows separately.
|
|
21
|
+
|
|
22
|
+
## Roles
|
|
23
|
+
|
|
24
|
+
### Test Planner (This Workflow)
|
|
25
|
+
|
|
26
|
+
**Focus**: Strategic decisions
|
|
27
|
+
- WHAT behaviors need testing
|
|
28
|
+
- WHERE (which layer) each belongs
|
|
29
|
+
- WHAT risk level applies
|
|
30
|
+
- WHAT fixtures/contracts are needed
|
|
31
|
+
|
|
32
|
+
**Output**: Test Responsibility Map
|
|
33
|
+
|
|
34
|
+
### Test Writer (Separate)
|
|
35
|
+
|
|
36
|
+
**Focus**: Tactical implementation
|
|
37
|
+
- HOW to implement each test
|
|
38
|
+
- HOW to stub dependencies
|
|
39
|
+
- HOW to assert results
|
|
40
|
+
- HOW to maintain performance (<100ms)
|
|
41
|
+
|
|
42
|
+
**Output**: Test files
|
|
43
|
+
|
|
44
|
+
## When to Use
|
|
45
|
+
|
|
46
|
+
- Before implementing a new feature
|
|
47
|
+
- Before fixing a bug (plan regression test)
|
|
48
|
+
- When reviewing existing test coverage
|
|
49
|
+
- As part of `ace-bundle wfi://task/work`
|
|
50
|
+
|
|
51
|
+
## Input
|
|
52
|
+
|
|
53
|
+
- Feature description or task specification
|
|
54
|
+
- List of files to be modified
|
|
55
|
+
- Existing test coverage (optional)
|
|
56
|
+
|
|
57
|
+
## Workflow Steps
|
|
58
|
+
|
|
59
|
+
### Step 1: Understand the Change
|
|
60
|
+
|
|
61
|
+
Analyze the feature/change to identify:
|
|
62
|
+
|
|
63
|
+
1. **Pure logic components** (algorithms, transformations, validations)
|
|
64
|
+
2. **Integration points** (component interactions, data flow)
|
|
65
|
+
3. **External dependencies** (filesystem, network, subprocess, git)
|
|
66
|
+
4. **User-facing behavior** (CLI output, exit codes, error messages)
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Questions to answer:
|
|
70
|
+
- What new functions/methods will be added?
|
|
71
|
+
- What existing behavior might change?
|
|
72
|
+
- What external systems are involved?
|
|
73
|
+
- What are the error scenarios?
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Step 2: Identify Behaviors to Test
|
|
77
|
+
|
|
78
|
+
For each component, list specific behaviors:
|
|
79
|
+
|
|
80
|
+
```markdown
|
|
81
|
+
## Behaviors to Test
|
|
82
|
+
|
|
83
|
+
### Component: ConfigParser
|
|
84
|
+
- [ ] Parses valid YAML file
|
|
85
|
+
- [ ] Returns default values for missing keys
|
|
86
|
+
- [ ] Raises error for malformed YAML
|
|
87
|
+
- [ ] Handles empty file gracefully
|
|
88
|
+
|
|
89
|
+
### Component: WorkflowOrchestrator
|
|
90
|
+
- [ ] Executes steps in order
|
|
91
|
+
- [ ] Stops on first failure
|
|
92
|
+
- [ ] Reports partial progress on failure
|
|
93
|
+
- [ ] Handles empty step list
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Step 3: Assign Risk Levels
|
|
97
|
+
|
|
98
|
+
For each behavior, assess risk:
|
|
99
|
+
|
|
100
|
+
| Risk Level | Criteria | Coverage Required |
|
|
101
|
+
|------------|----------|-------------------|
|
|
102
|
+
| **High** | Security, data integrity, core business, user-facing errors | Unit + E2E |
|
|
103
|
+
| **Medium** | Important functionality, configuration | Unit required |
|
|
104
|
+
| **Low** | Logging, cosmetic, internal helpers | Unit if time permits |
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
|
|
108
|
+
| Behavior | Risk | Why |
|
|
109
|
+
|----------|------|-----|
|
|
110
|
+
| Parse valid YAML | Medium | Core functionality |
|
|
111
|
+
| Malformed YAML error | High | User-facing error handling |
|
|
112
|
+
| CLI exit codes | High | User workflow |
|
|
113
|
+
| Debug logging | Low | Internal only |
|
|
114
|
+
|
|
115
|
+
### Step 4: Classify by Test Layer
|
|
116
|
+
|
|
117
|
+
For each behavior, decide the appropriate layer:
|
|
118
|
+
|
|
119
|
+
| Behavior | Risk | Layer | Rationale |
|
|
120
|
+
|----------|------|-------|-----------|
|
|
121
|
+
| Parse valid YAML | Medium | Unit | Pure function, no I/O |
|
|
122
|
+
| Default values for missing keys | Medium | Unit | Data transformation |
|
|
123
|
+
| Malformed YAML error | High | Unit | Error handling |
|
|
124
|
+
| Steps execute in order | Medium | Integration | Component interaction |
|
|
125
|
+
| CLI shows progress | High | E2E | User-facing behavior |
|
|
126
|
+
|
|
127
|
+
**Decision criteria**:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Unit Test if:
|
|
131
|
+
- Pure logic, no side effects
|
|
132
|
+
- Can be tested with simple input/output
|
|
133
|
+
- No external dependencies needed
|
|
134
|
+
|
|
135
|
+
Integration Test if:
|
|
136
|
+
- Multiple components interact
|
|
137
|
+
- Needs controlled I/O (temp files)
|
|
138
|
+
- Tests error propagation
|
|
139
|
+
|
|
140
|
+
E2E Test if:
|
|
141
|
+
- Tests complete user workflow
|
|
142
|
+
- Requires real external tools
|
|
143
|
+
- Validates CLI behavior
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Step 5: Define Mock Strategy
|
|
147
|
+
|
|
148
|
+
For each non-E2E test, identify what to mock:
|
|
149
|
+
|
|
150
|
+
```markdown
|
|
151
|
+
## Mock Strategy
|
|
152
|
+
|
|
153
|
+
### Unit Tests
|
|
154
|
+
- Stub `FileSystem.read` with test content
|
|
155
|
+
- Stub `Time.now` for timestamp tests
|
|
156
|
+
- Use `MockGitRepo` for commit data
|
|
157
|
+
|
|
158
|
+
### Integration Tests
|
|
159
|
+
- Stub `Open3.capture3` for subprocess calls
|
|
160
|
+
- Stub `WebMock` for API calls
|
|
161
|
+
- Use temp directory for file operations
|
|
162
|
+
|
|
163
|
+
### What NOT to Mock
|
|
164
|
+
- The system under test itself
|
|
165
|
+
- Simple value objects
|
|
166
|
+
- Pure functions
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Step 6: Identify Edge Cases
|
|
170
|
+
|
|
171
|
+
For each behavior, list edge cases:
|
|
172
|
+
|
|
173
|
+
```markdown
|
|
174
|
+
## Edge Cases
|
|
175
|
+
|
|
176
|
+
### ConfigParser
|
|
177
|
+
- Empty string input
|
|
178
|
+
- Nil input
|
|
179
|
+
- Very large file (>1MB)
|
|
180
|
+
- Unicode characters in keys
|
|
181
|
+
- Circular references
|
|
182
|
+
|
|
183
|
+
### WorkflowOrchestrator
|
|
184
|
+
- Zero steps
|
|
185
|
+
- 100+ steps
|
|
186
|
+
- Step throws exception
|
|
187
|
+
- Step returns nil
|
|
188
|
+
- Concurrent execution
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Step 7: Check for Existing Coverage
|
|
192
|
+
|
|
193
|
+
Search for existing tests:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Find existing tests for the component
|
|
197
|
+
ace-search "class ConfigParser" --type test
|
|
198
|
+
ace-search "def test.*config" --type test
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Identify:
|
|
202
|
+
- Tests that already cover some behaviors
|
|
203
|
+
- Tests that need updating
|
|
204
|
+
- Gaps in coverage
|
|
205
|
+
|
|
206
|
+
### Step 8: Generate Test Responsibility Map
|
|
207
|
+
|
|
208
|
+
Output the Test Responsibility Map document:
|
|
209
|
+
|
|
210
|
+
```markdown
|
|
211
|
+
# Test Responsibility Map: [Feature Name]
|
|
212
|
+
|
|
213
|
+
## Summary
|
|
214
|
+
- Total behaviors: N
|
|
215
|
+
- High risk: N (require E2E coverage)
|
|
216
|
+
- Unit tests planned: N
|
|
217
|
+
- Integration tests planned: N
|
|
218
|
+
- E2E tests planned: N
|
|
219
|
+
|
|
220
|
+
## Responsibility Matrix
|
|
221
|
+
|
|
222
|
+
| Behavior | Risk | Layer | Test File | Source of Truth |
|
|
223
|
+
|----------|------|-------|-----------|-----------------|
|
|
224
|
+
| Parse valid YAML | Medium | Unit | config_parser_test.rb | YAML schema |
|
|
225
|
+
| Malformed YAML error | High | Unit | config_parser_test.rb | Error messages |
|
|
226
|
+
| CLI exit codes | High | E2E | TS-CONFIG-001 | CLI spec |
|
|
227
|
+
|
|
228
|
+
## Unit Tests (atoms/molecules)
|
|
229
|
+
|
|
230
|
+
### File: test/atoms/config_parser_test.rb
|
|
231
|
+
|
|
232
|
+
#### test_parses_valid_yaml
|
|
233
|
+
- Input: Valid YAML string
|
|
234
|
+
- Expected: Parsed hash with correct values
|
|
235
|
+
- Mocks: None (pure function)
|
|
236
|
+
|
|
237
|
+
#### test_returns_defaults_for_missing_keys
|
|
238
|
+
- Input: YAML without optional keys
|
|
239
|
+
- Expected: Hash with default values filled
|
|
240
|
+
- Mocks: None
|
|
241
|
+
|
|
242
|
+
#### test_raises_on_malformed_yaml
|
|
243
|
+
- Input: Invalid YAML syntax
|
|
244
|
+
- Expected: ParseError with line number
|
|
245
|
+
- Mocks: None
|
|
246
|
+
|
|
247
|
+
## Integration Tests (organisms)
|
|
248
|
+
|
|
249
|
+
### File: test/organisms/workflow_orchestrator_test.rb
|
|
250
|
+
|
|
251
|
+
#### test_executes_steps_in_order
|
|
252
|
+
- Setup: Create 3 mock steps
|
|
253
|
+
- Action: Execute orchestrator
|
|
254
|
+
- Verify: Steps called in order
|
|
255
|
+
- Mocks: Step executors
|
|
256
|
+
|
|
257
|
+
#### test_stops_on_first_failure
|
|
258
|
+
- Setup: Step 2 returns failure
|
|
259
|
+
- Action: Execute orchestrator
|
|
260
|
+
- Verify: Step 3 not called, error reported
|
|
261
|
+
- Mocks: Step executors
|
|
262
|
+
|
|
263
|
+
## E2E Tests
|
|
264
|
+
|
|
265
|
+
### Directory: test/e2e/TS-FEATURE-001-workflow-execution/
|
|
266
|
+
|
|
267
|
+
#### TC-001: Complete workflow success
|
|
268
|
+
- Steps: Create config, run CLI, verify output
|
|
269
|
+
- Expected: Exit 0, output contains success message
|
|
270
|
+
|
|
271
|
+
#### TC-002: Workflow failure handling
|
|
272
|
+
- Steps: Create invalid config, run CLI
|
|
273
|
+
- Expected: Exit 1, error message is actionable
|
|
274
|
+
|
|
275
|
+
## Mock Data Needed
|
|
276
|
+
|
|
277
|
+
- fixtures/valid_config.yml
|
|
278
|
+
- fixtures/malformed_config.yml
|
|
279
|
+
- fixtures/large_config.yml
|
|
280
|
+
|
|
281
|
+
## Composite Helpers Needed
|
|
282
|
+
|
|
283
|
+
- with_mock_steps(count:, failing_at:)
|
|
284
|
+
- with_temp_config(content:)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Output
|
|
288
|
+
|
|
289
|
+
The test plan should be saved to:
|
|
290
|
+
- Task folder: `.ace-taskflow/.../task-XXX/test-plan.md`
|
|
291
|
+
- Or reviewed in conversation before implementation
|
|
292
|
+
|
|
293
|
+
## Checklist Before Implementation
|
|
294
|
+
|
|
295
|
+
- [ ] All new behaviors have tests planned
|
|
296
|
+
- [ ] Tests are at appropriate layers
|
|
297
|
+
- [ ] Edge cases identified
|
|
298
|
+
- [ ] Mock strategy defined
|
|
299
|
+
- [ ] No duplicate testing across layers
|
|
300
|
+
- [ ] E2E tests cover critical user paths only
|
|
301
|
+
|
|
302
|
+
## Integration with Other Workflows
|
|
303
|
+
|
|
304
|
+
### With `ace-bundle wfi://task/work`
|
|
305
|
+
|
|
306
|
+
1. Load task specification
|
|
307
|
+
2. **Load `ace-bundle wfi://test/plan`**
|
|
308
|
+
3. Implement feature
|
|
309
|
+
4. Write tests according to plan
|
|
310
|
+
5. Verify coverage
|
|
311
|
+
|
|
312
|
+
### With `ace-bundle wfi://test/create-cases`
|
|
313
|
+
|
|
314
|
+
Use this workflow first to plan, then `ace-bundle wfi://test/create-cases` to generate test code.
|
|
315
|
+
|
|
316
|
+
## See Also
|
|
317
|
+
|
|
318
|
+
- [Test Layer Decision Guide](guide://test-layer-decision)
|
|
319
|
+
- [Test Responsibility Map Guide](guide://test-responsibility-map)
|
|
320
|
+
- [Test Mocking Patterns Guide](guide://test-mocking-patterns)
|
|
321
|
+
- [Test Review Checklist](guide://test-review-checklist)
|
|
322
|
+
- [Create Test Cases Workflow](wfi://test/create-cases)
|
|
323
|
+
- [Verify Test Suite Workflow](wfi://test/verify-suite)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
doc-type: workflow
|
|
3
|
+
title: Test Review Workflow
|
|
4
|
+
purpose: test review workflow
|
|
5
|
+
ace-docs:
|
|
6
|
+
last-updated: 2026-03-12
|
|
7
|
+
last-checked: 2026-03-21
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Test Review Workflow
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Read `guide://test-review-checklist`.
|
|
15
|
+
2. Review the requested tests for layer fit, mock quality, coverage, and performance.
|
|
16
|
+
3. Read `guide://test-responsibility-map` when layer placement is unclear.
|