Files
recordingtest/docs/contracts/recorder.evaluation.md
minsung 836afea5ee Orchestrate P1 UI automation evaluations (#6, #7)
- recorder v1 (fail) → v2 (pass): drag state machine, focus events, ts/raw_coord
- player pass with caveats: reliability untestable in sandbox
- PROGRESS.md Done rows + follow-ups for live SUT smoke test
- PLAN.md P1 pivoted to test-runner + live smoke test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 14:37:14 +09:00

4.7 KiB

Recorder — Evaluation (v2)

  • Generator commit: 56b7233
  • Build: dotnet build recordingtest.sln → green (0 warnings, 0 errors)
  • Tests: dotnet test tests/Recordingtest.Recorder.Tests → 9 passed / 0 failed / 0 skipped
  • Evaluator: independent re-read of source + tests after Generator iteration 2
  • Previous evaluation archived at docs/contracts/recorder.evaluation.v1.md

Verdict table

# DoD item Verdict Evidence
1 Console attach to SUT + 입력 캡처 시작 pass (source) / untestable (live) Program.TryAttach attaches by pid or by window-title scan via Application.Attach; never Launch(). LowLevelHook installs WH_KEYBOARD_LL + WH_MOUSE_LL on a dedicated STA thread. Cannot exercise against EG-BIM Modeler in this sandbox.
2 캡처 이벤트: 키 down/up, 클릭/드래그/휠, 포커스 변경 pass LowLevelHook emits key_down/up, mouse_down_l/r/m, mouse_up_l, wheel, move. DragCollapser is a real state machine: on mouse_down_l it stores the down event and tracks max distance through moves; on mouse_up_l it picks drag if max(maxDistSq, finalDistSq) >= threshold² else click. Right-click and key/wheel paths emit their own steps. Program.cs calls automation.RegisterFocusChangedEvent(...), builds an UIA path inside the callback (try/catch-guarded) and pushes a synthetic focus_change RawEvent into the same channel; DragCollapser translates it to a focus ScenarioStep.
3 Event shape {ts, kind, uia_path, offset_norm, raw_coord, value} pass RawEvent carries TimestampMs, Kind, X, Y, Code, WheelDelta, FocusedElementPath. ScenarioStep now exposes Ts, RawCoord, EndOffset, EndRawCoord plus existing Kind/Target{UiaPath,Offset}/Value/WaitFor. DragCollapser populates Ts and RawCoord (and end variants for drags) on every emitted step.
4 3D viewport offset_norm ∈ [0..1] pass OffsetNormalizer.Normalize clamps each axis to [0,1]; covered by OffsetNormalizer_ClicksInsideElement_ReturnsZeroToOne.
5 Yaml schema 준수 pass ScenarioWriter uses UnderscoredNamingConvention; ts and raw_coord therefore serialize as snake_case. ScenarioStep_YamlRoundtrip_PreservesTsAndRawCoord asserts both ts: and raw_coord appear in the yaml and round-trip back to identical values. YamlSerializer_RoundtripsScenario covers click + masked-type.
6 비밀번호/토큰 마스킹 pass MaskPolicy.Apply returns <MASKED> for IsPassword or ClassName == "PasswordBox". DragCollapser calls MaskPolicy.IsMasked on the resolved snapshot for both click and key paths and overrides step.Value = MaskPolicy.MaskedValue. Unit covered by FocusedElementIsPassword_ReturnsMasked.
7 60 FPS 영향 없음 untestable Requires running SUT + perf measurement; not possible in sandbox. Architecture (separate STA hook thread + unbounded Channel, UIA resolution moved out of the hook callback) is consistent with the requirement. Explicitly deferred.
8 종료 시 요약(이벤트 수, 소요 시간, 미결 건수) pass Program.Run writes [recorder] done. events={count} elapsed={sw.Elapsed} unresolved_paths={unresolved} on Ctrl+C exit.

Tests (9)

  1. ElementPathBuilder_WithNestedElements_ReturnsFullPath
  2. OffsetNormalizer_ClicksInsideElement_ReturnsZeroToOne
  3. FocusedElementIsPassword_ReturnsMasked
  4. YamlSerializer_RoundtripsScenario
  5. Cli_MissingAttach_ExitTwo
  6. DragCollapser_DownMoveUp_BeyondThreshold_EmitsDrag (new — drag emit beyond threshold)
  7. DragCollapser_DownUp_BelowThreshold_EmitsClick (new — click emit below threshold)
  8. DragCollapser_FocusChangeEvent_EmitsFocusStep (new — focus_change → focus step)
  9. ScenarioStep_YamlRoundtrip_PreservesTsAndRawCoord (new — yaml ts + raw_coord)

All four iteration-2 tests are present, meaningful, and assert the previously-missing behavior (state machine threshold, focus translation, snake_case persistence).

Configurable threshold

DragCollapser constructor: public DragCollapser(int dragThresholdPx = 4) and stored on DragThresholdPx. Default 4 px as required.

Remaining items

  • DoD #1 live attach + DoD #7 perf: structurally untestable in this sandbox; deferred to manual smoke on a workstation with EG-BIM Modeler. Source-side wiring is correct. These are no longer "missing code" — they are environment-bound.
  • IME (한글 조합) handling: still not implemented; this is a contract Risk, not a DoD item.

Overall verdict

pass — all DoD items with code obligations are satisfied; the only non-pass cells (1 live, 7) are explicitly deferred as untestable in the sandbox, not missing code. v1 release gates (drag collapse, focus capture, ts+raw_coord persistence, drag-state-machine tests) are all closed.