Newer
Older
TIASjudge / docs / 06_TEST / TEST_01_回帰テスト採取手順.md

回帰テスト採取手順 (Regression Data Capture Procedure)

PLAN_02 ステップ 5「回帰テスト」で使う 旧実装 exe の入出力ペア を採取する手順. 本作業は人間が行う(PLAN_02「人間が行う作業」).採取した CSV を tests/fixtures/regression/ に置くと,uv run pytest の回帰テストが自動で有効になる.

目的 (Purpose)

新実装(src/tiasjudge/core/)が旧実装と同じ診断結果を返すことを証明する(PLAN_01 成功基準・M1). そのために «同じ入力に対する旧 exe の出力» を固定データとして採取する.

採取方式の考え方 (Capture Design)

旧 exe には RGB や L*a*b* を直接入力する画面が無い(org/src を確認済み). 入力経路は「PNG 画像を読み込み → 画像上をクリック → その ROI の平均色」だけであり, さらにクリック位置を手作業で再現できないという問題がある(PLAN_02 の注記).

そこで次の方式で採取する.

  • 画像全面を単一色で塗った PNG を読み込ませる
    • ROI(51×51 px)がどこに置かれても平均色は画像の色そのものになる
    • → クリック位置が 1 px ずれても入力 RGB が変わらない=再現可能な入力になる
    • → 入力 RGB は «画像を作るときに指定した R, G, B» として厳密に分かる
  • 出力は 1 回の診断で L*a*b* と 5 色スコアの両方をメイン画面から読み取れる
    • → 「RGB → Lab」と「RGB → スコア(パイプライン全体)」の 2 種類を同時に採取できる

※ 「Lab → スコア」を単独で採取することは,旧 exe に Lab の入力手段が無いためできない. またメイン画面の L*a*b* 表示は整数に丸められているため,表示された Lab を入力として 使い回すと SVM の予測が変わりうる.したがって Lab は «出力側の照合対象» としてのみ扱う (形式定義 README の ③ の注意を参照).

事前準備 (Prerequisites)

  1. 旧実装 exe を実行できる状態にする
    • 実行ファイル: org/src/tonguediagnosisMFC2/x64/Release/tonguediagnosisMFC2.exe(または Debug)
    • exe と同じ作業フォルダに data.csv と img/img_student2.bmp が必要 (org/src/tonguediagnosisMFC2/ 直下でそのまま実行するのが確実)
  2. 撮影環境の 変換行列 CSV(17 行 × 3 列)を 1 つ用意する
    • 実際の診断で使っているものを使う.どのファイルを使ったかを必ず控える
  3. 採取用の単色 PNG を生成する(下記)

単色 PNG の生成 (Generate Solid-Color Images)

リポジトリ直下で次を実行する(生成先はリポジトリ外・作業用フォルダを推奨).

uv run python scripts/generate_regression_images.py --out-dir <出力先フォルダ>
  • 既定で 12 枚(代表的な舌色・境界値・域外色)を 1024×1280 px で生成する
  • ファイル名は rgb_156_102_098.png のように RGB がそのまま入る(採取時の取り違え防止)
  • 色を指定したい場合: --color 156,102,98 --color 120,70,70(複数指定可)
  • 実行すると,採取表(CSV)の雛形が標準出力に表示される.そのままエディタに貼って使える

採取手順 (Capture Steps)

1 色(1 枚)につき次を 1 回行う.

  1. 旧 exe を起動する
  2. ① 変換行列(.csv)読み込み の参照ボタンで変換行列 CSV を選ぶ
  3. ② 舌画像(.png)読み込み の参照ボタンで単色 PNG を 1 枚選ぶ
  4. 左の画像表示エリアの中央付近を左クリックする(1 点だけ)
    • 「現在のクリック ●」が 1 つ点灯すれば OK
    • 画像の端から 15 px 以上内側をクリックする(端では ROI がはみ出して旧 exe が落ちる)
    • 誤ってクリックした場合は右クリックで取り消してから,読み込みからやり直す (※ 旧実装は右クリックしてもクリック数の内部カウントが戻らない. クリックし直したら一度 exe を再起動するか「診断続行」でリセットするのが安全)
  5. ④ 舌色診断ボタン をクリックする
  6. メイン画面の右下に表示される次の 8 つの値を読み取り,採取表に記入する
    • 上から 紫 xx%・暗赤 xx%・紅 xx%・淡紅 xx%・淡白 xx%
    • その下に L* xx・a* xx・b* xx
    • いずれも整数表示(旧実装の書式が %3.0lf のため.小数は表示されない)
  7. 同時に開く結果画面を見て,赤い帯の 「Diagnosis failed / Please try again.」が出ているかを記録する
    • 出ていれば failed 列に yes,出ていなければ no
  8. 結果画面を閉じ,診断続行 ボタンを押す
    • 「同じ変換行列を使用するか」に はい と答えると,変換行列を選び直さずに次の画像へ進める
  9. 次の色の画像を ② から読み込み,同じ手順を繰り返す

採取すべきケース (Cases to Capture)

scripts/generate_regression_images.py の既定 12 色がそのまま以下をカバーする. 最低でも「代表色 5 点 + 境界値 2 点 + 域外 2 点」を採取する.

種類色(R,G,B)意図
代表156,102,98基準色(旧実装コメントの平均 BGR 由来)
代表180,120,115やや明るい舌色
代表205,145,140淡い舌色(淡紅・淡白寄り)
代表140,85,85やや暗い舌色
代表115,62,68暗い舌色(暗赤・紫寄り)
代表170,92,112赤紫寄り
代表196,74,74鮮やかな紅寄り
代表150,110,130青み寄り
境界255,255,255明るさの上限
境界0,0,0XYZ が 0 にクリップされる(L* = -16 になる想定)
失敗255,0,0学習データ域外(「Diagnosis failed」が出るか確認する)
失敗0,0,255学習データ域外

※ 実際の舌画像で «上位 2 色が入れ替わる境目» に近い色が分かっている場合は, その前後の色も追加すると回帰テストの価値が上がる.

採取表の記入 (Recording)

生成スクリプトが出力した雛形を使い,2 つの CSV を作る. 列名・列の意味・許容誤差は tests/fixtures/regression/README.md が正.

tests/fixtures/regression/rgb_to_lab.csv

matrix,r,g,b,l_star,a_star,b_star,note
translateMatrix.csv,156,102,98,55,22,7,基準色

tests/fixtures/regression/rgb_to_scores.csv

matrix,r,g,b,purple,dark_red,crimson,pink,pale,failed,note
translateMatrix.csv,156,102,98,16,61,11,5,0,no,基準色

記入のルール.

  • 数値は画面表示のまま(整数)書く.四捨五入や桁の追加をしない
  • 負の値(a* や b*)はマイナス記号を付けて書く
  • matrix 列には使った変換行列 CSV のファイル名を書く
  • 使った変換行列 CSV 自体を tests/fixtures/regression/matrices/ にコピーする(必須)
  • 文字コードは UTF-8(Excel で保存する場合は「CSV UTF-8」を選ぶ)
  • # で始まる行はコメントとして無視される(採取日・環境のメモに使ってよい)

照合の実行 (Run the Regression Test)

CSV を置いたら,リポジトリ直下で次を実行する(ENV_04).

uv run pytest tests/test_regression.py -vv
  • CSV が無い間は skip(理由に本手順書のパスが表示される)
  • CSV を置くと 1 行 = 1 テストケースとして実行される
  • 許容誤差(README と同じ)
    • L*a*b*: 絶対誤差 0.51 以内(旧 exe が整数しか表示しないため)
    • 5 色スコア(%): 完全一致
    • 診断失敗の有無: 完全一致

不一致だったときの扱い (When Results Differ)

新実装(プロダクションコード)をその場で直さない.次の順に切り分けて記録する.

  1. 採取ミスの確認: 変換行列は同じか,クリックは 1 点か,画像を取り違えていないか
  2. 差の大きさを確認: L*a*b* が 1 未満のずれなら表示丸めの範囲内の可能性がある
  3. 原因の記録: どの入力で・どの値が・どれだけずれたかを PROGRESS.md に追記する
  4. 仕様への反映: 旧実装の挙動が SPEC_02 の記述と異なると分かった場合は SPEC_02 を更新してから実装を直す (PLAN_02 ステップ 5 の完了条件は「全ペアで結果一致(不一致時は原因を特定し記録)」)

精度を上げたい場合 (Higher Precision, Optional)

画面表示は整数までなので,L*a*b* の照合はどうしても ±0.5 の幅を持つ. より厳密に照合したい場合は,旧実装を Visual Studio で Debug ビルドして次を採取する.

  • CalcLab() の直後に TRACE("L=%.6f a=%.6f b=%.6f\n", m_tongueL, m_tonguea, m_tongueb); を追加し, 出力ウィンドウの値を rgb_to_lab.csv に書く(この場合は小数のまま記入してよい. テストの許容誤差 0.51 のままでも通るが,より厳しい照合が必要なら tests/test_regression.py の LAB_DISPLAY_TOLERANCE を下げる)
  • 同様に m_tongueL/a/b に任意の値を代入してから CalcSVM() を呼ぶ改造版を作れば, 「Lab → スコア」の組(README の ③ lab_to_scores.csv)も採取できる

※ 旧実装の改造は参照専用の org/ を書き換えない(Git 管理外・原本保持). コピーを別フォルダに作って行うこと.