fast-check
fast-checkは、想定外のバグを効率的に見つけるため、大量のランダムなテストデータを自動生成し、TypeScriptで記述されたコードの品質を向上させるproperty-based testingを支援するSkill。
📜 元の英語説明(参考)
Find edge-case bugs with property-based testing using fast-check — generate thousands of random inputs automatically. Use when someone asks to "find edge cases", "fast-check", "property-based testing", "fuzz testing in TypeScript", "generate random test data", "QuickCheck for JavaScript", or "test with random inputs". Covers property definitions, arbitraries, shrinking, model-based testing, and integration with Vitest/Jest.
🇯🇵 日本人クリエイター向け解説
fast-checkは、想定外のバグを効率的に見つけるため、大量のランダムなテストデータを自動生成し、TypeScriptで記述されたコードの品質を向上させるproperty-based testingを支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o fast-check.zip https://jpskill.com/download/14888.zip && unzip -o fast-check.zip && rm fast-check.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14888.zip -OutFile "$d\fast-check.zip"; Expand-Archive "$d\fast-check.zip" -DestinationPath $d -Force; ri "$d\fast-check.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
fast-check.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
fast-checkフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
fast-check
概要
fast-check はプロパティベースのテストフレームワークです。具体的なテストケースを書く代わりに、常に成り立つべきプロパティを記述すると、fast-check はそれらを破ろうと何千ものランダムな入力を生成します。失敗する入力を見つけると、自動的にそれを最小限の再現ケースに縮小します。空文字列、負の数、Unicode、巨大な配列、境界値など、テストすることを考えもしなかったエッジケースを捕捉します。
どのような時に使うか
- 多数の入力が考えられる関数 (パーサー、バリデーター、シリアライザー)
- ビジネスロジックにおけるエッジケースの発見 (価格設定、権限、日付処理)
- シリアライズ/デシリアライズのラウンドトリップテスト (encode → decode = original)
- 数学的特性の検証 (可換性、結合性)
- 手書きのテストケースを生成されたテストケースで置き換える
手順
セットアップ
npm install -D fast-check
基本的なプロパティ
// math.test.ts — 数学関数のためのプロパティベーステスト
import fc from "fast-check";
import { describe, it, expect } from "vitest";
describe("sort", () => {
it("should produce an array of same length", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
return sorted.length === arr.length;
})
);
});
it("should produce ordered output", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
for (let i = 1; i < sorted.length; i++) {
expect(sorted[i]).toBeGreaterThanOrEqual(sorted[i - 1]);
}
})
);
});
it("should contain the same elements", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
expect(sorted).toEqual(expect.arrayContaining(arr));
expect(arr).toEqual(expect.arrayContaining(sorted));
})
);
});
});
ラウンドトリップテスト
// serialization.test.ts — エンコード/デコードのラウンドトリップ
import fc from "fast-check";
import { encode, decode } from "./my-codec";
it("decode(encode(x)) === x for any string", () => {
fc.assert(
fc.property(fc.string(), (original) => {
const encoded = encode(original);
const decoded = decode(encoded);
expect(decoded).toEqual(original);
})
);
});
it("JSON roundtrip preserves data", () => {
fc.assert(
fc.property(fc.jsonValue(), (value) => {
const json = JSON.stringify(value);
const parsed = JSON.parse(json);
expect(parsed).toEqual(value);
})
);
});
カスタム Arbitraries
// business.test.ts — ドメインオブジェクトのためのカスタムデータジェネレーター
import fc from "fast-check";
// Generate realistic user objects
const userArbitrary = fc.record({
id: fc.uuid(),
name: fc.string({ minLength: 1, maxLength: 100 }),
email: fc.emailAddress(),
age: fc.integer({ min: 13, max: 120 }),
role: fc.constantFrom("admin", "user", "viewer"),
createdAt: fc.date({ min: new Date("2020-01-01"), max: new Date() }),
});
// Generate realistic money amounts
const moneyArbitrary = fc.record({
amount: fc.integer({ min: 0, max: 1_000_000 }), // Cents
currency: fc.constantFrom("USD", "EUR", "GBP"),
});
it("discount should never result in negative price", () => {
fc.assert(
fc.property(
moneyArbitrary,
fc.integer({ min: 0, max: 100 }), // Discount percentage
(price, discountPercent) => {
const discounted = applyDiscount(price, discountPercent);
expect(discounted.amount).toBeGreaterThanOrEqual(0);
}
)
);
});
it("total should equal sum of line items", () => {
fc.assert(
fc.property(
fc.array(moneyArbitrary, { minLength: 1, maxLength: 50 }),
(items) => {
const total = calculateTotal(items);
const expected = items.reduce((sum, item) => sum + item.amount, 0);
expect(total).toBe(expected);
}
)
);
});
Shrinking (自動的な最小再現)
// プロパティが失敗した場合、fast-check は自動的に最小の失敗する入力を探します
it("handles edge cases in URL parsing", () => {
fc.assert(
fc.property(fc.webUrl(), (url) => {
const parsed = parseUrl(url);
expect(parsed.protocol).toBeTruthy();
// If this fails on a complex URL, fast-check shrinks it to
// the simplest URL that still fails, e.g., "http://a"
})
);
});
例
例 1: エッジケースに対するパーサーのテスト
ユーザープロンプト: 「私の CSV パーサーは奇妙な入力で壊れます。すべてのエッジケースを見つけてください。」
エージェントは "parse(serialize(data)) === data" のようなプロパティを記述し、エッジケース (フィールド内のカンマ、改行、空のセル、Unicode) を含むランダムな CSV データを生成し、失敗する入力を特定します。
例 2: 価格設定ロジックの検証
ユーザープロンプト: 「割引計算をテストして、負の価格や丸め誤差が発生しないことを確認してください。」
エージェントはランダムな価格、割引率、およびクーポン組み合わせを生成し、不変条件 (非負、正しい丸め、順序は関係ない) を検証します。
ガイドライン
- 例ではなく、プロパティで考える — 「ソートされた出力は順序付けられている」ではなく「sort([3,1,2]) = [1,2,3]」
- ラウンドトリップは最も簡単なプロパティ —
decode(encode(x)) === x fc.assertはデフォルトで 100 回のイテレーションを実行する —{ numRuns: 1000 }で増やす- Shrinking は自動 — 失敗した入力は最も単純なケースに最小化される
- 組み込みの arbitraries はほとんどのニーズをカバーする —
string,integer,array,record,date,uuid,emailAddress - enums には
constantFrom—fc.constantFrom("a", "b", "c") - 事前条件には
fc.pre(condition)— 条件を満たさない入力をスキップする - 例ベースのテストと組み合わせる — プロパティは未知のものを見つけ、例は既知のものを検証する
- 再現性のためのシード — 失敗した実行はシードを出力する。同じシードで再実行して再現する
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
fast-check
Overview
fast-check is a property-based testing framework — instead of writing specific test cases, you describe properties that should always hold, and fast-check generates thousands of random inputs to try to break them. When it finds a failing input, it automatically shrinks it to the minimal reproducing case. Catches edge cases you'd never think to test: empty strings, negative numbers, Unicode, massive arrays, boundary values.
When to Use
- Functions with many possible inputs (parsers, validators, serializers)
- Finding edge cases in business logic (pricing, permissions, date handling)
- Testing serialization/deserialization roundtrips (encode → decode = original)
- Verifying mathematical properties (commutativity, associativity)
- Replacing hand-written test cases with generated ones
Instructions
Setup
npm install -D fast-check
Basic Properties
// math.test.ts — Property-based testing for math functions
import fc from "fast-check";
import { describe, it, expect } from "vitest";
describe("sort", () => {
it("should produce an array of same length", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
return sorted.length === arr.length;
})
);
});
it("should produce ordered output", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
for (let i = 1; i < sorted.length; i++) {
expect(sorted[i]).toBeGreaterThanOrEqual(sorted[i - 1]);
}
})
);
});
it("should contain the same elements", () => {
fc.assert(
fc.property(fc.array(fc.integer()), (arr) => {
const sorted = [...arr].sort((a, b) => a - b);
expect(sorted).toEqual(expect.arrayContaining(arr));
expect(arr).toEqual(expect.arrayContaining(sorted));
})
);
});
});
Roundtrip Testing
// serialization.test.ts — Encode/decode roundtrips
import fc from "fast-check";
import { encode, decode } from "./my-codec";
it("decode(encode(x)) === x for any string", () => {
fc.assert(
fc.property(fc.string(), (original) => {
const encoded = encode(original);
const decoded = decode(encoded);
expect(decoded).toEqual(original);
})
);
});
it("JSON roundtrip preserves data", () => {
fc.assert(
fc.property(fc.jsonValue(), (value) => {
const json = JSON.stringify(value);
const parsed = JSON.parse(json);
expect(parsed).toEqual(value);
})
);
});
Custom Arbitraries
// business.test.ts — Custom data generators for domain objects
import fc from "fast-check";
// Generate realistic user objects
const userArbitrary = fc.record({
id: fc.uuid(),
name: fc.string({ minLength: 1, maxLength: 100 }),
email: fc.emailAddress(),
age: fc.integer({ min: 13, max: 120 }),
role: fc.constantFrom("admin", "user", "viewer"),
createdAt: fc.date({ min: new Date("2020-01-01"), max: new Date() }),
});
// Generate realistic money amounts
const moneyArbitrary = fc.record({
amount: fc.integer({ min: 0, max: 1_000_000 }), // Cents
currency: fc.constantFrom("USD", "EUR", "GBP"),
});
it("discount should never result in negative price", () => {
fc.assert(
fc.property(
moneyArbitrary,
fc.integer({ min: 0, max: 100 }), // Discount percentage
(price, discountPercent) => {
const discounted = applyDiscount(price, discountPercent);
expect(discounted.amount).toBeGreaterThanOrEqual(0);
}
)
);
});
it("total should equal sum of line items", () => {
fc.assert(
fc.property(
fc.array(moneyArbitrary, { minLength: 1, maxLength: 50 }),
(items) => {
const total = calculateTotal(items);
const expected = items.reduce((sum, item) => sum + item.amount, 0);
expect(total).toBe(expected);
}
)
);
});
Shrinking (Automatic Minimal Reproduction)
// When a property fails, fast-check automatically finds the SMALLEST failing input
it("handles edge cases in URL parsing", () => {
fc.assert(
fc.property(fc.webUrl(), (url) => {
const parsed = parseUrl(url);
expect(parsed.protocol).toBeTruthy();
// If this fails on a complex URL, fast-check shrinks it to
// the simplest URL that still fails, e.g., "http://a"
})
);
});
Examples
Example 1: Test a parser for edge cases
User prompt: "My CSV parser breaks on weird inputs. Find all the edge cases."
The agent will write properties like "parse(serialize(data)) === data", generate random CSV data with edge cases (commas in fields, newlines, empty cells, Unicode), and identify failing inputs.
Example 2: Verify pricing logic
User prompt: "Test our discount calculation to make sure it never produces negative prices or rounding errors."
The agent will generate random prices, discount percentages, and coupon combinations, then verify invariants (non-negative, correct rounding, order doesn't matter).
Guidelines
- Think in properties, not examples — "sorted output is ordered" not "sort([3,1,2]) = [1,2,3]"
- Roundtrip is the easiest property —
decode(encode(x)) === x fc.assertruns 100 iterations by default — increase with{ numRuns: 1000 }- Shrinking is automatic — failed inputs are minimized to the simplest case
- Built-in arbitraries cover most needs —
string,integer,array,record,date,uuid,emailAddress constantFromfor enums —fc.constantFrom("a", "b", "c")fc.pre(condition)for preconditions — skip inputs that don't meet criteria- Combine with example-based tests — properties find unknowns, examples verify knowns
- Seed for reproducibility — failed runs print a seed; re-run with same seed to reproduce