| name | levels-system |
| description | テストの粒度選択のうち、システム全体を外から見る広域確認の層(システムテスト、 E2Eテスト、受け入れテスト/UAT)を扱う。 test-catalog の手法カタログの一部。複数サービス・DB・設定が組み合わさった本番に 近い構成での機能/性能/セキュリティ要件の検証、実ブラウザでの主要ユーザーフロー の通し確認、ビジネス側と合意した受け入れ基準へのトレーサビリティを検証したい、 または割り当てたいときに使う。通常は test-catalog スキルの索引経由で手法が選定 された後にこのスキルを直接参照する。
|
| disable-model-invocation | true |
テストレベル(システム全体・広域確認)
システム全体を外から見るレベルのうち、利用者や発注者の視点で振る舞いを確かめる「広域確認」の層を集める。
複数のサービスや UI、DB、設定が組み合わさった状態で、本物の環境に近い構成で代表シナリオを通す。
いずれも個別ロジックのデバッグには向かず、要件・利用フロー・受け入れ基準を代表シナリオで踏むことに集中する。
各レベルは「概要」「目的/いつ使う」「example」「落とし穴」「網羅の定義」「遂行手順(着手→完了)」「完了チェック(もれ確認)」で示す。
遂行手順は「要件/基準/フローを洗い出す → 代表を選ぶ → 完了を判定する」を番号付きの手順に落とし、完了チェックは漏れを実際に検出する確認項目を並べる。
目次
システムテスト
概要
統合された全体を本番に近い構成で立ち上げ、外部から見た機能、性能、セキュリティを検証する。
目的/いつ使う
複数サービス、DB、設定が組み合わさった状態で要件を満たすかを、リリース前に確かめたいときに使う。
個別ロジックのデバッグには向かない(遅く、失敗箇所の切り分けが難しい)。
TypeScript example
import { describe, it, expect } from "vitest";
const BASE = process.env.SYSTEM_URL ?? "http://localhost:8080";
describe("注文フロー(システム)", () => {
it("注文を作成すると 201 と ID を返す", async () => {
const res = await fetch(`${BASE}/orders`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ sku: "A1", qty: 1 }),
});
expect(res.status).toBe(201);
const body = await res.json();
expect(body.id).toBeTypeOf("string");
});
});
落とし穴
環境差(設定、データ、依存サービスのバージョン)で落ちると、原因究明にコードより時間を食う。
あらゆる分岐をここで網羅しようとすると遅さで破綻する。網羅は下層に任せ、ここは代表経路に絞る。
網羅の定義
このレベルは「統合された全体での要件(機能、性能、セキュリティ)」を網羅対象に取る層。
分岐の網羅は下層に委ね、ここはエンドツーエンドの代表経路に絞る。
- 網羅基準(いつ網羅完了とみなすか):主要な機能要件と非機能要件(性能、セキュリティ)ごとに、本番に近い構成での代表シナリオを1本ずつ通したとき。分岐の全網羅は基準にしない。
- 網羅手順(基準を満たすケース集合の作り方):1. リリース判定に必要な要件を機能、性能、セキュリティで列挙する。2. 各要件を代表する end-to-end シナリオを1つ選ぶ。3. 同じ要件の細かいバリエーションは下層(単体、結合)へ送り返す。
- 達成チェック(漏れの検出):網羅を欲張ってシナリオを増やしすぎ、遅さと不安定さで破綻していないか。下層で取れる網羅をこの層に持ち込んでいないか。
遂行手順(着手→完了)
システムテストの本体は「リリース判定に要る要件を機能と非機能の両面で漏れなく洗い出し、各要件カテゴリに代表シナリオを1本ずつ当てる」ことだ。要件の洗い出しが空疎だと、緑でも「何を確かめたか」が言えない。次の順で進める。
- 要件の出どころを集める:仕様書・受け入れ基準・SLA/SLO・セキュリティ要件票・過去障害の再発防止項目を1か所に集める。出どころを欠くと、頭の中の要件だけを確認して本物の要件を取りこぼす。
- 機能要件を列挙する:「誰が・何を・どうなる」の単位で、システムが外から提供する振る舞いを箇条書きにする(例:注文を作成できる/在庫切れは拒否する/領収書を発行する)。1 振る舞い1行で、UI 画面や API エンドポイントを総当たりして取りこぼしを防ぐ。
- 非機能要件をカテゴリで列挙する:最低でも 性能(応答時間・スループット)・セキュリティ(認証/認可・入力検証・機密の非漏洩)・可用性/回復性(障害時の挙動)・データ整合性(永続化の一貫性) の各カテゴリに、本番で守るべき具体値や条件を1つ以上書き出す。カテゴリを空欄のまま残さない(空欄=そのカテゴリを誰も確かめない)。
- 各要件に代表シナリオを1本割り当てる:要件1件につき、本番に近い構成で外から踏める end-to-end シナリオを1つ選ぶ。同じ要件の細かいバリエーション(入力の同値分割・境界値)はここで足さず、下層(単体・結合)へ送り返す印を付ける。
- 代表シナリオを本番に近い構成で書く:example のように内部実装へ触れず、HTTP など外部インターフェース越しに結果だけを判定する。性能は閾値アサート、セキュリティは未認証アクセスの拒否など、カテゴリの性質を観察可能な形で確かめる。
完了チェック(もれ確認)
- 全要件カテゴリに代表が当たったか:手順3で挙げた非機能カテゴリ(性能/セキュリティ/可用性/データ整合性)それぞれに、対応する代表シナリオが最低1本あるか。1つでも代表ゼロのカテゴリがあれば、そのカテゴリは未検証(リリース判定の根拠が欠ける)。
- 機能要件に未対応が無いか:手順2の機能要件リストと、書いたシナリオの対応表を作り、テストの無い要件行が残っていないか。残っていれば洗い出しと実装の間に漏れがある。
- 要件の出どころと一致するか:シナリオが手順1で集めた仕様/SLA/セキュリティ要件票の具体値と食い違っていないか(例:SLO が p95 300ms なのにアサートが緩い)。食い違えば「要件を確かめた」が嘘になる。
- 下層の網羅を持ち込んでいないか:シナリオ本数が要件カテゴリ数に対して膨らみすぎていないか。入力の同値分割・境界値がこの層に紛れていれば、遅さと不安定さの原因なので下層へ送り返す。
E2E テスト(Playwright 例)
概要
実ブラウザを使い、ユーザーの操作と同じ経路で UI から裏側まで通しで検証する。
目的/いつ使う
ログインから購入完了までの主要な利用シナリオが壊れていないことを保証したいときに使う。
細かい表示条件やバリデーションの全パターンには使わない(遅く脆い。単体/コンポーネントへ寄せる)。
TypeScript example
import { test, expect } from "@playwright/test";
test("ログインしてダッシュボードに到達する", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("メールアドレス").fill("alice@example.com");
await page.getByLabel("パスワード").fill("secret");
await page.getByRole("button", { name: "ログイン" }).click();
await expect(page).toHaveURL(/\/dashboard/);
await expect(page.getByRole("heading", { name: "ダッシュボード" })).toBeVisible();
});
落とし穴
waitForTimeout の固定待ちや CSS セレクタ依存は、flaky と保守コストの主因。
ロールやラベルで要素を取り、自動待機(expect(...).toBeVisible())に任せる。
シナリオを増やしすぎると CI が肥大する。E2E はピラミッドの頂点、本数を絞る。
網羅の定義
このレベルは「主要な利用シナリオの最小集合」を網羅対象に取る層。
ピラミッドの頂点として本数を絞り、重要フローだけを通す。
- 網羅基準(いつ網羅完了とみなすか):事業上クリティカルな利用フロー(ログイン〜購入完了など)を、実ブラウザで通しに1本ずつ持ったとき。細かいバリデーションの網羅は基準に含めない。
- 網羅手順(基準を満たすケース集合の作り方):1. 壊れたら売上や信頼に直結する主要フローを列挙する。2. 各フローを最短の通しシナリオ1本にする。3. 入力バリエーションや表示条件の網羅は単体/コンポーネントへ送り返す。
- 達成チェック(漏れの検出):重要フローに抜けが無いか、かつ重要でないフローを積みすぎていないか。flaky 対策(ロールやラベルでの要素取得、固定待ちでなく自動待機)ができているか。
遂行手順(着手→完了)
E2E の本体は「主要ユーザーフローを列挙し、事業インパクト順に最小本数だけ通しシナリオへ落とす」ことだ。フローの列挙が曖昧だと、重要フローを取りこぼしたまま枝葉の表示確認を積み上げてしまう。次の順で進める。
- ユーザーフローを列挙する:システムが提供する「目的を達成する一連の操作」を、ペルソナ × ゴール単位で書き出す(例:新規ユーザーが登録〜初回ログイン/既存ユーザーがログイン〜購入完了/管理者が返金処理)。画面遷移図やサイトマップを総当たりして取りこぼしを防ぐ。
- 事業インパクトで順位を付ける:各フローに「壊れたら売上・信頼・法令順守にどれだけ響くか」で優先度を付ける。最上位だけが E2E の対象候補になる。
- 最小本数を選定する:優先度上位から、1 フロー=1 通しシナリオで選ぶ。同じ画面を通る別フローは代表1本に統合し、本数を絞る(E2E はピラミッドの頂点)。入力の同値分割・表示条件の網羅は対象にせず、単体/コンポーネントへ送り返す印を付ける。
- 各フローを最短の通しシナリオで書く:example のようにロール/ラベルで要素を取り、固定待ちでなく自動待機(
expect(...).toBeVisible())に任せる。フローの開始点から「ゴールに到達した観察可能な状態」までを1本で通す。
- 本数の上限を決め超えたら統合する:CI 時間の予算からフロー本数の上限を先に決め、超えたら優先度下位を下層へ落とすか代表へ統合する。
完了チェック(もれ確認)
- 最上位フローに抜けが無いか:手順2で最上位に置いたフローすべてに、対応する通しシナリオが1本あるか。最上位なのにシナリオ無しのフローがあれば、最も壊れてはいけない経路が無防備。
- 最小本数に収まっているか:シナリオ本数が手順5で決めた上限を超えていないか。超過分に入力バリエーション・表示条件など下層で取れるものが紛れていないか(紛れていれば送り返す)。
- flaky 対策ができているか:
waitForTimeout の固定待ちや CSS セレクタ依存が残っていないか(grep -n "waitForTimeout" <test> がヒットしないこと)。ロール/ラベル取得と自動待機に統一されているか。
- 観察可能な状態で判定しているか:各シナリオが URL・ロール・可視テキストなど利用者から見える状態を assert しているか。内部実装に依存した判定は脆さの証拠。
受け入れテスト(UAT)
概要
発注者やユーザー視点で、要件と受け入れ基準を満たすかを判定する。自動化する場合は Gherkin など業務語彙で書く。
目的/いつ使う
「作ったもの」ではなく「望まれたもの」になっているかを、ビジネス側と合意した基準で確認したいときに使う。
技術的な内部品質の検証には使わない(それは開発側のテストの責務)。
TypeScript example
import { describe, it, expect } from "vitest";
import { checkout } from "./checkout";
describe("受け入れ: クーポン適用", () => {
it("有効なクーポンを使うと合計が割引額だけ下がる", () => {
const before = checkout({ items: [{ price: 1000 }] });
const after = checkout({ items: [{ price: 1000 }], coupon: "OFF200" });
expect(before.total - after.total).toBe(200);
});
});
落とし穴
受け入れ基準が曖昧なまま自動化すると、何を合意したのか後から誰も言えなくなる。
開発者だけで書いた UAT は「自分が作った仕様の再確認」になりがち。基準はビジネス側と先に固める。
網羅の定義
このレベルは「ビジネスと合意した受け入れ基準の全項目」を網羅対象に取る層。
技術的な内部品質ではなく、合意済みの基準そのものを網羅する。
- 網羅基準(いつ網羅完了とみなすか):合意した受け入れ基準の各項目に、業務語彙で書いたテストが1対1で対応し、全項目が緑になったとき。
- 網羅手順(基準を満たすケース集合の作り方):1. ビジネス側と合意した受け入れ基準を項目として列挙する。2. 各項目を業務の言葉でテスト名にし、外から見た結果だけを判定するテストにする。3. 基準に対応しないテストを足さない(技術検証は開発側テストへ)。
- 達成チェック(漏れの検出):受け入れ基準がビジネス側と先に固定されているか(後付けだと何を合意したか曖昧になる)。基準の項目に未対応のものが残っていないか。
遂行手順(着手→完了)
UAT の本体は「合意済みの受け入れ基準を1つずつ取得し、基準とテストを1対1で紐づけ、全基準がテストで覆われたことをトレーサビリティで示す」ことだ。基準とテストの対応が見えないと、何を合意し何を確かめたかが後から誰も言えなくなる。次の順で進める。
- 受け入れ基準を取得する:ユーザーストーリーの Acceptance Criteria、Definition of Done、契約・要件定義書からビジネス側と合意済みの基準を集める。合意前のものは対象にしない(後付け基準は「自分が作った仕様の再確認」に堕ちる)。基準が曖昧なら、この段でビジネス側と Given/When/Then の形に具体化してから進む。
- 基準に一意の ID を振る:各受け入れ基準へ
AC-注文-01 のような ID を付け、基準文を一覧化する。ID が無いと対応の取りようがない。
- トレーサビリティ表を作る:
基準ID | 基準文 | テスト名 | 状態(緑/赤/未着手) の表を用意し、基準を行として全部並べる。これがカバレッジの台帳になる。
- 基準1件にテスト1本を対応させる:各基準を業務語彙でテスト名にし(Gherkin なら1シナリオ)、外から見た結果だけを判定するテストを書く。書いたらトレーサビリティ表のその行にテスト名を記入する。1基準に複数観点があるなら、観点ごとに基準を分割してから1対1を保つ(1テストに複数基準を詰めない=どの基準が落ちたか不明になる)。
- 基準に無いテストを足さない:技術的内部品質の検証は開発側テストへ回し、UAT は基準の表に載る項目だけに保つ。
完了チェック(もれ確認)
- 全基準がテストに対応したか:トレーサビリティ表の「テスト名」列に空欄(未着手)が無いか。空欄=その合意基準は誰も確かめていない。基準の総数とテストの本数が一致するか(1対1)。
- テスト→基準の逆引きが成立するか:書いた各テストが表のいずれかの基準IDに紐づくか。どの基準にも紐づかないテストがあれば、合意外の検証が紛れている(技術検証なら開発側へ移す)。
- 基準が事前合意か:手順1の各基準が、実装より前にビジネス側と固定されたものか。実装後に都合よく書いた基準が混じっていないか(後付けは合意の証拠にならない)。
- 1テスト1基準が保たれているか:1本のテストに複数基準を詰め込んでいないか。詰め込みがあると、落ちたとき「どの合意が破れたか」が特定できない。
レベルを選んだあとの配分(ピラミッド/トロフィー)と階層化(関心事による分割)は strategy-allocation.md を読む(levels.md 末尾と同じ)。
運用確認の層(スモーク/サニティ/回帰)は levels-operational.md を読む。