人間による実機確認を「カメラ・光源 SDK の実呼び出し」と「実画像の見た目」だけに絞り,それ以外の回帰を自動テストで担保する.
方針の本体(常に従う規約)は testing.md に置き,本書はそこへ移行するための段取り(フェーズ・完了条件・リスク)を定める.
/auto-audit では,報告した指摘 26 件の多くが「CameraBase・Form1・カメラ層で再現テストを書けない」ことを理由に自動修正できなかった.中でも保存失敗が成功扱いになる件や終了時の画像取りこぼしは,データ欠損に直結する.SelfTest/SelfTestCamera)とヘッドレス Form1(Form1.SelfTest.cs)がすでにあり,セルフテストでは CameraBase の校正〜保存を通している.NUnit で細かく検証していないだけで,自動化できない範囲は思っていたより狭い.| 確認内容 | 本当に実機が要るか | 移行先 |
|---|---|---|
| カメラ接続・露光/ゲインの反映・フレーム取得 | 要る(SDK の実呼び出し) | 実機に残す(層④) |
| 光源の ON/OFF | 要る(シリアル通信) | 実機に残す(層④) |
| 校正の自動開始〜完了,撮影ボタンの有効化 | 判断ロジックは不要 | 層②(偽カメラ+ヘッドレス Form1) |
| 単発・連続撮影でファイルが保存される | 不要 | 層②・セルフテスト |
| 保存失敗・ディスク満杯・設定破損時の挙動 | 不要(失敗を注入できる) | 層② |
| アプリを閉じてもエラーが出ない | 終了順序の判断は不要 | 層②(SDK の停止そのものは層④) |
| 校正結果・色の妥当性 | 合成チャートでは不十分 | 実機録画データによる回帰(層①の拡張) |
| 層 | 対象 | テスト手段 |
|---|---|---|
| ① ピュアロジック | 色補正・チャート検出・CSV・設定・ゲイン計算・画像統計 | NUnit(実値で検証) |
| ② 結合ロジック | CameraBase の校正の状態遷移・撮影ループ・SaveThread・失敗通知・終了処理,Form1 の UI 連携メソッド | NUnit+偽カメラ+ヘッドレス Form1(STA スレッドでメッセージを処理するハーネス) |
| ③ SDK アダプタ | IScam・Lucam・LightSource | 判断ロジックを純粋関数へ切り出して層①で検証する.SDK 呼び出しそのものは層④ |
| ④ 実機 | SDK の実呼び出し・実画像の見た目 | 短い手動チェックリスト(TEST_01) |
詳細な判断基準は testing.md を参照する.
2026-10-06 にユーザーと合意した.
| 項目 | 決定 |
|---|---|
テストプロジェクトへの System.Windows.Forms 参照追加 | 許可する(.NET Framework 標準アセンブリで NuGet 依存は増えない) |
層②(CameraBase を NUnit で検証) | 行う |
| 層③(SDK アダプタからの判断ロジック切り出し) | 撮影・保存の信頼性修正(/auto-audit 報告の束 B)と同時に行う |
| 実機録画データ | 撮る.舌診チャートと白板のみ(舌の画像は個人情報のため扱わない) |
| カバレッジ | 数値目標は課さず,「一度も通っていない箇所」を見つける地図として使う |
| 実機録画データの置き場所 | Git LFS で管理する.CI が無くテストは開発マシンでしか回らないため,コードと同じ版のデータが clone で確実に手元に来る方式を選んだ.1 機種・1 場面あたり 3〜5 フレームに絞り,合計 100〜150MB 程度に抑える(GitHub の LFS 無料枠はストレージ 1GB・転送量 1GB/月) |
| 層②のテストの実行時間 | 層②全体で 30 秒を目安とし,1 件あたり 15 秒のタイムアウトを付ける.超えそうなときはテスト用設定(校正フレーム数等)を見直して速くする./auto-audit は修正 1 件ごとにテスト一式を何度も回すため,ここが延びると全作業が遅くなる |
/verify に含めるか | 常に含める(run_selftest.py は絞り込まずに全件実行するので追加設定は不要).CI が無く,/verify・/auto-audit が実質唯一の自動チェックのため,カテゴリで分けて通常は回さない運用にはしない |
| メモリ量で判定するテスト | 2026-10-06 に追加したリーク再現テスト等は [Category("Memory")] に分け,環境による不安定さが出たら通常の実行から外せるようにする |
System.Windows.Forms の参照を追加するForm1 を生成してハンドルを作る(SelfTestStart)SelfTestRunner の Application.DoEvents による待機と同じ考え方で,可能なら共通化するconfig.xml を用意する(Config.Load(path) を使う)Calib/Frames)等を小さくし,1 件あたり 1 秒前後で終わるようにする[Category("Memory")] を付ける/auto-audit 報告台帳)の赤テストを書き,修正するSELFTEST は Debug 系のみ)TIASshot.Tests/IntegrationHarness.cs.一時 config の作成と待機処理は TIASshot/SelfTest/SelfTestConfig.cs・SelfTestPump.cs に切り出し,セルフテストのランナーと共用するCameraBaseSaveIntegrationTests(保存成功・単発の保存失敗・連続撮影の途中の保存失敗)は 3 回連続で緑.保存失敗の 2 件は修正前のコードで赤になることを確認した.層② 3 件の所要時間は計約 5 秒Cv2.ImWrite に false を返させる方法をとった(例外ではなく false になることを単体テストで固定している)CalcTcc の校正画像の保存失敗は「自動校正完了」と表示される(失敗時に校正済みとするかが仕様判断のため未修正)SaveThread(保存失敗・例外時の後始末・残りフレームの破棄)Form1 の UI 連携メソッド(UI スレッド外からの呼び出しを含む)/auto-audit 報告台帳のうち,層②で再現テストを書けるようになった項目をここで修正するForm1 の取得系メソッドが UI スレッド外で値を返さない,再検出時と切断時にチャートマスクを解放しない,ResetShotQueue が残った画像を解放しない,撮影失敗行の Note 欄のクォート漏れ.再現テスト 7 件は修正前のコードで赤になることを確認したCalib/ConversionChannels=4)に絞って時間を抑えた.全次元での保存はフェーズ 1 の単発撮影テストで確認しているCalcTcc の例外境界と校正画像の保存失敗,Form1_FormClosing,SaveThread の同期 Invoke,DrainShots の待ち時間,撮影枚数 0 の完了表示.束 B(フェーズ 3 と同時)で方針を決めてから扱うDisconnect でストリーム停止の直後にマスクを解放してよいか(SDK がコールバックの終了を待つか)IScam・Lucam・LightSource から判断ロジックを純粋関数として切り出す
2026-10-06 にユーザーと合意した.
| 論点 | 方針 |
|---|---|
校正中の例外(CalcTcc・ProcessCalibrationFrame) | カメラのコールバックへ例外を伝えない.捕捉してログを残し,「校正に失敗しました」と通知し,チャート検出からやり直せる状態(未校正・マスク解放)に戻す.通知がチャート検出の進捗表示ですぐ上書きされないよう,次に校正が完了するまで検出中の表示を「校正に失敗しました(理由).チャートの検出からやり直しています」に差し替えて出し続ける(エラーダイアログはカメラのコールバックを止めるため使わない) |
| 校正画像(TccImage・TccRoisImage)の保存失敗 | 変換行列はメモリ上で有効なので校正済みのままにし,「自動校正完了(校正画像の保存に失敗)」のように警告を表示する |
アプリを閉じるとき(Form1_FormClosing) | 保存中なら閉じるのを取り消して「保存中」と知らせる(閉じる理由は区別しない.Windows のシャットダウン時も取り消し,待つか強制終了するかはユーザーに選ばせる).閉じ始めたらカメラのコールバックから UI への呼び出しを行わない(ハングの防止).光源のポートを閉じる(消灯はしない.終了後も光源は点いたまま.上流 v1.7 と同じ動作で,2026-10-08 にユーザーが仕様として確定) |
| 保存スレッドから UI への通知 | 進捗表示などは UI スレッドを待たない非同期の呼び出しにする(撮影中でも保存が進み,画像がキューに溜まり続けない) |
保存キューの待ち時間(DrainShots) | 固定 30 秒をやめ,「30 秒」と「撮影間隔の 2 倍」の大きい方にする |
Form1.CanClose・CameraBase.GetDrainIdleTimeout・FormatCalibrationFailure・ShouldNotifyCalibrationFailure・FormatChartDetectionMessage・FormatCalibrationDone として切り出し,層①でテストした/auto-audit 報告台帳の該当項目)git lfs の導入確認,.gitattributes での対象パターン指定,GitHub 側の LFS の利用確認)Microsoft.CodeCoverage(テストプロジェクトに導入済み)で未通過の箇所を確認し,重要な経路の抜けを埋める当初はフェーズ 5 完了後に残す項目を想定していたが,実機を Claude が操作して確かめる実機テスト(PLAN_06)ができたため,2026-10-09 に PLAN_06 フェーズ 3 で TEST_01 の手動テストを先に縮めた.現在 TEST_01 に残している項目は次のとおり(詳細は TEST_01「手動テスト」).
※ 接続・プレビューのフレーム・露光/ゲイン・光源・校正・撮影と保存・プレビュー中/保存中/校正中に閉じる,は実機テストで,保存ファイルの有無・内容・失敗時の通知・撮影ボタンの有効/無効は層②とセルフテストで確かめ,手動では確認しない.
| リスク | 対策 |
|---|---|
| WinForms のテストがハング・不安定になる(STA・メッセージ処理の誤り) | ハーネスを 1 か所に集約し,待機には必ずタイムアウトを付ける.新しいハーネス利用テストは 3 回連続実行で安定性を確認してから取り込む |
テストの実行時間が延びて /verify や /auto-audit が遅くなる | 層②のテストに [Category("Integration")] を付けて所要時間を計測し,全体 30 秒の目安を超えそうならテスト用設定を見直して速くする(/verify から外すことはしない) |
テストが Form1 の内部構造に依存して壊れやすくなる | Form1.SelfTest.cs のアクセサ(SelfTestMessage・SelfTestLastError・SelfTestShotsEnabled 等)経由でのみ観測する.足りないアクセサはそこに追加する |
| メモリ量で判定するテストが環境によって不安定になる | 2026-10-06 に追加したリーク再現テスト(プライベートメモリ増分のしきい値判定,OpenCV 内部の参照カウント読み取り)を棚卸しし,必要なら [Category("Memory")] に分ける |
| 実機録画データが大きい/個人情報を含む | 舌診チャートと白板に限る.フレーム数を絞り Git LFS で管理する.LFS の転送量の無料枠(1GB/月)を超えそうなら,データの削減か有料枠を検討する |