coverage-strategist について
ビジネスリスクと投入対効果に基づいてテスト範囲を計画する、チーム向けのテスト戦略スキルです。重要な経路や層別の目標、テスト対象外を定め、100%のカバレッジを追う方針ではありません。
主な機能
- 01重要な業務経路の特定
- 02層別カバレッジ目標の設定
- 03影響とリスクに基づく優先順位付け
- 04テスト対象外の明確化
- 05テスト投資対効果の評価
- 06チームレビュー指針の作成
活用シーン
- 01認証や決済フローのテスト計画
- 02複雑な業務ロジックのテスト選定
- 03プロジェクトのカバレッジ基準設定
- 04コード変更のテスト範囲レビュー
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ patricio0312rev/ skills --skill coverage-strategistインストール後、Claude Code で/coverage-strategistを入力して読み込まれたか確認します。
詳細
カバレッジ戦略
実用的で、ROI を重視したテストカバレッジ戦略を定義します。
カバレッジの基本方針
目標:最小限のテストで最大限の信頼性を得る
原則:カバレッジ 100%は目標ではありません。重要なものをテストします。
重要なパスの特定
// Critical paths that MUST be tested
const criticalPaths = {
authentication: {
priority: "P0",
coverage: "100%",
paths: [
"User login flow",
"User registration",
"Password reset",
"Token refresh",
"Session management",
],
reasoning: "Security critical, impacts all users",
},
checkout: {
priority: "P0",
coverage: "100%",
paths: [
"Add to cart",
"Update cart",
"Apply coupon",
"Process payment",
"Order confirmation",
],
reasoning: "Revenue critical, business essential",
},
dataIntegrity: {
priority: "P0",
coverage: "100%",
paths: [
"User data CRUD",
"Order creation",
"Inventory updates",
"Database transactions",
],
reasoning: "Data corruption would be catastrophic",
},
};
// Important but not critical
const importantPaths = {
userProfile: {
priority: "P1",
coverage: "80%",
paths: ["Profile updates", "Avatar upload", "Preferences"],
reasoning: "Important UX, but not business critical",
},
search: {
priority: "P1",
coverage: "70%",
paths: ["Product search", "Filters", "Sorting"],
reasoning: "Enhances experience, not essential",
},
};
レイヤー別の目標
# Coverage Targets by Layer
## Business Logic / Core Functions: 90-100%
**Why**: High ROI - complex logic, many edge cases
**What to test**:
- Calculations
- Validations
- State machines
- Algorithms
- Data transformations
## API Endpoints: 80-90%
**Why**: Critical integration points
**What to test**:
- Happy paths
- Error cases
- Validation
- Authentication
- Authorization
## Database Layer: 70-80%
**Why**: Data integrity matters
**What to test**:
- CRUD operations
- Transactions
- Constraints
- Migrations
## UI Components: 50-70%
**Why**: Lower ROI - visual changes, less critical
**What to test**:
- User interactions
- State changes
- Error states
- Critical flows only
## Utils/Helpers: 80-90%
**Why**: Reused everywhere, high impact
**What to test**:
- All public functions
- Edge cases
- Error handling
「テストしないもの」リスト
// Explicit list of what NOT to test
const dontTestThese = {
externalLibraries: {
examples: ["React internals", "Next.js router", "Lodash functions"],
reasoning: "Already tested by library authors",
},
trivialCode: {
examples: [
"Simple getters/setters",
"Constants",
"Type definitions",
"Pass-through functions",
],
reasoning: "No logic to test, waste of time",
},
presentationalComponents: {
examples: ["Simple buttons", "Icons", "Layout wrappers"],
reasoning: "Visual regression testing more appropriate",
},
configurationFiles: {
examples: ["webpack.config.js", "next.config.js"],
reasoning: "Configuration, not logic",
},
mockData: {
examples: ["Fixtures", "Test data", "Storybook stories"],
reasoning: "Not production code",
},
};
// Example: Don't test trivial code
// ❌ Don't test this
class User {
constructor(private name: string) {}
getName() {
return this.name;
} // Trivial getter
}
// ✅ But DO test this
class User {
constructor(private name: string) {}
getDisplayName() {
// Business logic
return this.name
.split(" ")
.map((n) => n.charAt(0).toUpperCase() + n.slice(1))
.join(" ");
}
}
テスト優先度マトリクス
interface TestPriority {
feature: string;
businessImpact: "high" | "medium" | "low";
complexity: "high" | "medium" | "low";
changeFrequency: "high" | "medium" | "low";
priority: "P0" | "P1" | "P2" | "P3";
targetCoverage: string;
}
const testPriorities: TestPriority[] = [
{
feature: "Payment processing",
businessImpact: "high",
complexity: "high",
changeFrequency: "low",
priority: "P0",
targetCoverage: "100%",
},
{
feature: "User authentication",
businessImpact: "high",
complexity: "medium",
changeFrequency: "low",
priority: "P0",
targetCoverage: "100%",
},
{
feature: "Product search",
businessImpact: "medium",
complexity: "medium",
changeFrequency: "medium",
priority: "P1",
targetCoverage: "80%",
},
{
feature: "UI themes",
businessImpact: "low",
complexity: "low",
changeFrequency: "high",
priority: "P3",
targetCoverage: "30%",
},
];
// Priority calculation
function calculatePriority(
businessImpact: number, // 1-10
complexity: number, // 1-10
changeFrequency: number // 1-10
): number {
return businessImpact * 0.5 + complexity * 0.3 + changeFrequency * 0.2;
}
カバレッジの設定
// jest.config.js
module.exports = {
collectCoverageFrom: [
"src/**/*.{ts,tsx}",
"!src/**/*.d.ts",
"!src/**/*.stories.tsx", // Don't count stories
"!src/mocks/**", // Don't count mocks
"!src/**/__tests__/**", // Don't count tests
],
coverageThresholds: {
global: {
statements: 70,
branches: 65,
functions: 70,
lines: 70,
},
// Critical paths: 90%+
"./src/services/payment/**/*.ts": {
statements: 90,
branches: 85,
functions: 90,
lines: 90,
},
"./src/services/auth/**/*.ts": {
statements: 90,
branches: 85,
functions: 90,
lines: 90,
},
// Utils: 80%+
"./src/utils/**/*.ts": {
statements: 80,
branches: 75,
functions: 80,
lines: 80,
},
// UI components: 50%+ (lower bar)
"./src/components/**/*.tsx": {
statements: 50,
branches: 45,
functions: 50,
lines: 50,
},
},
};
テスト投資の ROI
// Calculate ROI of testing
interface TestROI {
feature: string;
testingCost: number; // hours
bugPreventionValue: number; // estimated $ saved
roi: number; // ratio
}
const testROI: TestROI[] = [
{
feature: "Payment processing",
testingCost: 40, // hours
bugPreventionValue: 50000, // Could lose $50k revenue
roi: 1250, // $1,250 per hour invested
},
{
feature: "Authentication",
testingCost: 20,
bugPreventionValue: 10000, // Security breach cost
roi: 500,
},
{
feature: "Theme switcher",
testingCost: 5,
bugPreventionValue: 100, // Minor UX issue
roi: 20,
},
];
// Focus on high ROI tests
const sortedByROI = testROI.sort((a, b) => b.roi - a.roi);
実用的なテスト戦略
# Testing Strategy Document
## Principles
1. **Business value first**: Test what breaks the business
2. **Edge cases over happy path**: Happy path is obvious
3. **Integration over unit**: Test how pieces work together
4. **Critical flows end-to-end**: User journeys matter most
## Test Types Distribution
- 70% Unit tests (fast, isolated)
- 20% Integration tests (API + DB)
- 10% E2E tests (critical flows only)
## Coverage Goals
- Overall: 70% (pragmatic goal)
- Critical business logic: 90%+
- API endpoints: 80%+
- UI components: 50%+ (user interactions only)
## What NOT to Test
- Third-party libraries
- Trivial getters/setters
- Pure presentational components
- Configuration files
- Mock data and fixtures
## Review Criteria
Before writing a test, ask:
1. What bug would this test prevent?
2. How likely is that bug?
3. How costly would that bug be?
4. Is this already covered by integration tests?
If ROI is low, skip the test.
チームのガイドライン
// Code review checklist for test coverage
const reviewChecklist = {
criticalPath: {
question: "Does this change affect a critical path?",
ifYes: "MUST have comprehensive tests (90%+)",
},
businessLogic: {
question: "Is this complex business logic?",
ifYes: "MUST have unit tests with edge cases",
},
apiEndpoint: {
question: "Is this a new API endpoint?",
ifYes: "MUST have integration tests",
},
uiComponent: {
question: "Is this a UI component?",
ifYes: "Optional - test interactions only",
},
bugFix: {
question: "Is this a bug fix?",
ifYes: "MUST have regression test",
},
};
ベストプラクティス
- リスクに注目する:問題が起こりうる箇所をテストします
- 効果は逓減する:カバレッジ 100%の ROI は低くなります
- ユニットテストより統合テスト:実装ではなく、振る舞いをテストします
- 重要なパスを優先する:決済、認証、データの整合性
- 「テストしないもの」を明確にする:意図的にテストを省略します
- 定期的に見直す:目標を四半期ごとに調整します
- バグを測定する:テストが実際の問題を検出しているかを追跡します
出力チェックリスト
- 重要なパスを特定した
- レイヤー別の目標を定義した
- 「テストしないもの」リストを作成した
- 優先度マトリクスを作成した
- カバレッジのしきい値を設定した
- ROI 分析を実施した
- テスト戦略を文書化した
- チームのガイドラインを定義した
コメント
Markdown 対応