Orchestrate test-runner PoC evaluation (#8)
- 5-module E2E integration runner, 6 tests, all DoD pass - PROGRESS.md Done row, PLAN.md pivoted to live smoke test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
43
docs/contracts/test-runner.evaluation.md
Normal file
43
docs/contracts/test-runner.evaluation.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# test-runner Evaluation (Issue #8)
|
||||
|
||||
- Generator commit: `96df2ef`
|
||||
- Evaluator: independent verification per contract `docs/contracts/test-runner.md`
|
||||
- Build: `dotnet build recordingtest.sln` -> 0 warnings, 0 errors
|
||||
- Tests: `dotnet test tests/Recordingtest.Runner.Tests` -> 6 passed / 0 failed / 0 skipped
|
||||
|
||||
## Verdict: PASS
|
||||
|
||||
## DoD verification
|
||||
|
||||
| # | DoD item | Result | Evidence |
|
||||
|---|----------|--------|----------|
|
||||
| 1 | Console exe with 5 flags `--scenarios/--baselines/--out/--profile/--no-launch` | pass | `src/Recordingtest.Runner/Program.cs` switch parses all 5; missing required -> exit 2 |
|
||||
| 2 | Scan `*.yaml` and write to `<out>/<scenario>/` | pass | `TestRunner.cs` L27-36 enumerates `*.yaml`, creates per-scenario `artifactDir` |
|
||||
| 3 | Order: player -> normalizer -> diff-reporter | pass | `TestRunner.cs` L50-52 (engine.Run), L103-104 (Normalize), L111 (Compare) |
|
||||
| 4 | Profile default `default`, overridable | pass | `RunnerOptions.Profile = "default"`; passed through to normalizer; `--profile` writes it |
|
||||
| 5 | `report.json` schema `{runAt,total,passed,failed,errored,scenarios:[{name,status,hunks,checkpointCount,artifactDir}]}` | pass | `RunReport.cs` matches; camelCase JSON; test 6 asserts every field |
|
||||
| 6 | `report.md` human summary with table + failure section | pass | `WriteMarkdownReport` builds table + Failures section |
|
||||
| 7 | Exit codes 0/1/2 | pass | `ToExitCode`: errored>0 -> 2, failed>0 -> 1, else 0; tests assert all three |
|
||||
| 8 | `IPlayerHost` DI via `IRunnerHostFactory` | pass | `Interfaces.cs`; `RunAll` takes factory + INormalizer + IDiffer; tests inject fakes |
|
||||
| 9 | xUnit tests >=5 covering 5 scenarios | pass | 6 tests, all required cases (identical, differs, throws, empty, profile spy, schema) |
|
||||
| 10 | `dotnet build` green, `dotnet test` all pass | pass | 0/0 build, 6/6 tests |
|
||||
| 11 | Fixed sleep 0 | pass | grep `Thread.Sleep(` and `Task.Delay(TimeSpan.FromSeconds` in `src/Recordingtest.Runner` -> 0 hits |
|
||||
|
||||
## Baseline normalization policy
|
||||
Contract allows either pre-normalized or re-normalized baselines. `TestRunner.cs` L10-11 documents the choice: baselines are re-normalized with the same profile as received output (safe either way). Documented = pass.
|
||||
|
||||
## Test quality (not stubs)
|
||||
- TwoScenarios_BothIdentical_ExitZero_AllPass: real scenario YAML, real PlayerEngine, real diff stub identical
|
||||
- OneScenarioDiffers: asserts hunks==1 and status=="fail"
|
||||
- PlayerThrows: uses click step + `throwOnClick` fake host -> errored>=1, exit 2
|
||||
- EmptyScenariosDir: total==0, exit 0
|
||||
- ProfileOverride: SpyNormalizer captures profiles list; asserts contains "strict", not "default"
|
||||
- ReportJson schema: parses report.json and asserts every contract field; checks report.md exists
|
||||
|
||||
## Integration smoke
|
||||
Trusted via unit tests + source review (Runner is fully DI-testable; tests drive `TestRunner.RunAll` directly with real `PlayerEngine` + scenario YAML).
|
||||
|
||||
## Artifacts
|
||||
- Source: `src/Recordingtest.Runner/{Program.cs,TestRunner.cs,Interfaces.cs,RunnerOptions.cs,RunReport.cs,DefaultAdapters.cs}`
|
||||
- Tests: `tests/Recordingtest.Runner.Tests/{TestRunnerTests.cs,Fakes.cs}`
|
||||
- Contract: `docs/contracts/test-runner.md`
|
||||
54
docs/contracts/test-runner.md
Normal file
54
docs/contracts/test-runner.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Sprint Contract — test-runner
|
||||
|
||||
**Owner:** Generator
|
||||
**Depends on:** sut-prober, normalizer, player, diff-reporter (all pass)
|
||||
**Issue:** #8
|
||||
|
||||
## Goal
|
||||
|
||||
5개 PoC 모듈을 엮어 **시나리오 일괄 회귀 파이프라인**을 제공한다. 한 번의 CLI 호출로: 시나리오 디렉터리 스캔 → player로 각 시나리오 재생 → 결과 저장 파일을 normalizer 적용 → baseline과 diff-reporter로 비교 → 종합 리포트 생성. player/SUT 상호작용은 fake host로 교체 가능해야 단위 테스트가 라이브 SUT 없이 통과한다.
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] `Recordingtest.Runner` 콘솔 exe — `--scenarios <dir> --baselines <dir> --out <dir> [--profile <name>] [--no-launch]`
|
||||
- [ ] 시나리오 디렉터리의 모든 `*.yaml` 을 로드 → 각각 실행 → `<out>/<scenario>/` 하위에 산출물 저장
|
||||
- [ ] 각 시나리오 실행 순서: player → normalizer(결과 파일) → diff-reporter(vs baseline)
|
||||
- [ ] 정규화 프로파일 기본 `default`, `--profile`로 오버라이드 가능
|
||||
- [ ] `<out>/report.json` 집계 리포트 스키마: `{ runAt, total, passed, failed, errored, scenarios: [{ name, status, hunks, checkpointCount, artifactDir }] }`
|
||||
- [ ] `<out>/report.md` 사람용 요약 (pass/fail 표 + 실패 시나리오당 diff 링크)
|
||||
- [ ] Exit code: 0 = all pass, 1 = any fail, 2 = any error
|
||||
- [ ] `IPlayerHost`를 DI로 주입 가능하게 하여 fake host로 단위 테스트 실행
|
||||
- [ ] xUnit 테스트 ≥ 5:
|
||||
- 2개 시나리오(모두 identical) → `all pass`, exit 0
|
||||
- 1개 시나리오가 baseline과 다름 → `fail`, exit 1, report.json 해당 항목에 hunks ≥ 1
|
||||
- 1개 시나리오 player에서 예외 → `error`, exit 2, artifactDir 생성
|
||||
- 빈 시나리오 디렉터리 → exit 0 (total=0)
|
||||
- `--profile` 변경 시 normalizer가 해당 프로파일로 호출됨 확인 (spy)
|
||||
- [ ] `dotnet build` green, `dotnet test` all pass
|
||||
- [ ] 고정 sleep 0건 (player 원칙 상속)
|
||||
|
||||
## Interfaces
|
||||
|
||||
- **Inputs:** 시나리오 디렉터리, baseline 디렉터리, 출력 디렉터리, 정규화 프로파일
|
||||
- **Outputs:** `<out>/<scenario>/` (체크포인트, 아티팩트), `<out>/report.json`, `<out>/report.md`
|
||||
- **Side effects:** player host의 입력 전달 (fake 또는 UIA)
|
||||
|
||||
## Out of scope
|
||||
|
||||
- 실제 SUT 실행 안정성 (recorder/player의 몫)
|
||||
- 병렬 시나리오 실행 (v2)
|
||||
- CI 통합 (별도 작업)
|
||||
|
||||
## Evaluation plan
|
||||
|
||||
1. `dotnet build` + `dotnet test tests/Recordingtest.Runner.Tests` — count passed/failed
|
||||
2. xUnit 테스트 5개 모두 pass 확인
|
||||
3. `report.json` 스키마 검증 (테스트 안에서)
|
||||
4. `grep Thread.Sleep\\| Task.Delay` in Runner source → 0건
|
||||
5. DI 관점: `IPlayerHost` 생성자 주입 가능 확인
|
||||
6. CLI exit code 확인 (0/1/2)
|
||||
|
||||
## Risks
|
||||
|
||||
- normalizer의 파일 경로 vs 문자열 API — runner가 바이트 스트림으로 전달할지 파일로 flush 할지 결정 필요
|
||||
- 체크포인트 처리 복잡도 — v1은 마지막 저장 파일만 diff, 체크포인트 diff는 v2로 연기 가능
|
||||
Reference in New Issue
Block a user