Healthcare Eval Harness — 患者安全検証
医療アプリケーションのデプロイメント向け自動検証システム。単一のCRITICALな失敗がデプロイをブロックします。患者安全は絶対条件です。
注: 例ではJestを参照テストランナーとして使用しています。コマンドはご利用のフレームワーク(Vitest、pytest、PHPUnitなど)に合わせて調整してください。テストカテゴリと合格しきい値はフレームワークに依存しません。
使用すべきタイミング
- EMR/EHRアプリケーションのデプロイメント前
- CDSSロジック(薬物相互作用、用量バリデーション、スコアリング)を変更した後
- 患者データに触れるデータベーススキーマを変更した後
- 認証またはアクセス制御を変更した後
- 医療アプリケーションのCI/CDパイプライン設定時
- 臨床モジュールのマージ競合を解決した後
動作の仕組み
評価ハーネスは5つのテストカテゴリを順に実行します。最初の3つ(CDSS精度、PHI露出、データ整合性)はCRITICALゲートで、100%の合格率が必要です。1件の失敗でもデプロイをブロックします。残りの2つ(臨床ワークフロー、統合)はHIGHゲートで、95%以上の合格率が必要です。
各カテゴリはJestのテストパスパターンにマッピングされます。CIパイプラインはCRITICALゲートを--bail(最初の失敗で停止)で実行し、--coverage --coverageThresholdでカバレッジしきい値を適用します。
評価カテゴリ
1. CDSS精度(CRITICAL — 100%必須)
すべての臨床意思決定支援ロジックをテスト:薬物相互作用ペア(両方向)、用量バリデーションルール、公開仕様に対する臨床スコアリング、偽陰性なし、サイレント障害なし。
npx jest --testPathPattern='tests/cdss' --bail --ci --coverage
2. PHI露出(CRITICAL — 100%必須)
保護健康情報(PHI)の漏洩をテスト:APIエラーレスポンス、コンソール出力、URLパラメータ、ブラウザストレージ、施設間分離、未認証アクセス、サービスロールキーの欠如。
npx jest --testPathPattern='tests/security/phi' --bail --ci
3. データ整合性(CRITICAL — 100%必須)
臨床データの安全性をテスト:ロックされた診療記録、監査証跡エントリ、カスケード削除保護、同時編集処理、孤立レコードなし。
npx jest --testPathPattern='tests/data-integrity' --bail --ci
4. 臨床ワークフロー(HIGH — 95%以上必須)
エンドツーエンドのフローをテスト:診療記録ライフサイクル、テンプレートレンダリング、投薬セット、薬剤/診断検索、処方PDF、赤旗アラート。
tmp_json=$(mktemp)
npx jest --testPathPattern='tests/clinical' --ci --json --outputFile="$tmp_json" || true
total=$(jq '.numTotalTests // 0' "$tmp_json")
passed=$(jq '.numPassedTests // 0' "$tmp_json")
if [ "$total" -eq 0 ]; then
echo "No clinical tests found" >&2
exit 1
fi
rate=$(echo "scale=2; $passed * 100 / $total" | bc)
echo "Clinical pass rate: ${rate}% ($passed/$total)"
5. 統合コンプライアンス(HIGH — 95%以上必須)
外部システムをテスト:HL7メッセージ解析(v2.x)、FHIRバリデーション、ラボ結果マッピング、不正メッセージ処理。
tmp_json=$(mktemp)
npx jest --testPathPattern='tests/integration' --ci --json --outputFile="$tmp_json" || true
total=$(jq '.numTotalTests // 0' "$tmp_json")
passed=$(jq '.numPassedTests // 0' "$tmp_json")
if [ "$total" -eq 0 ]; then
echo "No integration tests found" >&2
exit 1
fi
rate=$(echo "scale=2; $passed * 100 / $total" | bc)
echo "Integration pass rate: ${rate}% ($passed/$total)"
合格/不合格マトリックス
| カテゴリ | しきい値 | 失敗時の動作 |
|---|---|---|
| CDSS精度 | 100% | デプロイをブロック |
| PHI露出 | 100% | デプロイをブロック |
| データ整合性 | 100% | デプロイをブロック |
| 臨床ワークフロー | 95%以上 | 警告、レビュー付きで許可 |
| 統合 | 95%以上 | 警告、レビュー付きで許可 |
CI/CD統合
name: Healthcare Safety Gate
on: [push, pull_request]
jobs:
safety-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
# CRITICALゲート — 100%必須、最初の失敗で停止
- name: CDSS Accuracy
run: npx jest --testPathPattern='tests/cdss' --bail --ci --coverage --coverageThreshold='{"global":{"branches":80,"functions":80,"lines":80}}'
- name: PHI Exposure Check
run: npx jest --testPathPattern='tests/security/phi' --bail --ci
- name: Data Integrity
run: npx jest --testPathPattern='tests/data-integrity' --bail --ci
# HIGHゲート — 95%以上必須、カスタムしきい値チェック
- name: Clinical Workflows
run: |
TMP_JSON=$(mktemp)
npx jest --testPathPattern='tests/clinical' --ci --json --outputFile="$TMP_JSON" || true
TOTAL=$(jq '.numTotalTests // 0' "$TMP_JSON")
PASSED=$(jq '.numPassedTests // 0' "$TMP_JSON")
if [ "$TOTAL" -eq 0 ]; then
echo "::error::No clinical tests found"; exit 1
fi
RATE=$(echo "scale=2; $PASSED * 100 / $TOTAL" | bc)
echo "Pass rate: ${RATE}% ($PASSED/$TOTAL)"
if (( $(echo "$RATE < 95" | bc -l) )); then
echo "::warning::Clinical pass rate ${RATE}% below 95%"
fi
- name: Integration Compliance
run: |
TMP_JSON=$(mktemp)
npx jest --testPathPattern='tests/integration' --ci --json --outputFile="$TMP_JSON" || true
TOTAL=$(jq '.numTotalTests // 0' "$TMP_JSON")
PASSED=$(jq '.numPassedTests // 0' "$TMP_JSON")
if [ "$TOTAL" -eq 0 ]; then
echo "::error::No integration tests found"; exit 1
fi
RATE=$(echo "scale=2; $PASSED * 100 / $TOTAL" | bc)
echo "Pass rate: ${RATE}% ($PASSED/$TOTAL)"
if (( $(echo "$RATE < 95" | bc -l) )); then
echo "::warning::Integration pass rate ${RATE}% below 95%"
fi
アンチパターン
- 「前回合格したから」という理由でCDSSテストをスキップする
- CRITICALのしきい値を100%未満に設定する
- CRITICALテストスイートで
--no-bailを使用する - 統合テストでCDSSエンジンをモックする(実際のロジックをテストする必要がある)
- 安全ゲートが赤のときにデプロイを許可する
- CDSSスイートで
--coverageなしでテストを実行する
例
例1: すべてのCRITICALゲートをローカルで実行
npx jest --testPathPattern='tests/cdss' --bail --ci --coverage && \
npx jest --testPathPattern='tests/security/phi' --bail --ci && \
npx jest --testPathPattern='tests/data-integrity' --bail --ci
例2: HIGHゲートの合格率を確認
tmp_json=$(mktemp)
npx jest --testPathPattern='tests/clinical' --ci --json --outputFile="$tmp_json" || true
jq '{
passed: (.numPassedTests // 0),
total: (.numTotalTests // 0),
rate: (if (.numTotalTests // 0) == 0 then 0 else ((.numPassedTests // 0) / (.numTotalTests // 1) * 100) end)
}' "$tmp_json"
# 期待値: { "passed": 21, "total": 22, "rate": 95.45 }
例3: 評価レポート
## Healthcare Eval: 2026-03-27 [commit abc1234]
### Patient Safety: PASS
| カテゴリ | テスト数 | 合格 | 失敗 | ステータス |
|----------|----------|------|------|------------|
| CDSS精度 | 39 | 39 | 0 | PASS |
| PHI露出 | 8 | 8 | 0 | PASS |
| データ整合性 | 12 | 12 | 0 | PASS |
| 臨床ワークフロー | 22 | 21 | 1 | 95.5% PASS |
| 統合 | 6 | 6 | 0 | PASS |
### カバレッジ: 84% (目標: 80%以上)
### 判定: デプロイ安全