/note/tech

複雑なドメインの知識をテストケースとして資産化する

要約:

■ 1. 報酬算定エンジンと開発上の不安

  • 報酬算定エンジンの役割:
    • 介護報酬算定ロジックを組み込んだ仕組み
    • 事業者が提供した介護サービスの内容をもとに、介護保険制度のルールに沿って金額を計算する
  • 正確性の継続的な担保への不安:
    • 介護報酬算定には多くの条件や例外があり、制度の理解そのものが簡単ではない
    • 制度を正しく理解し、それを計算処理として実装する必要がある
    • さらにその計算結果が正しいことを確認する必要がある
  • デグレードへの懸念:
    • 少しずつ機能を追加する過程では既存コードの修正も発生する
    • 以前実装した計算が意図せず壊れることが最も怖い
    • 検知が遅れると原因調査や修正に時間がかかり、新規実装に使える時間が減る

■ 2. QA観点の確認を自動化する理由

  • QA観点の確認の定義:
    • 内部でどの処理が呼ばれたかではなく、この条件を入力したとき期待通りの算定結果が得られるかを確かめること
  • 手動テストの限界:
    • 人手がかかるため実行できるタイミングが限られる
    • 大きな機能を実装したあとにまとめて確認する形になりがち
    • 問題が見つかった時点で変更範囲が広く、どの変更が原因かの特定に時間がかかる
  • 小さく実装して都度実行する状態:
    • 早い段階で不具合を見つけられる状態にしたい
    • 大きな節目だけに限定せず、日々の開発の中で繰り返し実行できるようにする

■ 3. 算定結果のテストという選択

  • 入力から出力までを検証対象化:
    • 個々の計算ロジックが正しいだけでは不十分
    • それらが組み合わさった結果として期待通りの出力を得られることが重要
    • 内部のクラスや関数を直接呼び出す形にはしない
  • 呼称の方針:
    • 技術的には報酬算定エンジンへの入力から出力までを確認する結合テスト
    • テストの分類よりも何を確認するテストなのかが伝わるよう算定結果のテストと呼ぶ
  • リファクタリングのための足場:
    • 新規開発の最中であり、新たな事実に応じて設計や実装を大きく見直したくなる場面がある
    • 内部実装の細部に強く依存したテストだけでは大きなリファクタリングを進めづらい
    • 単体テストも重要だが、内部構造を見直すたびに多くのテストを書き換える状態は避けたい
    • 外側の振る舞いを守れば、内部実装を変更しても振る舞いが変わっていないことを確認できる

■ 4. 専門知識をテストケース化する流れ

  • 関係者全員での制度理解:
    • テストケース自体はQA担当者が作成する
    • QA担当者だけが制度を読み解くのではなく、エンジニア、QA、POなど関係者全員での理解から始める
  • 制度の整理と図示:
    • 制度の文章をそのまま実装やテストに落とし込むことは難しい
    • 制度の内容を読み解き、計算処理としてどのように表現できるかを整理する
    • 処理の流れや条件分岐を図に起こし、チーム全体で認識を合わせる
  • 共通理解からの分岐:
    • 同じ理解をもとにエンジニアが実装を進め、QA担当者がテストケースを作成する
    • エンジニアとQAが別々の前提で作業してしまうことを避けられる

■ 5. QA担当者が扱いやすい形式

  • コードで書かせない判断:
    • QA担当者は制度や業務観点に詳しい一方、技術スタックに精通しているとは限らない
    • コードで書く形にすると、追加や修正のたびにエンジニアの手を介する必要が出る
  • Googleスプレッドシートの採用:
    • QA担当者が普段の業務の延長で扱いやすい
    • 内部実装やテストフレームワークを詳しく知らなくてもテストケースを作成できる
  • 実務様式を参考にした設計:
    • サービス提供票別表やその他様式2などの様式を参考にして形式を設計した
    • 専門知識を持つ人がテストケースを直感的に理解できるようにするため
    • 機械的に扱いやすい形式だけを優先すると、作成する人にとって読みにくくなる
  • 入口の単純さの優先:
    • 作成されたテストケースはCSVとしてエクスポートし、実行時に読み込んで入力に変換する
    • 変換処理自体は地道な実装になったが、QA担当者が扱う入口をシンプルに保つことを優先した

■ 6. CIによる実行の仕組み化

  • 手動エクスポートの回避:
    • 毎回手作業でCSVにエクスポートする運用は実行前のひと手間が増える
    • エクスポート漏れや古いCSVを使ってしまう可能性もある
  • GitHub Actions上のワークフロー:
    • 対象のスプレッドシートをCSVとしてエクスポートする
    • そのCSVをGitにコミットしたうえで算定結果のテストを実行する
  • workflow_dispatchによる手動実行:
    • QA担当者自身が任意のタイミングで実行できる
    • テストケースを作成したタイミングを起点に、最新のテストケースで検証できる
    • QA観点の確認をエンジニアだけに閉じない形にできた

■ 7. 導入して良かったこと

  • 知見の資産化:
    • QA担当者が作成したテストケースを蓄積している
    • 現在の仕様だけでなく、過去の制度に基づく計算もテストとして残せる
  • 過去の計算ルールの保護:
    • 報酬改定によって計算ルールが変わる
    • 過去に提供した介護サービス分は改定前のルールに基づく計算が必要になる場面がある
    • 法改正で現在の計算ロジックが変わっても、過去分の計算が壊れていないかを繰り返し確認できる
  • 報酬改定時の安心感:
    • 報酬改定では新しいルールの追加だけでなく既存の処理にも手を入れる必要がある
    • 修正対象ではない計算まで意図せず変えてしまうことが怖い
    • 変更による想定外の影響を早い段階で検知できる
    • 修正内容が誤っていれば過去のテストが落ちるため、本番環境で不具合を出す前に気づける
  • 小さな検知の積み重ね:
    • 大きな障害を防いだという派手なエピソードがあるわけではない
    • 大きな問題が起きていないこと自体が、この仕組みが効果を発揮していることの表れかもしれない

■ 8. 難しかったこと

  • 古い形式のテストケースへの対応:
    • 開発が進むにつれ機能が増え、入力値や出力値も増えていく
    • 過去のテストケースはその時点の入力値・出力値を前提にしている
    • 変換処理側に形式ごとの差分を吸収する分岐を持たせて対応している
  • コード管理の煩雑化:
    • 入力値や出力値が増えるたびに変換処理側で考慮することが増える
    • テストケースを資産として残すほど、過去のフォーマットとの互換性の扱いが課題になる
  • それでも上回る価値:
    • QA担当者の知見を長く使える資産として残せる
    • 報酬改定やリファクタリング時に想定外の変更を検知できる

■ 9. まとめ

  • 取り組みの要点:
    • 専門知識を持つ人がテストケースを作りやすい入口を用意する
    • その知見を繰り返し実行できる形にする
  • 仕組みの全体像:
    • Googleスプレッドシートで作成したテストケースをCSVとして取り込む
    • 報酬算定エンジンへの入力に変換して算定結果のテストとして実行する
    • CIによってQA担当者を起点に最新のテストケースで検証できるようにする
  • 複雑なドメイン開発における重要性:
    • エンジニアだけで正しさを判断しきれない場面がある
    • 専門知識を持つ人の知見をテストに落とし込み、継続的に実行できる形にすることが重要