test-specialist
JavaScriptおよびTypeScriptアプリケーションのテストケース作成、バグ修正、コード分析、テストカバレッジ改善が必要な際に使用するスキルです。ユニットテスト・統合テスト・E2Eテストの作成から、ランタイムエラー・ロジックバグ・パフォーマンス問題・セキュリティ脆弱性のデバッグ、体系的なコード解析まで幅広く対応します。
description の原文を見る
This skill should be used when writing test cases, fixing bugs, analyzing code for potential issues, or improving test coverage for JavaScript/TypeScript applications. Use this for unit tests, integration tests, end-to-end tests, debugging runtime errors, logic bugs, performance issues, security vulnerabilities, and systematic code analysis.
SKILL.md 本文
テストスペシャリスト
概要
JavaScript/TypeScript アプリケーションに対して体系的なテスト方法論とデバッグ技法を適用します。このスキルは包括的なテスト戦略、バグ分析フレームワーク、およびカバレッジギャップと未テストコードを特定するための自動化ツールを提供します。
コア機能
1. テストケースの作成
ユニット、インテグレーション、エンドツーエンドのシナリオをカバーする包括的なテストを作成します。
ユニットテストアプローチ
AAA パターン(Arrange-Act-Assert)を使用してテストを構造化します:
describe('ExpenseCalculator', () => {
describe('calculateTotal', () => {
test('sums expense amounts correctly', () => {
// Arrange
const expenses = [
{ amount: 100, category: 'food' },
{ amount: 50, category: 'transport' },
{ amount: 25, category: 'entertainment' }
];
// Act
const total = calculateTotal(expenses);
// Assert
expect(total).toBe(175);
});
test('handles empty expense list', () => {
expect(calculateTotal([])).toBe(0);
});
test('handles negative amounts', () => {
const expenses = [
{ amount: 100, category: 'food' },
{ amount: -50, category: 'refund' }
];
expect(calculateTotal(expenses)).toBe(50);
});
});
});
重要な原則:
- テストごとに1つの動作をテストする
- 正常系、エッジケース、エラー条件をカバーする
- シナリオを説明する説明的なテスト名を使用する
- テストは独立し、分離されている状態を保つ
インテグレーションテストアプローチ
データベース、API、およびサービスの相互作用を含む、コンポーネント間の連携をテストします:
describe('ExpenseAPI Integration', () => {
beforeAll(async () => {
await database.connect(TEST_DB_URL);
});
afterAll(async () => {
await database.disconnect();
});
beforeEach(async () => {
await database.clear();
await seedTestData();
});
test('POST /expenses creates expense and updates total', async () => {
const response = await request(app)
.post('/api/expenses')
.send({
amount: 50,
category: 'food',
description: 'Lunch'
})
.expect(201);
expect(response.body).toMatchObject({
id: expect.any(Number),
amount: 50,
category: 'food'
});
// Verify database state
const total = await getTotalExpenses();
expect(total).toBe(50);
});
});
エンドツーエンドテストアプローチ
Playwright または Cypress などのツールを使用して完全なユーザーワークフローをテストします:
test('user can track expense from start to finish', async ({ page }) => {
// Navigate to app
await page.goto('/');
// Add new expense
await page.click('[data-testid="add-expense-btn"]');
await page.fill('[data-testid="amount"]', '50.00');
await page.selectOption('[data-testid="category"]', 'food');
await page.fill('[data-testid="description"]', 'Lunch');
await page.click('[data-testid="submit"]');
// Verify expense appears in list
await expect(page.locator('[data-testid="expense-item"]')).toContainText('Lunch');
await expect(page.locator('[data-testid="total"]')).toContainText('$50.00');
});
2. 体系的なバグ分析
問題を特定して修正するために、構造化されたデバッグ方法論を適用します。
5ステップの分析プロセス
-
再現(Reproduction): バグを確実に再現する
- バグをトリガーするための正確なステップを文書化する
- 必要な環境/状態を特定する
- 期待される動作と実際の動作を記録する
-
分離(Isolation): 問題を絞り込む
- コードパスを通じて二分探索を実行する
- 最小限の再現ケースを作成する
- 無関係な依存関係を削除する
-
根本原因分析(Root Cause Analysis): 根底にある原因を特定する
- 実行フローをトレースする
- 仮定と前提条件を確認する
- 最近の変更を確認する(git blame)
-
修正実装(Fix Implementation): ソリューションを実装する
- 最初に失敗するテストを作成する(TDD)
- 修正を実装する
- テストが合格することを確認する
-
検証(Validation): 完全性を保証する
- フルテストスイートを実行する
- エッジケースをテストする
- リグレッションがないことを確認する
一般的なバグパターン
競合状態(Race Conditions):
// 並行操作をテストする
test('handles concurrent updates correctly', async () => {
const promises = Array.from({ length: 100 }, () =>
incrementExpenseCount()
);
await Promise.all(promises);
expect(getExpenseCount()).toBe(100);
});
Null/Undefined エラー:
// null 安全性をテストする
test.each([null, undefined, '', 0, false])
('handles invalid input: %p', (input) => {
expect(() => processExpense(input)).toThrow('Invalid expense');
});
オフバイワンエラー:
// 境界を明示的にテストする
describe('pagination', () => {
test('handles empty list', () => {
expect(paginate([], 1, 10)).toEqual([]);
});
test('handles single item', () => {
expect(paginate([item], 1, 10)).toEqual([item]);
});
test('handles last page with partial items', () => {
const items = Array.from({ length: 25 }, (_, i) => i);
expect(paginate(items, 3, 10)).toHaveLength(5);
});
});
3. 潜在的な問題の特定
バグになる前に問題を積極的に特定します。
セキュリティ脆弱性
一般的なセキュリティ問題をテストします:
describe('security', () => {
test('prevents SQL injection', async () => {
const malicious = "'; DROP TABLE expenses; --";
await expect(
searchExpenses(malicious)
).resolves.not.toThrow();
});
test('sanitizes XSS in descriptions', () => {
const xss = '<script>alert("xss")</script>';
const expense = createExpense({ description: xss });
expect(expense.description).not.toContain('<script>');
});
test('requires authentication for expense operations', async () => {
await request(app)
.post('/api/expenses')
.send({ amount: 50 })
.expect(401);
});
});
パフォーマンスの問題
パフォーマンスの問題をテストします:
test('processes large expense list efficiently', () => {
const largeList = Array.from({ length: 10000 }, (_, i) => ({
amount: i,
category: 'test'
}));
const start = performance.now();
const total = calculateTotal(largeList);
const duration = performance.now() - start;
expect(duration).toBeLessThan(100); // Should complete in <100ms
expect(total).toBe(49995000);
});
ロジックエラー
パラメータ化されたテストを使用してエッジケースを捕捉します:
test.each([
// [input, expected, description]
[[10, 20, 30], 60, 'normal positive values'],
[[0, 0, 0], 0, 'all zeros'],
[[-10, 20, -5], 5, 'mixed positive and negative'],
[[0.1, 0.2], 0.3, 'decimal precision'],
[[Number.MAX_SAFE_INTEGER], Number.MAX_SAFE_INTEGER, 'large numbers'],
])('calculateTotal(%p) = %p (%s)', (amounts, expected, description) => {
const expenses = amounts.map(amount => ({ amount, category: 'test' }));
expect(calculateTotal(expenses)).toBeCloseTo(expected);
});
4. テストカバレッジ分析
自動化されたツールを使用してテストカバレッジのギャップを特定します。
未テストコードの検出
提供されたスクリプトを実行して、テストのないソースファイルを特定します:
python3 scripts/find_untested_code.py src
スクリプトは以下を実行します:
- ソースディレクトリをスキャンしてすべてのコードファイルを特定する
- 対応するテストファイルがないファイルを特定する
- 未テストファイルをタイプ別に分類する(コンポーネント、サービス、ユーティリティなど)
- 最初にテストが必要なファイルに優先順位を付ける
解釈:
- API/サービス: 高優先度 - ビジネスロジックとデータ操作をテストする
- モデル: 高優先度 - データ検証と変換をテストする
- フック: 中優先度 - ステートフル動作をテストする
- コンポーネント: 中優先度 - 複雑な UI ロジックをテストする
- ユーティリティ: 低優先度 - 複雑な関数に必要に応じてテストする
カバレッジレポートの分析
カバレッジを生成した後、カバレッジ分析スクリプトを実行します:
# カバレッジを生成する(Jest の例)
npm test -- --coverage
# カバレッジギャップを分析する
python3 scripts/analyze_coverage.py coverage/coverage-final.json
スクリプトは以下を特定します:
- カバレッジ閾値を下回るファイル(デフォルト 80%)
- ステートメント、ブランチ、関数のカバレッジ率
- 改善の優先度ファイル
カバレッジ目標:
- 重大パス: 90% 以上のカバレッジ
- ビジネスロジック: 85% 以上のカバレッジ
- UI コンポーネント: 75% 以上のカバレッジ
- ユーティリティ: 70% 以上のカバレッジ
5. テストの保守と品質
テストが価値があり、保守可能なままであることを保証します。
テストコード品質の原則
DRY(Don't Repeat Yourself):
// 共通のセットアップを抽出する
function createTestExpense(overrides = {}) {
return {
amount: 50,
category: 'food',
description: 'Test expense',
date: new Date('2024-01-01'),
...overrides
};
}
test('filters by category', () => {
const expenses = [
createTestExpense({ category: 'food' }),
createTestExpense({ category: 'transport' }),
];
// ...
});
明確なテストデータ:
// 悪い例: マジックナンバー
expect(calculateDiscount(100, 0.15)).toBe(85);
// 良い例: 名前付き定数
const ORIGINAL_PRICE = 100;
const DISCOUNT_RATE = 0.15;
const EXPECTED_PRICE = 85;
expect(calculateDiscount(ORIGINAL_PRICE, DISCOUNT_RATE)).toBe(EXPECTED_PRICE);
テストの独立性を維持する:
// 悪い例: テストが実行順序に依存している
let sharedState;
test('test 1', () => {
sharedState = { value: 1 };
});
test('test 2', () => {
expect(sharedState.value).toBe(1); // Depends on test 1
});
// 良い例: 独立したテスト
test('test 1', () => {
const state = { value: 1 };
expect(state.value).toBe(1);
});
test('test 2', () => {
const state = { value: 1 };
expect(state.value).toBe(1);
});
ワークフロー決定ツリー
この決定ツリーに従ってテストアプローチを決定します:
-
新機能を追加していますか?
- はい → テストを最初に書く(TDD)
- 失敗するテストを書く
- 機能を実装する
- テストが合格することを確認する
- リファクタリングする
- いいえ → ステップ 2 に進む
- はい → テストを最初に書く(TDD)
-
バグを修正していますか?
- はい → バグ分析プロセスを適用する
- バグを再現する
- バグを示す失敗するテストを書く
- 実装を修正する
- テストが合格することを確認する
- いいえ → ステップ 3 に進む
- はい → バグ分析プロセスを適用する
-
テストカバレッジを改善していますか?
- はい → カバレッジツールを使用する
find_untested_code.pyを実行してギャップを特定する- カバレッジレポートで
analyze_coverage.pyを実行する - 重大パスに優先順位を付ける
- 未テストコードのテストを書く
- いいえ → ステップ 4 に進む
- はい → カバレッジツールを使用する
-
コード品質を分析していますか?
- はい → 体系的なレビュー
- セキュリティ脆弱性を確認する
- エッジケースとエラー処理をテストする
- パフォーマンス特性を確認する
- エラーハンドリングをレビューする
- はい → 体系的なレビュー
テストフレームワークとツール
推奨スタック
ユニット/インテグレーションテスト:
- Jest または Vitest(テストランナー用)
- Testing Library(React コンポーネント用)
- Supertest(API テスト用)
- MSW(Mock Service Worker)(API モック用)
E2E テスト:
- Playwright または Cypress
- ページオブジェクトモデルパターン
カバレッジ:
- Istanbul(Jest/Vitest に組み込まれている)
- JSON 形式のカバレッジレポート
テストの実行
# すべてのテストを実行する
npm test
# カバレッジ付きで実行する
npm test -- --coverage
# 特定のテストファイルを実行する
npm test -- ExpenseCalculator.test.ts
# ウォッチモードで実行する
npm test -- --watch
# E2E テストを実行する
npm run test:e2e
リファレンスドキュメント
詳細なパターンと技術については、以下を参照してください:
references/testing_patterns.md- 包括的なテストパターン、ベストプラクティス、コード例references/bug_analysis.md- 詳細なバグ分析フレームワーク、一般的なバグパターン、デバッグ技法
これらのリファレンスには詳細な例と高度な技術が含まれています。以下の場合にロードしてください:
- 複雑なテストシナリオに対処している
- 特定のパターン実装が必要
- 異常な問題をデバッグしている
- 特定の状況でのベストプラクティスを探している
スクリプト
analyze_coverage.py
Jest/Istanbul カバレッジレポートを分析してギャップを特定します:
python3 scripts/analyze_coverage.py [coverage-file]
指定されていない場合、一般的なカバレッジファイルの場所を自動的に検出します。
出力:
- カバレッジ閾値を下回るファイル
- ステートメント、ブランチ、関数のカバレッジ率
- 改善の優先度ファイル
find_untested_code.py
対応するテストファイルがないソースファイルを検出します:
python3 scripts/find_untested_code.py [src-dir] [--pattern test|spec]
出力:
- ソースおよびテストファイルの総数
- テストファイルカバレッジ率
- タイプ別に分類された未テストファイル(API、サービス、コンポーネントなど)
- 優先順位付けの推奨事項
ベストプラクティスの要約
- 新機能を追加する際はテストを最初に書く(TDD)
- 実装ではなく動作をテストする - テストはリファクタリングに耐えるべき
- テストは独立させる - テスト間に共有状態がない
- 説明的な名前を使用する - テスト名がシナリオを説明すべき
- エッジケースをカバーする - null、空、境界値、エラー条件
- 外部依存関係をモック化する - テストは高速で信頼できるべき
- カバレッジを高く保つ - 重大なコードで 80% 以上
- 失敗するテストはすぐに修正する - 壊れたテストをコミットしない
- テストをリファクタリングする - 本番コードと同じ品質基準を適用する
- ツールを使用する - カバレッジ分析とギャップ特定を自動化する
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- ailabs-393
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/ailabs-393/ai-labs-claude-skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。