| name | experience-checklist |
| description | 仕様の構造から機械的に導くのではなく、経験・過去の欠陥をチェックリストに外部化して消し込むブラックボックス技法群。 test-catalog の手法カタログの一部。チェックリストベーステスト(Checklist-based Testing、満たすべき確認事項を体系的に消し込む)、 エラー推測(Error Guessing、空・null・巨大値・特殊文字・重複・並行など壊れそうな入力を経験と直感で狙い撃つ) を検証したい、または割り当てたいときに使う。通常は test-catalog スキルの索引経由で 手法が選定された後にこのスキルを直接参照する。
|
| disable-model-invocation | true |
ブラックボックス設計技法: 経験・チェックリストベース(経験をリストに外部化して消し込む)
仕様の構造から機械的に導くのではなく、テスト担当者の経験・直感・過去の欠陥から欠陥を狙う非形式的な技法のうち、経験を確認項目リストに外部化し、全項目を消し込む形にするもの(チェックリストベーステスト、エラー推測)を扱う。
乱数と即興で壊すもの(ランダムファジング、探索的テスト、アドホックテスト)は experience-exploratory.md を参照。
業務フロー(ユースケース、シナリオ)とフォーマット文法(構文テスト)を起点にするものは experience-scenario.md を参照。
体系的(仕様ベース)な技法のうち入力空間の分割(同値分割、境界値、デシジョンテーブル)は blackbox-partition.md を、履歴と状態は blackbox-state.md を、組合せの縮約のうち論理ベース(原因結果グラフ、クラシフィケーションツリー)は blackbox-cause-effect.md を、因子被覆(ペアワイズ、直交表、T-way)は blackbox-covering.md を参照。
これらは体系的技法の網を補う仕上げであり、単独で網羅性を主張しない。
見つけた欠陥は体系的技法へ書き戻して資産化(回帰テスト化)する。
目次
チェックリストベーステスト(Checklist-based Testing)
概要
過去の経験・ドメイン知識・法規制から作った確認項目リストに基づき、リストの各項目を体系的に消し込むテスト。
エラー推測が「壊しそうな入力」を狙うのに対し、こちらは「満たすべき確認事項」を網羅する点が違う(壊す起点 vs 満たす起点)。
目的/いつ使う
繰り返し発生する既知の要求(a11y チェックリスト、リリース前チェックリスト、業種特有の規制要件、コードレビュー観点)を、
案件ごとに考え直さず体系的にこなしたいとき。
チェックリストは他の技法(同値分割、境界値)の代替ではなく、技法を選び忘れないための索引として使う。
項目が形骸化(意味を考えず埋めるだけ)しないよう、各項目に「何を確認したら合格か」を明文化する。
TypeScript example
リリース前チェックリストを配列化し、各項目の合否を機械的に検証できるものはテストへ、できないものは人手確認欄として残す。
import { describe, it, expect } from "vitest";
import { getBuildInfo } from "./build-info";
describe("リリース前チェックリスト(機械検証可能な項目)", () => {
it("CL-01: バージョン番号が package.json と一致する", () => {
expect(getBuildInfo().version).toBe(require("../package.json").version);
});
it("CL-02: ソースマップが本番バンドルに含まれない", () => {
expect(getBuildInfo().hasSourceMap).toBe(false);
});
});
落とし穴
- リストを埋めることが目的化し、各項目の「なぜ必要か」を考えずにチェックだけ付ける(形骸化)。
- リストが古いまま更新されず、廃止済み要件や新規リスクが反映されない。
- 機械検証できる項目とできない項目(デザインレビュー等)を混ぜたまま自動化しようとして頓挫する。
遂行手順(着手→完了)
- 既存チェックリストを集める:ドメイン標準(WCAG、OWASP等)、社内規約、過去の欠陥から作った独自リストを集約する。出典を明記する。
- 各項目を機械検証可能/人手判断必須に仕分ける:機械検証できる項目(バージョン整合、必須ファイル存在、a11y ルール等)はテストコード化する。人手判断が要る項目(デザインの妥当性等)はチェックリスト文書側に残し、無理に自動化しない。
- 機械検証項目をテストへ落とす:各項目に
CL-ID を振り、対応するテストを1本ずつ書く。
- リストを定期的に見直す:新しい既知欠陥・規制変更が出たら項目を追加する。使われなくなった項目は削除理由を残して落とす。
完了チェック(もれ確認)
- 全項目に出典があるか:各
CL-ID に「なぜこの項目が要るか」の根拠(規格名、過去の欠陥番号)が書かれているか。
- 機械検証項目が全てテスト化されたか:
CL-ID とテスト名を grep で逆引き突合する。
- 形骸化していないか:チェックだけ付けて中身を確認していない項目が無いか、レビューで抜き取り確認する。
「網羅」の扱い(リストの網羅であって仕様の網羅ではない)
- なぜ全体網羅を主張しないか:チェックリストはそのリストが尽くす範囲でしか網羅しない。リスト自体の漏れは別の技法(同値分割・境界値等)で埋める必要がある。
- 停止規範:リストの全項目が消化された時点で、そのリストに関しては完了。リストの更新は継続的に行う。
- 体系的技法への昇格:チェックリストで見つかった欠陥パターンは、可能なら同値分割・境界値の代表値として体系的技法へ書き戻す。
エラー推測(Error Guessing)
概要
テスト担当者の経験と直感から、欠陥が潜みそうな入力(空、null、ゼロ、巨大値、特殊文字、重複、並行)を狙い撃ちする。
目的/いつ使う
体系的技法の網を補う仕上げとして、既知の障害パターンや過去のバグ傾向を当て込むとき。
チェックリスト化すると属人性を下げられる。
体系的設計の代わりにこれだけで済ませてはいけない(網羅性を保証しない)。
TypeScript example
典型的な「壊しに行く」入力をチェックリスト由来の配列にして文字列処理 slugify へ叩き込む。
import { describe, it, expect } from "vitest";
import { slugify } from "./slug";
describe("slugify: error guessing", () => {
const nasty = [
{ input: "", desc: "empty" },
{ input: " ", desc: "whitespace only" },
{ input: "a".repeat(10_000), desc: "very long" },
{ input: "héllo/wörld?", desc: "non-ascii & reserved" },
{ input: "../../etc", desc: "path traversal-ish" },
] as const;
it.each(nasty)("handles $desc without crashing", ({ input }) => {
expect(() => slugify(input)).not.toThrow();
});
});
落とし穴
- 当てずっぽうに依存し再現性が低い。見つけたパターンは必ずチェックリストへ昇格させ資産化する。
- これを主軸にすると網羅性が証明できない。同値分割や境界値の補完として位置づける。
遂行手順(着手→完了)
エラー推測の本体は「頭の中の勘」を「逆引きできるチェックリスト」へ外部化し、全項目をケースへ落としきることだ。即興で叩いて終わりにしない。次の順で進める。
- 障害源を3系統から集める:(a) この対象/類似機能の過去バグ(issue, バグ票, ポストモーテム,
git log --grep=fix)、(b) 汎用の壊しパターン(空 / null・undefined / 0・負数 / 巨大値・桁あふれ / 空白のみ・前後空白 / 特殊文字・制御文字・絵文字・サロゲートペア / 非ASCII・正規化(NFC/NFD)/ 重複・順序入替 / path traversal・インジェクション片 / 並行・再入)、(c) この対象固有の勘所(扱う型・境界・外部依存から「ここは雑に見える」を1人ブレストで挙げる)。
- チェックリストへ採番して書き出す:各項目を
EG-01 から連番で1行立てる(入力 / 狙う欠陥 / 出典(過去バグ番号 or パターン名))。頭の中に置かない。過剰採取は安全、漏れは危険。迷ったら載せる。
- 各項目に oracle(期待)を1つ決める:その入力で何が「正しい」か。多くは「クラッシュしない」「特定の例外型で弾く」「サニタイズして通す」のどれか。oracle を決められない項目は、それ自体が仕様の曖昧さ(別途確認に回す)。
- チェックリストをケースへ写す:
it.each の配列に EG-ID を desc として埋め、1項目1ケースで叩く。複数の壊しを1ケースに混ぜない(どの項目で落ちたか切り分け不能になる)。
- 落ちた入力を回帰へ昇格する:壊れた入力は同値分割・境界値・構文テスト・回帰へ書き戻し(
blackbox-partition.md)、チェックリストの出典欄に「→回帰化済み」と記す。
完了チェック(もれ確認)
- 全 EG-ID がケースへ落ちたか(逆引き):チェックリストの各
EG-ID を、テストファイル中の desc に grep で1行ずつ突き合わせる。grep -o 'EG-[0-9]*' <test> | sort -u の件数とチェックリストの項目数が一致する。差があればケース未作成の項目が残っている。
- 3系統すべてから採れたか:過去バグ由来・汎用パターン由来・対象固有の3系統が、それぞれ最低1項目はチェックリストに載っているか。1系統でも0件なら採取漏れ(特に過去バグの確認を飛ばしがち)。
- oracle 無しの項目が無いか:各項目に「何が正しいか」が書いてあるか。
not.toThrow だけで埋めて意味的正しさを見落としていないか(意味は PBT/メタモルフィック oracle-relational.md の領分だが、明らかな期待値があるなら固定する)。
- 混在ケースが無いか:1ケースで複数の壊しを同時に入れていないか(切り分け不能を防ぐ)。
- 落ちた入力が資産化されたか:見つけた欠陥がチェックリスト上で「回帰化済み」になっているか。なっていなければ次の変更で再発する。
「網羅」の扱い(網羅は主張しない)
- なぜ網羅を定義できないか:経験や直感由来で狙うため、入力空間を形式的に覆えない。
- 停止規範(どこまでやれば十分とするか):既知障害パターンのチェックリスト(空、null、0、巨大値、特殊文字、重複、並行 等)を全項目当て込むまで。新たな壊しパターンが思いつかなくなり、過去バグ由来の項目も尽きたら打ち切る。
- 体系的技法への昇格:見つけた壊れる入力は同値分割、境界値、回帰テストへ書き戻し、網羅資産化する。
関連 reference