| name | levels-operational |
| description | テストの粒度選択のうち、システム全体を外から見る運用確認の層(スモークテスト、 サニティテスト、回帰テスト)を扱う。 test-catalog の手法カタログの一部。デプロイ直後の致命傷即検知、小さな修正後の 変更箇所の狭い確認、過去バグの再発防止と継続的な退行防止を検証したい、または 割り当てたいときに使う。通常は test-catalog スキルの索引経由で手法が選定された 後にこのスキルを直接参照する。
|
| disable-model-invocation | true |
テストレベル(システム全体・運用確認)
システム全体を外から見るレベルのうち、デプロイ前後の足切りや退行防止に使う「運用確認」の層を集める。
ビルドやデプロイの直後、バグ修正の直後、変更を取り込むたびに、本物の環境に近い構成で「壊れていないか」を素早く確かめる。
いずれも網羅は目的でなく、致命傷の即検知(スモーク)・変更箇所の確認(サニティ)・退行の継続防止(回帰)に役割を絞る。
各レベルは「概要」「目的/いつ使う」「example」「落とし穴」「網羅の定義」「遂行手順(着手→完了)」「完了チェック(もれ確認)」で示す。
遂行手順は「何を最小確認とするか → どう書くか → 合否を判定する」を番号付きの手順に落とし、完了チェックは漏れ(項目過多・スキップ黙殺など)を実際に検出する確認項目を並べる。
目次
スモークテスト
概要
ビルドやデプロイ直後に、最重要機能がそもそも起動して動作するかを最短で確認する。
目的/いつ使う
詳細テストを回す価値があるかの足切りに使う。デプロイ後のヘルスチェックにも使う。
網羅的な検証には使わない(目的は「致命傷の即検知」だけ)。
TypeScript example
import { describe, it, expect } from "vitest";
const BASE = process.env.SYSTEM_URL ?? "http://localhost:8080";
describe("smoke", () => {
it("ヘルスチェックが 200 を返す", async () => {
const res = await fetch(`${BASE}/health`);
expect(res.status).toBe(200);
});
});
落とし穴
あれもこれもと項目を足すとスモークでなくなり、足切りの速さという利点を失う。
逆に health だけ見て主要機能の 1 経路を入れないと、起動はするが壊れている状態を通す。
網羅の定義
このレベルは「最重要機能の起動と生存のみ」を対象に取る層。
網羅ではなく致命傷の即検知が目的なので、対象は意図的に最小に絞る。
- 網羅基準(いつ網羅完了とみなすか):起動の生死を示す health と、最重要機能の主要1経路を数秒で確認できたとき。これ以上は基準に足さない。
- 網羅手順(基準を満たすケース集合の作り方):1. 落ちたら全体が無価値になる機能を1つだけ選ぶ。2. その起動確認と health を最小集合にする。3. 詳細な検証は足切り通過後の下層テストへ回す。
- 達成チェック(漏れの検出):health だけで主要機能の1経路が抜けていないか。逆に項目を足しすぎて足切りの速さ(数秒)を失っていないか。
遂行手順(着手→完了)
スモークの本体は「落ちたら以降のテストすべてが無意味になる致命点だけを、数秒で確認する最小集合に絞る」ことだ。何を最小確認とするかの線引きが甘いと、足切りの速さという唯一の利点を失う。次の順で進める。
- 致命点を1つに絞る:システムが提供する機能のうち「これが死んでいたら他を試す価値が無い」ものを1つだけ選ぶ(例:認証なしでは全機能が無意味なら認証エンドポイント)。複数挙がっても、最小確認は1致命点 + health に留める。
- 生存確認の最小経路を決める:health(プロセスの起動)に加え、致命機能の主要1経路(例:ログイン要求が想定ステータスを返す)を最短で踏む経路を決める。深い検証はここに入れない。
- 数秒で終わる集合として書く:example のように外部から触り、起動の生死だけを判定する。実行時間を計測し、目標(数秒)を超えるなら項目を削る。
- 合否基準を二値で定める:全項目が緑なら「詳細テストへ進んでよい」、1つでも赤なら「即停止しデプロイ/詳細実行を中止」と、足切りの判断を機械的に決める。曖昧な「だいたい通った」を残さない。
完了チェック(もれ確認)
- 最小集合に health だけでなく主要1経路があるか:health が 200 を返すだけで、致命機能の1経路が抜けていないか。抜けていれば「起動はするが壊れている」状態を通す。
- 項目を足しすぎていないか:スモークの実行時間が数秒を超えていないか。超えていれば網羅的検証が紛れているので下層へ送り返す。
- 合否が二値で運用されているか:赤のときデプロイ/詳細実行が実際に止まる仕組み(CI のゲート)になっているか。赤を見ても進めるなら足切りとして機能していない。
サニティテスト
概要
特定の修正や小変更が意図どおり効いているかを、狭い範囲で素早く確認する。
目的/いつ使う
バグ修正後や小さな変更後に、その箇所と周辺だけを軽く確かめたいときに使う。
全体の健全性確認には使わない(それはスモークや回帰の役割)。
TypeScript example
import { describe, it, expect } from "vitest";
import { parseAmount } from "./parse-amount";
describe("sanity: parseAmount 全角対応", () => {
it("全角数字を半角として解釈する", () => {
expect(parseAmount("123")).toBe(123);
});
});
落とし穴
スモークとの線引きが曖昧になりやすい。スモークは「広く浅く起動確認」、サニティは「狭く深く変更確認」と役割で分ける。
サニティで通ったから全体も大丈夫、と早合点して回帰を省くと別の箇所の退行を見逃す。
網羅の定義
このレベルは「直近の修正点とその周辺のみ」を対象に取る層。
広く浅くではなく、変更箇所を狭く深く確認することに限定する。
- 網羅基準(いつ網羅完了とみなすか):直前の変更が意図どおり効いていることと、その変更が直接触れる周辺を確認できたとき。全体の健全性確認は基準に含めない。
- 網羅手順(基準を満たすケース集合の作り方):1. 今回の修正点を特定する。2. その修正点の期待挙動を直接確認するケースを書く。3. 修正が触れた周辺の代表箇所だけ軽く確認し、無関係箇所は対象外にする。
- 達成チェック(漏れの検出):スモーク(広く浅く起動確認)と役割を混同していないか。サニティ通過を全体 OK と早合点して回帰を省いていないか。
遂行手順(着手→完了)
サニティの本体は「今回の変更点を特定し、その意図どおりの挙動と、変更が直接触れた周辺だけを狭く深く確認する」ことだ。最小確認の範囲は「変更が触れた所」であって全体ではない。次の順で進める。
- 変更点を特定する:diff を見て、今回の修正で挙動が変わるべき箇所を1つ(または1組)に確定する(例:全角数字の許容を追加した
parseAmount)。何を直したかが曖昧なら、まずそこを言語化する。
- 意図挙動を直接確認するケースを書く:修正の狙いそのものを最短で踏むケースを書く(example の全角入力など)。これが最小確認の中核。
- 直接触れた周辺だけ軽く確認する:変更が同じ関数/モジュールで隣接する代表箇所(例:半角入力が従来どおり通るか)を1〜2件だけ確認する。無関係箇所は対象外にする。
- 合否を判定し、全体保証と切り離す:中核ケースと周辺ケースが緑なら「変更は意図どおり」とだけ結論づける。全体が壊れていないことの保証はここではしない(回帰の役割)。
完了チェック(もれ確認)
- 変更の意図が直接確認されているか:書いたケースが、今回の修正の狙い(手順1)をそのまま踏んでいるか。修正点とずれたケースしか無ければ意図を確かめていない。
- スモークと役割を混同していないか:サニティが「広く浅い起動確認」に膨らんでいないか。範囲が変更箇所を超えて全体に及んでいれば、それはスモーク/回帰の領分。
- 全体 OK と早合点していないか:サニティ緑をもって回帰を省いていないか。変更が遠くの箇所を壊す退行はここでは捕まらないので、回帰(回帰テスト)を別途回す前提になっているか。
回帰テスト
概要
変更によって既存の動作が壊れていないかを、過去に通ったテスト群を再実行して確認する。
目的/いつ使う
コード変更、依存更新、リファクタのたびに、CI で継続的に走らせる。
新機能そのものの検証には使わない(回帰は「壊していないこと」の保証)。
TypeScript example
import { describe, it, expect } from "vitest";
import { renderInvoice } from "./invoice";
describe("回帰", () => {
it("#482: 数量 0 の行で NaN を出さない", () => {
const out = renderInvoice([{ name: "X", qty: 0, price: 100 }]);
expect(out).not.toContain("NaN");
});
});
落とし穴
落ちたテストを直さず skip で黙らせると、回帰スイートは飾りになる。
過去バグの再現テストを残さないと、同じ欠陥が何度でも戻ってくる。修正のたびに 1 本固定する。
網羅の定義
このレベルは「過去に通った振る舞い全体と、再発防止すべき既知バグ」を網羅対象に取る層。
新機能の検証ではなく、壊していないことの継続的な保証に集中する。
- 網羅基準(いつ網羅完了とみなすか):過去に通ったテスト群が CI で継続実行され、かつ修正した既知バグごとに再現テストが1本ずつ恒久固定されているとき。
- 網羅手順(基準を満たすケース集合の作り方):1. 既存のテスト群を CI の継続実行対象にする。2. バグ修正のたびに、その欠陥を再現する最小テストを1本追加し由来(番号)を残す。3. 過去バグの再現テストを消さずに蓄積する。
- 達成チェック(漏れの検出):落ちたテストを skip で黙らせて飾りにしていないか。修正のたびに回帰を1本足しているか。過去バグの再現テストが欠けていないか。
遂行手順(着手→完了)
回帰の本体は「バグ修正のたびに再現テストを1本ずつ追加し、過去分を消さずに蓄積し、CI で継続実行して退行を捕まえ続ける」ことだ。一回ぽっきりでなく、修正のたびに積み増す運用が核心。次の順で進める。
- 既存テスト群を継続実行対象にする:過去に通っているテストを CI の毎回実行に組み込む。手で気が向いたときだけ回す運用にしない(回さなければ退行は見えない)。
- バグ修正ごとに再現テストを先に書く:バグを直す前に、その欠陥を最小入力で再現して赤になるテストを1本書く(Red を確認 → 修正で Green)。先に赤を見ることで、テストが本当にその欠陥を捕まえることを保証する。
- 由来を残して恒久固定する:テスト名にバグ番号や Issue 由来を入れ(example の
#482 など)、なぜ存在するかを追える形で残す。以後このテストは消さず蓄積する。
- 緑を保ったまま積み増す:新しい変更で既存の回帰テストが落ちたら、退行を疑い原因を直す(テスト側を緩めて通すのは退行の隠蔽)。修正が正当なら期待値を更新し、由来をコメントに残す。
- skip/only の混入を定期的に検出する:落ちたテストを skip で黙らせていないか、CI のゲートで機械的に検出する仕組みを置く(手順は完了チェック参照)。
完了チェック(もれ確認)
- 修正ごとに1本足したか:今回のバグ修正に対応する再現テストが追加され、修正前に赤・修正後に緑だったことを確認したか。再現テストの無い修正は同じ欠陥が再発し得る。
- skip 黙殺を検出できているか:
grep -rn "\.skip\|\.only\|\.todo\|xit(\|xdescribe(" <testdir> または lint ルール(例 no-disabled-tests)で、黙らされたテストが残っていないか機械的に確認する。手目視だけだと見落とす。skip が残るなら、それは守られていない退行ケース。
- 過去バグの再現テストが消えていないか:由来(番号)付きの回帰テストが削除・コメントアウトされていないか。
git log で回帰テストの削除がないか追える状態か。
- CI で実際に走っているか:回帰スイートが毎回の CI に含まれ、赤でマージがブロックされるか。ローカルだけで走るなら退行は素通りする。
配分と階層化は別ファイルへ
レベルを選んだあとの配分(ピラミッド/トロフィー)と階層化(関心事による分割)は strategy-allocation.md を読む(levels.md 末尾と同じ)。
広域確認の層(システム/E2E/UAT)は levels-system.md を読む。