독립 검증 도구 추가와 앱 상태 책임 분리

This commit is contained in:
2026-09-06 18:09:11 +09:00
parent 0f0431de5a
commit 002a922e1b
62 changed files with 3454 additions and 2008 deletions
+101
View File
@@ -0,0 +1,101 @@
# 검증과 성능 측정
## 독립 테스트
.NET 10 SDK를 설치하고 저장소 루트에서 실행합니다.
```bash
Tools/agentctl test
```
기본 `dotnet` 대신 특정 실행 파일을 사용하려면 `PROJECTQUINT_DOTNET`을 지정합니다.
Windows에서는 `Verification` 폴더에서 다음 명령을 직접 실행할 수 있습니다.
```bash
dotnet test ProjectQuint.Tests/ProjectQuint.Tests.csproj -c Release -p:RestoreLockedMode=true
```
패키지 버전과 간접 의존성은 `packages.lock.json`으로 고정합니다.
처음 패키지를 복원할 때는 인터넷 연결이 필요하며, 복원 후에는 `--no-restore`를 추가할 수 있습니다.
유니티 편집 모드와 .NET은 `Assets/ProjectQuint/Tests/Core`의 같은 테스트 파일을 사용합니다.
홈 화면 이동·프로필 선택·업데이트 상태 테스트 역시 유니티와 독립 실행에서 공유합니다.
## 합성 입력 탐색
```bash
Tools/agentctl list
Tools/agentctl replay --notes 1000 --seed 42 --fps 30
Tools/agentctl replay --notes 1000 --seed 42 --fps 240
```
`replay`는 합성 노트와 미리 시각을 정한 입력 이벤트를 시간순으로 병합해 실행합니다.
같은 노트 수와 시드에서 `result.judgement`를 비교하면 점수·콤보·판정 수·완료 여부를 확인할 수 있습니다.
입력에는 일반 노트, 롱노트, 고의적인 미입력과 조기 놓기가 포함됩니다.
가상 시간이므로 실제 곡 길이만큼 기다리지 않으며 음악이나 외부 BMS 폴더를 읽지 않습니다.
- `--notes`: 1부터 100,000까지의 노트 수입니다.
- `--seed`: 0 이상의 정수입니다. 노트별 입력 시각 변화를 재현합니다.
- `--fps`: 1부터 10,000까지의 가상 갱신 빈도입니다. 실제 FPS 측정값이 아닙니다.
- `--output`: 결과 JSON을 저장할 경로입니다. 상대 경로는 `Verification` 폴더를 기준으로 합니다.
`list`, `replay`, `benchmark`의 표준 출력은 JSON이며 빌드 진단과 진행률은 표준 오류로 분리합니다.
잘못된 인수와 실행 실패는 0이 아닌 종료 코드를 반환합니다.
검증 도구는 `Assets` 바깥에 있으므로 유니티 게임 빌드에 포함되지 않습니다.
이 도구는 코어 검증용이며 전체 게임 화면을 조작하는 인터페이스는 아닙니다.
## 성능 측정 재현
```bash
Tools/agentctl benchmark --notes 10000 --seed 42 --fps 240 --iterations 20 \
--output ../_workspace/core-benchmark.json
```
워밍업 3회 뒤 요청한 횟수만큼 실행합니다. `--iterations`의 허용 범위는 1부터 100입니다.
각 회차마다 진행률을 표시하고, 출력 경로를 지정하면 완료된 샘플을 중간 저장합니다.
모든 회차를 마친 결과에만 `complete: true`가 기록됩니다.
측정 중 중단된 결과를 최종 결과로 사용하지 않습니다.
원자료: [core-baseline.json](benchmarks/core-baseline.json).
| 항목 | 측정 조건 또는 결과 |
| --- | --- |
| 측정일 | 2026-09-06 |
| 실행 환경 | macOS ARM64, .NET 10.0.11, 프로세스에서 관측한 논리 프로세서 18개 |
| 입력 | 노트 10,000개, 입력 이벤트 18,822개, 시드 42 |
| 가상 갱신 빈도 | 초당 240회 |
| 반복 | 워밍업 3회, 본 측정 20회 |
| 엔진 생성 시간 | 중앙값 0.995 ms, 최솟값 0.845 ms, 최댓값 2.797 ms |
| 전체 입력 재생 시간 | 중앙값 4.831 ms, 최솟값 4.675 ms, 최댓값 5.243 ms |
| 엔진 생성 중 관리 메모리 할당 | 중앙값 1,544,688바이트 |
| 입력 재생 중 관리 메모리 추가 할당 | 20회 모두 0바이트 |
시간은 `Stopwatch`로, 할당량은 `GC.GetAllocatedBytesForCurrentThread`로 측정했습니다.
합성 입력 생성과 결과 JSON 직렬화는 측정 구간에서 제외합니다.
엔진 생성과 입력 재생을 나눠 기록하므로 준비 비용을 무시하지 않습니다.
각 회차의 판정 결과가 워밍업과 같은지 확인하고, 다르면 측정을 실패 처리합니다.
이는 현재 구현의 기준 측정이지 최적화 전후 비교가 아닙니다.
JIT 상태와 다른 프로세스의 부하에 따라 시간은 달라질 수 있으며 절대 시간으로 테스트를 실패시키지 않습니다.
관리 메모리 측정에는 다른 스레드·네이티브 할당이 포함되지 않습니다.
화면 렌더링·오디오 출력·앱의 판정 이벤트 구독자도 실행하지 않으므로,
이 결과로 실제 게임 전체의 무할당 동작이나 입력 지연을 주장할 수 없습니다.
## 유니티와 실제 플레이 검증
유니티 `6000.3.20f1`에서 `EditMode` 테스트를 실행합니다.
명령줄에서는 `-runTests -testPlatform EditMode -testResults <파일> -logFile <파일>`을 사용하며
`-quit`는 함께 전달하지 않습니다. 에디터 활성화와 프로젝트 의존성 복원이 필요합니다.
외부 BMS 자료가 필요한 테스트는 별도의 환경 변수로 경로를 받습니다.
독립 검증은 실제 FMOD 출력, 장치 전환, 화면 조작과 파일 선택 창을 검증하지 않습니다.
음악을 재배포하지 않는 범위에서 실제 플레이로 로딩 취소·다시 시작·장치 변경·프로필 화면을 확인해야 합니다.
자동화 서버에서의 연속 실행과 실제 플레이어 성능 측정은 별도 운영 범위입니다.
2026-09-06 검증에서는 독립 테스트 142개와 배포 도구 테스트 9개가 통과했습니다.
유니티 컴파일러를 이용한 어셈블리 11개의 컴파일도 확인했습니다.
유니티 Test Runner는 유효한 에디터 라이선스가 없어 테스트 시작 전에 종료되었으므로,
편집 모드 전체 테스트와 실제 플레이 검증은 완료된 것으로 기록하지 않습니다.
앱의 업데이트와 프로필 상태는 독립 컨트롤러가 소유하지만,
팩 관리·오디오 설정·화면 연결을 조정하는 코드는 아직 큰 앱 클래스에 남아 있습니다.
추가 분리 시에는 관련 동작 테스트를 확보하고 같은 검증 절차를 반복합니다.