mcpField
T
testing

testing

github.com/seb1nテスト・品質236138 回インストール12 週間前に更新
リポジトリ

testing について

testing は、AI エージェント向けのコードテストスキルです。テストケースの特定、作成と実行、カバレッジ分析、改善提案までを扱い、複数の言語とテストフレームワークに対応します。

主な機能

  1. 01コードと依存関係の分析
  2. 02境界値や例外のテストケース特定
  3. 03テストの作成と実行
  4. 04カバレッジ分析と改善提案
  5. 05複数言語とテストフレームワークへの対応

活用シーン

  1. 01既存モジュールのユニットテスト生成
  2. 02テスト拡張とカバレッジ不足の確認
  3. 03テスト失敗の調査と改善計画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/seb1n/awesome-ai-agent-skills --skill testing

インストール後、Claude Code で/testingを入力して読み込まれたか確認します。

詳細

テスト

このスキルを使うと、AI エージェントが指定されたコードベースのテストを体系的に生成、実行、評価できます。ソースコードの分析や有意義なテストケースの特定から、テストの作成と実行、カバレッジの測定、改善案の提案まで、テストのライフサイクル全体を網羅します。エージェントは、複数の言語やフレームワークにわたって、単体テスト、統合テスト、エンドツーエンドテストに対応しています。

ワークフロー

  1. ソースコードを分析します。 対象のファイルまたはモジュールを読み込み、その関数、クラス、外部とのやり取りに関する依存関係グラフを作成します。公開インターフェース、内部ヘルパー、入力パラメーター、戻り値の型、副作用を特定します。このステップで、何をテストできるか、どのようなテストが適切かを判断します。

  2. テストケースを特定します。 各関数またはメソッドについて、網羅すべきシナリオを列挙します。正常系の入力、境界値、不正または null の入力、例外パス、状態遷移が含まれます。統合ポイントについては、モックまたはスタブを使用する対象と、実際にテストする対象を特定します。リスクに基づいてケースに優先順位を付け、複雑な分岐ロジックと公開 API の範囲から着手します。

  3. テストを作成します。 プロジェクトで既に使用されているテストフレームワーク(例:pytest、Jest、JUnit)を使って、適切に構成されたテストコードを生成します。各テストには、シナリオと期待される結果がわかる説明的な名前を付けます。Arrange-Act-Assert パターンを使用し、事前条件を設定してから、テスト対象のコードを呼び出し、期待される結果をアサートします。複数の入力セットに同じ論理ケースを適用できる場合は、パラメーター化テストを追加します。

  4. テストを実行します。 適切なランナーコマンドを使ってテストスイートを実行します。合否ステータス、アサーションメッセージ、実行時間を含む出力全体を記録します。テストが失敗した場合は、失敗時の出力を解析し、ソースコードのバグによる失敗なのか、テスト自体の誤りによる失敗なのかを判断します。

  5. カバレッジを分析します。 カバレッジ計測を有効にしてテストスイートを実行します(例:pytest --cov、jest --coverage)。カバレッジレポートを解析して、未カバーの行、分岐、関数を特定します。カバレッジが不足しているエラーハンドラー、セキュリティチェック、データ検証などの重要なコードパスにフラグを立てます。

  6. 改善案を提案します。 カバレッジの不足箇所とコードの複雑さに基づいて、追加のテストケースを提案します。純粋関数の抽出や依存性注入の導入など、コードをテストしやすくするリファクタリングの機会を提案します。カバレッジ率と、次に行うべきアクションの優先順位付きリストを含む概要レポートを作成します。

対応言語

言語フレームワークランナーコマンド
Pythonpytestpytest --cov=src -v
JavaScriptJestnpx jest --coverage --verbose
TypeScriptJest / Vitestnpx vitest run --coverage
JavaJUnit 5mvn test
Gotesting (stdlib)go test -cover ./...
Rustcargo testcargo test

使用方法

次の入力から、1 つ以上を指定します。

  • テストを生成するソースファイルまたはディレクトリ(例:src/utils/parser.py)。
  • 既存のテストファイル。エージェントに現在のテストを拡張または改善させたい場合に指定します。
  • テストフレームワークの希望。プロジェクトでまだ設定されていない場合に指定します。
  • カバレッジのしきい値。特定の割合を目標にしたい場合に指定します(例:90%)。

例

例 1 — pytest を使用する Python

次のソースファイル src/cart.py があるとします。

class ShoppingCart:
    def __init__(self):
        self.items = []

    def add_item(self, name: str, price: float, quantity: int = 1):
        if price < 0:
            raise ValueError("Price cannot be negative")
        if quantity < 1:
            raise ValueError("Quantity must be at least 1")
        self.items.append({"name": name, "price": price, "quantity": quantity})

    def total(self) -> float:
        return sum(item["price"] * item["quantity"] for item in self.items)

    def remove_item(self, name: str):
        self.items = [item for item in self.items if item["name"] != name]

エージェントは tests/test_cart.py を生成します。

import pytest
from src.cart import ShoppingCart

@pytest.fixture
def cart():
    return ShoppingCart()

def test_add_item_and_total(cart):
    cart.add_item("Widget", 9.99, 2)
    assert cart.total() == pytest.approx(19.98)

def test_empty_cart_total_is_zero(cart):
    assert cart.total() == 0.0

def test_add_item_negative_price_raises(cart):
    with pytest.raises(ValueError, match="Price cannot be negative"):
        cart.add_item("Bad", -1.0)

def test_add_item_zero_quantity_raises(cart):
    with pytest.raises(ValueError, match="Quantity must be at least 1"):
        cart.add_item("Bad", 5.0, 0)

def test_remove_item(cart):
    cart.add_item("A", 1.0)
    cart.add_item("B", 2.0)
    cart.remove_item("A")
    assert cart.total() == 2.0

def test_remove_nonexistent_item_does_nothing(cart):
    cart.add_item("A", 1.0)
    cart.remove_item("Z")
    assert cart.total() == 1.0

実行:pytest tests/test_cart.py --cov=src -v

例 2 — Jest を使用する JavaScript

次のソースファイル src/validator.js があるとします。

function isValidEmail(email) {
  if (typeof email !== "string") return false;
  const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return re.test(email);
}

function isStrongPassword(password) {
  if (typeof password !== "string") return false;
  return (
    password.length >= 8 &&
    /[A-Z]/.test(password) &&
    /[a-z]/.test(password) &&
    /[0-9]/.test(password)
  );
}

module.exports = { isValidEmail, isStrongPassword };

エージェントは src/__tests__/validator.test.js を生成します。

const { isValidEmail, isStrongPassword } = require("../validator");

describe("isValidEmail", () => {
  test.each([
    ["[email protected]", true],
    ["[email protected]", true],
    ["missing-at-sign.com", false],
    ["@no-local.com", false],
    ["spaces [email protected]", false],
    ["", false],
  ])("isValidEmail(%s) => %s", (input, expected) => {
    expect(isValidEmail(input)).toBe(expected);
  });

  test("returns false for non-string input", () => {
    expect(isValidEmail(null)).toBe(false);
    expect(isValidEmail(42)).toBe(false);
  });
});

describe("isStrongPassword", () => {
  test("accepts a strong password", () => {
    expect(isStrongPassword("Str0ngPwd")).toBe(true);
  });

  test("rejects short password", () => {
    expect(isStrongPassword("Ab1")).toBe(false);
  });

  test("rejects password without uppercase", () => {
    expect(isStrongPassword("alllower1")).toBe(false);
  });

  test("rejects non-string input", () => {
    expect(isStrongPassword(undefined)).toBe(false);
  });
});

実行:npx jest --coverage --verbose

ベストプラクティス

  • 実装ではなく、シナリオに基づいてテストに名前を付けます。 test_total_method ではなく、test_empty_cart_total_is_zero のような名前を使用します。これにより、失敗の内容が名前から分かります。
  • テストは互いに独立させます。 各テストでは、フィクスチャまたはセットアップメソッドを使って独自の状態を準備します。テストの実行順序に依存してはいけません。
  • 入力のバリエーションには、パラメーター化テストを使用します。 同じロジックを多数の入力に適用する場合は、テスト本体を複製するのではなく、@pytest.mark.parametrize または test.each を使用します。
  • 内部ロジックではなく、外部依存関係をモックします。 ネットワーク呼び出し、データベース、ファイル I/O はスタブ化します。テスト対象のコード自体をモックするのは避けてください。それではテストの目的が失われます。
  • 100%のカバレッジではなく、意味のあるカバレッジを目指します。 重要なパスを徹底的に分岐カバレッジで網羅します。単純なゲッターやフレームワークが生成するコードは、通常、個別のテストを必要としません。
  • すべてのコミットで CI 上のテストを実行します。 プロジェクトの CI パイプラインにテストコマンドを組み込み、リグレッションをすぐに検出できるようにします。

エッジケース

  • 動的に生成されるコード: コードベースでメタプログラミング、デコレーター、またはコード生成を使用している場合、エージェントがすべての呼び出し可能なパスを検出できないことがあります。生成されるインターフェースについてヒントを提示してください。
  • グローバル状態とシングルトン: グローバル状態を変更するコードのテストでは、慎重な後処理が必要です。エージェントはこれらを指摘しますが、許容されるリセット方法について案内が必要な場合があります。
  • 非同期コードと並行コード: 非同期関数のテストには、フレームワーク固有のパターン(pytest-asyncio、Jest の非同期処理など)が必要です。エージェントは適切なパターンを使用しますが、タイムアウトのしきい値について確認を求める場合があります。
  • 環境に依存するテスト: 環境変数、ファイルシステムの構成、またはネットワークアクセスに依存するテストは、統合テストとして明確に分類し、高速なユニットテストの実行対象から除外してください。
  • 不安定なテスト: テストの実行結果に断続的な失敗が生じる場合、エージェントは非決定的なパターン(例:実時間への依存、順序が保証されないコレクションの比較)を指摘し、修正方法を提案します。

コメント