# 開発コマンド (Development Commands)

日常の開発で使うビルド・テスト・実行コマンドをまとめる．人間とエージェント（tester・coder，`/auto-refactor`・`/auto-audit`）が**コマンドを推測せずに済むための唯一の参照先**とする．コマンドが増減・変更されたら本ファイルを更新する．

## 前提 (Prerequisites)

- ビルドは **x64 のみ**（`TIASshot.sln` は `Debug|x64` / `Release|x64` のみ定義）．OpenCvSharp 等がネイティブ DLL に依存するため `AnyCPU` は使わない．
- レガシー形式（packages.config）のため **`dotnet build` / `dotnet test` は使えない**．MSBuild と `vstest.console.exe` を使う．
- コマンドは PowerShell で実行する．VS のエディション差（Community / Professional / Enterprise）と Build Tools のみの環境を吸収するため，`vswhere` で MSBuild・vstest の場所を解決する．

## ツールパスの解決 (Locating Build Tools)

```powershell
$vs = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -property installationPath
$msbuild = Join-Path $vs "MSBuild\Current\Bin\MSBuild.exe"
$vstest  = Join-Path $vs "Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe"
```

※ `-products *` は必須．これが無いと `vswhere` は通常の VS 製品しか列挙せず，**VS Build Tools のみ**の環境では何も返さない（`$vs` が空になり `Join-Path` が失敗する）．

以降のコマンドは `$msbuild` / `$vstest` を解決済みとして記載する．

## NuGet 復元 (Restore)

```powershell
nuget restore TIASshot.sln
```

`nuget.exe` が PATH に無い場合はリポジトリルートの `nuget.exe` を使う（`setup.ps1` が未取得時に自動ダウンロードする）．

## ビルド (Build)

```powershell
# 開発・検証（WHITEBOARD / MEMMONITOR 有効）
& $msbuild TIASshot.sln /t:Build /p:Configuration=Debug /p:Platform=x64

# 配布版（診断機能なし）
& $msbuild TIASshot.sln /t:Build /p:Configuration=Release /p:Platform=x64

# クリーンビルド
& $msbuild TIASshot.sln /t:Rebuild /p:Configuration=Debug /p:Platform=x64
```

構成ごとのビルドフラグの意味は [ENV_06_ビルド構成とビルドフラグ](ENV_06_ビルド構成とビルドフラグ.md) を参照する．

## テスト (Test)

自動テストの方針・対象範囲は `.claude/rules/testing.md` を参照する（本ファイルはコマンドのみ）．

```powershell
# テストプロジェクトをビルドしてから x64 で実行する
& $msbuild TIASshot.sln /t:Build /p:Configuration=Debug /p:Platform=x64
& $vstest "TIASshot.Tests\bin\x64\Debug\TIASshot.Tests.dll" /Platform:x64
```

- ネイティブ DLL を x64 でロードするため `/Platform:x64` は必須．
- Visual Studio 上ではテストエクスプローラーから実行できる（プラットフォームを x64 にすること）．

カテゴリで絞り込んで実行する（開発中の確認用．判定には全件実行を使う）．

```powershell
# 層②（結合ロジック）のテストだけ実行する
& $vstest "TIASshot.Tests\bin\x64\Debug\TIASshot.Tests.dll" /Platform:x64 "/TestCaseFilter:TestCategory=Integration"
# メモリ量で判定するテストを除いて実行する（環境による不安定さを切り分けるとき）
& $vstest "TIASshot.Tests\bin\x64\Debug\TIASshot.Tests.dll" /Platform:x64 "/TestCaseFilter:TestCategory!=Memory"
```

- 層②のテストは `SELFTEST` フラグに依存するため，Debug 構成でのみコンパイル・実行される．

## クリーン環境での検証 (Clean Verification)

**ベースライン計測・マージ前検証・「テストが通ることの確認」は，必ず `bin` / `obj` を削除してから行う．**

`bin` に前回のビルド成果物が残っていると，過去のビルドでコピーされた DLL が残存してアセンブリ解決が偶然成立し，**依存の記述漏れを隠してしまう**（Issue #39: テストプロジェクトに OpenCvSharp の推移的依存が無いにもかかわらず，汚れた `bin` では全緑に見えていた）．同じマシンで作業し続ける限り気づけないため，計測・検証の前に毎回消す．

```powershell
# bin / obj を削除してからビルド・テストする
Get-ChildItem -Path TIASshot, TIASshot.Tests -Include bin, obj -Directory -Recurse | Remove-Item -Recurse -Force
& $msbuild TIASshot.sln /t:Build /p:Configuration=Debug /p:Platform=x64
& $vstest "TIASshot.Tests\bin\x64\Debug\TIASshot.Tests.dll" /Platform:x64
```

依存パッケージを追加・変更した PR の検証では，これに加えて `packages` も退避して `nuget restore` からやり直し，**新しいマシンでの `git clone` 直後と同じ状態**を再現する．

```powershell
# clone 相当の完全クリーン検証（packages も退避する）
Get-ChildItem -Path TIASshot, TIASshot.Tests -Include bin, obj -Directory -Recurse | Remove-Item -Recurse -Force
Rename-Item packages packages.bak      # 復元に失敗したときのために削除せず退避する
nuget restore TIASshot.sln
& $msbuild TIASshot.sln /t:Build /p:Configuration=Debug /p:Platform=x64
& $vstest "TIASshot.Tests\bin\x64\Debug\TIASshot.Tests.dll" /Platform:x64
```

- 合格条件: **テストが全件成功し，ビルド警告が増えていないこと**．
- `packages` の復元にはネットワークと時間がかかるため，通常の開発サイクルでは `bin` / `obj` の削除までで運用し，完全クリーン検証は依存変更時とマージ前に行う．
- 検証が終わったら退避した `packages.bak` は削除してよい（`nuget restore` で再取得できるため）．

## テストランナー (Test Runner)

上記「テスト」のビルド〜vstest 実行を 1 コマンドにまとめたランナー．**tester・refactorer エージェントはこれを使う**（エージェントの環境からは MSBuild・vstest を直接呼べないため．実行権限は `.claude/agents/` の tools で許可している）．人間が使ってもよい．

```bash
# 全件（Debug 出力を削除 → ビルド → テスト．判定にはこれを使う）
python scripts/verify/run_tests.py
# 絞り込み（vstest の /TestCaseFilter の式をそのまま渡す）
python scripts/verify/run_tests.py --filter "TestCategory=Integration"
# 安定性の確認（ビルドは 1 回，テストを 3 回続けて実行する）
python scripts/verify/run_tests.py --filter "TestCategory=Integration" --repeat 3
# 開発中の素早い再確認（Debug 出力を消さない．判定には使わない）
python scripts/verify/run_tests.py --filter "FullyQualifiedName~ConfigTests" --no-clean
```

- 出力先: `.verify/tests/run-<日時>/`（`build.log`・`test-<n>.log`・`result-<n>.trx`・`summary.json`）．画面には件数と，失敗したテストの名前・メッセージが出る
- 終了コード: `0`=全て合格，`1`=不合格あり（ビルド失敗・テスト失敗・絞り込みで該当 0 件），`2`=前提条件を満たさない（Visual Studio / Build Tools 未導入等）
- 既定で Debug 出力を削除してからビルドする．修正を一時的に戻して赤を確かめるときなどに，更新日時の古いファイルが再コンパイルされず古い結果を見てしまうのを防ぐため
- セルフテスト（`TIASshot.exe --selftest`）は実行しない．それは下記「セルフテスト」の `run_selftest.py` で行う

## 実行 (Run)

ビルド後，構成に対応した実行ファイルを起動する．実行時参照ファイル（`config.xml`・カメラ設定 XML・TCC の CSV）が同ディレクトリに配置済みであること（[ENV_02_環境構築手順](ENV_02_環境構築手順.md)）．

```powershell
# 開発・検証版
& "TIASshot\bin\x64\Debug\TIASshot.exe"

# 配布版
& "TIASshot\bin\x64\Release\TIASshot.exe"
```

実機カメラ・光源に接続して動作する UI アプリのため，完全な動作確認には機材が必要．

## セルフテスト (Self Test)

実機なしで確認できる範囲（依存アセンブリのロード・プレビュー経路・校正〜保存）を，フォームを表示せずに検査する（`Debug|x64` のみ．[ENV_06](ENV_06_ビルド構成とビルドフラグ.md) の `SELFTEST`）．

```powershell
# クリーンビルド → 既存テスト → セルフテストをまとめて実行する（結果は .verify/selftest/run-<日時>/）
python scripts/verify/run_selftest.py
# 依存パッケージを変更したとき（packages を退避して nuget restore からやり直す）
python scripts/verify/run_selftest.py --full

# セルフテスト単体（WinExe のため Start-Process -Wait で終了コードを受け取る）
$p = Start-Process "TIASshot\bin\x64\Debug\TIASshot.exe" -ArgumentList "--selftest","--selftest-out","$env:TEMP\tias-selftest.txt" -Wait -PassThru
$p.ExitCode                                     # 0=全項目合格，1=不合格あり，2=セルフテスト自体の異常，3=タイムアウト
Get-Content "$env:TEMP\tias-selftest.txt"      # 各項目の PASS/FAIL と理由（UTF-8 BOM 付き）
```

- ランナーがクリーンするのは Debug 出力（`TIASshot/` と `TIASshot.Tests/` の `bin/x64/Debug`・`obj/x64/Debug`）のみ．`bin/x64/Release` 等ほかの構成の出力は消さない．`--no-clean`・`--skip-tests` は開発時の短縮用で，検証の判定には使わない．
- `--selftest-keep` を付けると，合格時も作業フォルダ（`%TEMP%\TIASshot-selftest\work-*`．校正データ・保存画像）を残す（不合格時は常に残る）．
- verifier（`/verify`）による自動検証の手順・判定の読み方は `.claude/verify-profile.md` を参照する．

## 実機テスト (Hardware Test)

実機のカメラと光源を操作して，接続・プレビュー・露光/ゲイン・光源・閉じる処理・再接続を検査する（`Debug|x64` のみ．[ENV_06](ENV_06_ビルド構成とビルドフラグ.md) の `HWTEST`．計画は [PLAN_06](../03_PLAN/PLAN_06_実機自動テスト計画.md)）．実際の `Form1` が表示される．

**ユーザーの合図があるときだけ実行する**（撮影の本番中に機材を操作しないため．Claude は合図なしに実行しない）．

前提:

- カメラ・光源のドライバが入っている（[ENV_02](ENV_02_環境構築手順.md) の「カメラ・光源のドライバ」）
- 検査する機種のカメラと光源が開発 PC に接続されている
- カメラの前の穴にカラーチャート（または白板）がはめてある（チャート不要の検査の間は自動校正を止める）
- TIASshot が起動していない（起動中ならランナーは実行せずに終了コード 2 を返す）

```powershell
# ビルド（Debug|x64）→ 実機テスト（結果は .verify/hwtest/run-<日時>/）．2 機種とも行う場合は機種ごとに実行する
python scripts/verify/run_hwtest.py --camera lucam
python scripts/verify/run_hwtest.py --camera iscam
# 開発中の素早い再確認（Debug 出力を消さない．判定には使わない）
python scripts/verify/run_hwtest.py --camera iscam --no-clean

# 実機テスト単体（WinExe のため Start-Process -Wait で終了コードを受け取る．実行ファイルのフォルダで実行する）
$p = Start-Process "TIASshot\bin\x64\Debug\TIASshot.exe" -WorkingDirectory "TIASshot\bin\x64\Debug" -ArgumentList "--hwtest","--camera","iscam","--hwtest-out","$env:TEMP\tias-hwtest.txt" -Wait -PassThru
$p.ExitCode                                     # 0=全項目合格，1=不合格あり，2=実機テスト自体の異常，3=タイムアウト
Get-Content "$env:TEMP\tias-hwtest.txt"        # 各項目の PASS/FAIL と測定値（UTF-8 BOM 付き）
```

- 書式: `python scripts/verify/run_hwtest.py --camera <lucam|iscam> [--with-chart] [--no-clean]`．`--with-chart`（チャートが必要な検査．PLAN_06 フェーズ 2）は未実装で，指定すると機材に触れずに終了コード 2 になる．
- 単体の書式: `TIASshot.exe --hwtest --camera <lucam|iscam> [--hwtest-out <結果ファイル>] [--with-chart] [--hwtest-keep]`．`--hwtest-keep` を付けると合格時も作業フォルダ（`%TEMP%\TIASshot-hwtest\work-*`）を残す（不合格・タイムアウト時は常に残る）．
- 出力先: `.verify/hwtest/run-<日時>/`（`build.log`・`hwtest-result.txt`・`summary.json`）．
- ランナーの終了コード: `0`=全項目合格，`1`=不合格あり（ビルド失敗・検査の不合格・タイムアウト），`2`=前提条件を満たさない（ツール未導入・TIASshot 起動中・指定機種が見つからない・引数不正・`--with-chart`）．
- 実機テスト単体の終了コード（`summary.json` の `hwtest_exit_code`）: `0`=全項目合格，`1`=不合格あり，`2`=実機テスト自体の異常（引数不正・指定機種が見つからない・未実装の指定），`3`=タイムアウト（各項目の上限または全体 10 分．ランナーでは `1` になる），`null`=ランナーが 720 秒で打ち切った．
- NUnit テスト・セルフテストは実行しない（それぞれ `run_tests.py`・`run_selftest.py`）．
- 検査項目・しきい値・判定の読み方は `.claude/verify-profile.md` の「実機テスト」節と [TEST_01](../06_TEST/TEST_01_テスト仕様.md) を参照する．
