• Projects
  • Service
  • About
  • branding.bz
  • Podcast
  • Tips
  • FAQ
  • Recruit
  • Download
  • Contact
  • branding.bz(ブランド構築SaaS)
  • DESIGN NOW(デザインメディア)
  • X
  • LinkedIn
  • Spotify
  • Facebook

213-0011 神奈川県川崎市高津区久本3-6-7-303

© 2026 ID INC. All rights reserved

claude-skills/スキル
SKILLOfficialdevelopment

platform-apex-test-generate

プラグイン
salesforce-development
ソース
GitHub で見る ↗
説明

Apex テストクラスを生成・検証するスキルです。TestDataFactory パターン(テスト用データを効率的に作成する仕組み)、大量データテスト(251件以上のレコード)、モッキング戦略(外部処理を模擬する手法)、アサーション(確認処理)のベストプラクティス、および規律あるテスト・修正サイクルに対応します。 **次のような場合に使用:** - 新しい Apex テストクラスを作成する - テストカバレッジ(コードの検証度合い)を向上させる - 失敗した Apex テストをデバッグ・修正する - テスト実行とカバレッジ分析を行う - トリガー、サービス、コントローラー、バッチジョブ、キューアブル、連携処理のテストパターンを実装する **自動的に起動する条件:** `*Test.cls`、`*_Test.cls` ファイル、sf apex run test ワークフロー、カバレッジレポート、テスト・修正サイクル **起動しない条件:** 本番用の Apex コード(platform-apex-generate スキルを使用)や Jest/LWC テスト

原文を表示

Generate and validate Apex test classes with TestDataFactory patterns, bulk testing (251+ records), mocking strategies, assertion best practices, and disciplined test-fix loops. Use this skill when creating new Apex test classes, improving test coverage, debugging and fixing failing Apex tests, running test execution and coverage analysis, or implementing testing patterns for triggers, services, controllers, batch jobs, queueables, and integrations. Triggers on *Test.cls, *_Test.cls files, sf apex run test workflows, coverage reports, test-fix loops. Do NOT trigger for production Apex code (use platform-apex-generate) or Jest/LWC tests.

ユースケース
  • 新しい Apex テストクラスを作成する
  • テストカバレッジを向上させる
  • 失敗した Apex テストをデバッグ・修正する
  • テスト実行とカバレッジ分析を行う
  • トリガーやバッチジョブのテストを実装する
本文(日本語訳)

Apex テストの生成

本番環境対応のApexテストクラスを生成し、カバレッジ(コード網羅率)分析を伴った体系的なテスト修正サイクルを実行します。

基本原則

  1. 1メソッドにつき1つの動作 — 各テストメソッドは1つのシナリオのみを検証します。正常系、異常系、一括処理のテストは分けてください。関連しているが異なる入力値(例:null と空文字列)を1つのメソッドに混在させずに、_NullInput_ と _EmptyInput_ として別々のテストメソッドを作成してください

  2. 一括処理テストも含める — 251件以上のレコードでテストし、200件のトリガー一括処理境界を越えてください。Batch Apex の例外: テストコンテキストでは execute() が1回だけ実行されるため、batchSize >= testRecordCount に設定してください。references/async-testing.md を参照

  3. テストデータの分離 — すべての @TestSetup はレコード作成を TestDataFactory クラスに委譲してください。存在しない場合は先に作成してください。@TestSetup 内でレコードリストを直接構築しないでください。また、組織データ(SeeAllData=false)やハードコード化されたIDに依存しないでください。重複ルール処理については references/test-data-factory.md を参照

  4. 意味のあるアサーション — テストデータ設定から計算した正確な期待値を使用してください。値が確定的である場合、範囲指定アサーションや概数カウントは使用しないでください。常に失敗メッセージを含めてください。references/assertion-patterns.md を参照

  5. Assert クラスのみ使用 — Assert.areEqual、Assert.isTrue、Assert.fail などを使用してください。レガシーの System.assert、System.assertEquals、System.assertNotEquals は使用しないでください

  6. 外部連携をモック化 — 外部連携にはHttpCalloutMock、SOSL にはTest.setFixedSearchResults、データベース分離にはDMLモッククラスを使用してください。コンストラクタインジェクション経由のテスト設計を心がけてください。references/mocking-patterns.md を参照

  7. 負の経路もテスト — 正常系だけでなく、エラー処理と例外シナリオも検証してください

  8. startTest/stopTest で囲む — Test.startTest() と Test.stopTest() をペアで使用し、ガバナー制限(処理上限)をリセットし、非同期処理を強制実行してください

Test.startTest() / Test.stopTest()

テスト対象のコードを常に Test.startTest() / Test.stopTest() で囲んでください:

  • ガバナー制限をリセットし、テストがテスト対象コードのみを計測することを保証します
  • 非同期操作(キュー可能なジョブ、バッチ、Future メソッド)を同期的に実行します
  • スケジュール済みジョブを即座に実行します

テストコードのアンチパターン

アンチパターン 修正方法
ループ内のSOQL/DML ループ前に1回クエリを実行し、ルックアップに Map<Id, SObject> を使用
アサーション内のマジックナンバー 期待値をセットアップ定数から導出
巨大なテストクラス(500行超) 動作領域ごとに複数のテストクラスに分割
長いテストメソッド(30行超) Given/When/Then をヘルパーメソッドに抽出
汎用的な Exception キャッチ 予想される具体的な型をキャッチ(例:DmlException)

ワークフロー

ステップ1 — コンテキストを収集

テストを生成または修正する前に、以下を特定してください:

  • テスト対象の本番環境クラス
  • 既存のテストクラス、テストデータファクトリー(テストデータ作成支援クラス)、セットアップヘルパー
  • 必要なテスト範囲(1つのクラス、特定のメソッド、スイート、またはローカルテスト)
  • カバレッジ閾値(デプロイ時の最小値75%、推奨90%以上)
  • テストを実行する際の組織エイリアス

ステップ2 — テストクラスを生成

アセットテンプレートとリファレンスドキュメントの構造、命名規則、パターンを適用してください。

必須 — ファイル成果物: すべてのテストクラスについて、以下の2つのファイルを作成してください:

  1. {ClassName}Test.cls — テストクラス(assets/test-class-template.cls を出発点として使用)
  2. {ClassName}Test.cls-meta.xml — メタデータファイル:
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>66.0</apiVersion>
    <status>Active</status>
</ApexClass>

プロジェクトに TestDataFactory が存在しない場合、assets/test-data-factory-template.cls を使用して TestDataFactory.cls + TestDataFactory.cls-meta.xml を作成してください。

@TestSetup の例

@TestSetup
static void setupTestData() {
    List<Account> accounts = TestDataFactory.createAccounts(251, true);
}

テストメソッドの構造

Given/When/Then を使用してください:

@isTest
static void shouldUpdateStatus_WhenValidInput() {
    // Given
    List<Account> accounts = [SELECT Id FROM Account];

    // When
    Test.startTest();
    MyService.processAccounts(accounts);
    Test.stopTest();

    // Then
    List<Account> updated = [SELECT Id, Status__c FROM Account];
    Assert.areEqual(251, updated.size(), 'All accounts should be processed');
}

異常系テスト — 例外パターン

try/catch と Assert.fail を使用して予想される例外を検証してください:

@isTest
static void shouldThrowException_WhenInvalidInput() {
    // Given
    List<Account> emptyList = new List<Account>();

    // When/Then
    Test.startTest();
    try {
        MyService.processAccounts(emptyList);
        Assert.fail('Expected MyCustomException to be thrown');
    } catch (MyCustomException e) {
        Assert.isTrue(e.getMessage().contains('cannot be empty'),
            'Exception message should indicate empty input');
    }
    Test.stopTest();
}

命名規則

  • should[予想される結果]_When[条件]: shouldSendNotification_WhenOpportunityClosedWon
  • [対象または操作]_[条件]_[予想される結果]: AccountUpdate_ChangeName_Success

ステップ3 — テストを実行

デバッグ時は狭い範囲から始め、修正が安定した後に拡大してください。

# 1つのテストクラス
sf apex run test --class-names MyServiceTest --result-format human --code-coverage --target-org <alias>

# 特定のテストメソッド
sf apex run test --tests MyServiceTest.shouldUpdateStatus_WhenValidInput --result-format human --target-org <alias>

# すべてのローカルテスト
sf apex run test --test-level RunLocalTests --result-format human --code-coverage --target-org <alias>

ステップ4 — 結果を分析

以下に注目してください:

  • 失敗したメソッド — 例外タイプとスタックトレース
  • 未カバーの行と弱いカバレッジ領域
  • 失敗がテストデータの問題、脆いアサーション、または本番ロジックの不具合を示しているか
  • クラスメタデータのバージョンが66.0以下から67.0以上に変わる場合、明示的な共有設定を確認し、操作ごとにユーザーモード/システムモードを決定し、テストユーザーまたはパーミッションセットで必要なCRUD/FLS(フィールドレベルセキュリティ)権限を付与し、影響を受けたテストを再実行してください

ステップ5 — 修正ループ

テストが失敗した場合、体系的な修正ループを実行してください(最大3回のイテレーション — 依然として失敗している場合は根本原因を明らかにしてください):

  1. 失敗したテストクラスとテスト対象クラスを読んでください
  2. エラーメッセージとスタックトレースから根本原因を特定してください
  3. 修正を適用 — テスト側の問題の場合はテストデータまたはアサーションを調整;本番コード側の問題の場合は platform-apex-generate スキルに委譲してください
  4. より広い回帰テストの前に、絞ったテストを再実行してください
  5. すべてのテストが合格するか、イテレーション上限に達するか、設計変更が必要な根本原因が明らかになるまで繰り返してください

ステップ6 — カバレッジを検証

レベル カバレッジ 目的
本番環境デプロイ 最小75% Salesforce が必須
推奨 90%以上 ベストプラクティス目標
重要な経路 100% ビジネス上重要なコード

すべての経路をカバー:正常系、異常系/例外、一括処理(251件以上のレコード)、外部連携/非同期処理

コンポーネントごとのテスト対象

コンポーネント 主要なテストシナリオ
トリガー 一括挿入/更新/削除、再帰ガード(無限ループ防止)、フィールド変更検出
サービス 有効/無効な入力値、一括操作、例外処理
コントローラー ページロード、アクションメソッド、ビュー状態
バッチ start/execute/finish、スコープ一致(バッチサイズ >= レコード数)、Database.Stateful の追跡、エラー処理、チェーン(個別メソッド — finish() が Database.executeBatch() を呼び出すと UnexpectedException がスロー)
キューに登録可能な処理 チェーン(テストでは最初のジョブのみ実行)、一括処理、エラー処理、Test.startTest() 前に外部連携モックを設定
外部連携 成功レスポンス、エラーレスポンス、タイムアウト
セレクター(クエリヘルパー) 有効/null/空の入力値、一括処理(251件以上)、フィールド補完、ソート順、System.runAs 経由の WITH USER_MODE
スケジュール済み execute(null) 経由の直接実行、CronTrigger クエリ経由のCRON登録
プラットフォームイベント Test.enableChangeDataCapture()、Test.getEventBus().deliver()、購読者側の影響を検証

出力期待値

テストクラスごとの成果物:

  • {ClassName}Test.cls + {ClassName}Test.cls-meta.xml(テスト対象クラスのAPIバージョンに合わせる;デフォルト 66.0)
  • TestDataFactory.cls + TestDataFactory.cls-meta.xml(既に存在しない場合)

リファレンスファイル

詳細なパターンについては必要に応じて参照してください:

リファレンス 使用時期
references/test-data-factory.md TestDataFactory パターン、フィールド上書き、重複ルール処理
references/assertion-patterns.md アサーション ベストプラクティス、アンチパターン、一般的な落とし穴
references/mocking-patterns.md HttpCalloutMock、DMLモック、StubProvider、SOSL、メール、プラットフォームイベント
references/async-testing.md バッチ、キューに登録可能な処理、Future、スケジュール済みジョブのテスト
原文(English)を表示

Generating Apex Tests

Generate production-ready Apex test classes and run disciplined test-fix loops with coverage analysis.

Core Principles

  1. One behavior per method — each test method validates a single scenario. Separate positive, negative, and bulk tests. NEVER combine related-but-distinct inputs (e.g., null and empty) in one method — create _NullInput_ and _EmptyInput_ as separate test methods
  2. Bulkify tests — test with 251+ records to cross the 200-record trigger batch boundary. Batch Apex exception: in test context only one execute() invocation runs, so set batchSize >= testRecordCount. See references/async-testing.md
  3. Isolate test data — every @TestSetup must delegate record creation to a TestDataFactory class. If none exists, create one first. Never build record lists inline in @TestSetup. Never rely on org data (SeeAllData=false) or hardcoded IDs. For duplicate rule handling, see references/test-data-factory.md
  4. Assert meaningfully — use exact expected values computed from test data setup. NEVER use range assertions or approximate counts when the value is deterministic. Always include failure messages. See references/assertion-patterns.md
  5. Use Assert class only — Assert.areEqual, Assert.isTrue, Assert.fail, etc. Never use legacy System.assert, System.assertEquals, or System.assertNotEquals
  6. Mock external boundaries — use HttpCalloutMock for callouts, Test.setFixedSearchResults for SOSL, DML mock classes for database isolation. Design for testability via constructor injection. See references/mocking-patterns.md
  7. Test negative paths — validate error handling and exception scenarios, not just happy paths
  8. Wrap with start/stop — pair Test.startTest() with Test.stopTest() to reset governor limits and force async execution

Test.startTest() / Test.stopTest()

Always wrap the code under test in Test.startTest() / Test.stopTest():

  • Resets governor limits so the test measures only the code under test
  • Executes async operations synchronously (queueables, batch, future methods)
  • Fires scheduled jobs immediately

Test Code Anti-Patterns

Anti-Pattern Fix
SOQL/DML inside loops Query once before the loop; use Map<Id, SObject> for lookups
Magic numbers in assertions Derive expected values from setup constants
God test class (>500 lines) Split into multiple test classes by behavior area
Long test methods (>30 lines) Extract Given/When/Then into helper methods
Generic Exception catch Catch the specific expected type (e.g., DmlException)

Workflow

Step 1 — Gather Context

Before generating or fixing tests, identify:

  • the target production class(es) under test
  • existing test classes, test data factories, and setup helpers
  • desired test scope (single class, specific methods, suite, or local tests)
  • coverage threshold (75% minimum for deploy, 90%+ recommended)
  • org alias when running tests against an org

Step 2 — Generate the Test Class

Apply the structure, naming conventions, and patterns from the asset templates and reference docs.

MANDATORY — File Deliverables: For every test class, create BOTH files:

  1. {ClassName}Test.cls — the test class (use assets/test-class-template.cls as starting point)
  2. {ClassName}Test.cls-meta.xml — the metadata file:
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>66.0</apiVersion>
    <status>Active</status>
</ApexClass>

If no TestDataFactory exists in the project, create TestDataFactory.cls + TestDataFactory.cls-meta.xml using assets/test-data-factory-template.cls.

@TestSetup Example

@TestSetup
static void setupTestData() {
    List<Account> accounts = TestDataFactory.createAccounts(251, true);
}

Test Method Structure

Use Given/When/Then:

@isTest
static void shouldUpdateStatus_WhenValidInput() {
    // Given
    List<Account> accounts = [SELECT Id FROM Account];

    // When
    Test.startTest();
    MyService.processAccounts(accounts);
    Test.stopTest();

    // Then
    List<Account> updated = [SELECT Id, Status__c FROM Account];
    Assert.areEqual(251, updated.size(), 'All accounts should be processed');
}

Negative Test — Exception Pattern

Use try/catch with Assert.fail to verify expected exceptions:

@isTest
static void shouldThrowException_WhenInvalidInput() {
    // Given
    List<Account> emptyList = new List<Account>();

    // When/Then
    Test.startTest();
    try {
        MyService.processAccounts(emptyList);
        Assert.fail('Expected MyCustomException to be thrown');
    } catch (MyCustomException e) {
        Assert.isTrue(e.getMessage().contains('cannot be empty'),
            'Exception message should indicate empty input');
    }
    Test.stopTest();
}

Naming Convention

  • should[ExpectedResult]_When[Scenario]: shouldSendNotification_WhenOpportunityClosedWon
  • [SubjectOrAction]_[Scenario]_[ExpectedResult]: AccountUpdate_ChangeName_Success

Step 3 — Run Tests

Start narrow when debugging; widen after the fix is stable.

# Single test class
sf apex run test --class-names MyServiceTest --result-format human --code-coverage --target-org <alias>

# Specific test methods
sf apex run test --tests MyServiceTest.shouldUpdateStatus_WhenValidInput --result-format human --target-org <alias>

# All local tests
sf apex run test --test-level RunLocalTests --result-format human --code-coverage --target-org <alias>

Step 4 — Analyze Results

Focus on:

  • failing methods — exception types and stack traces
  • uncovered lines and weak coverage areas
  • whether failures indicate bad test data, brittle assertions, or broken production logic
  • when class metadata crosses from versions 66.0 and below to 67.0 and above, check explicit sharing, decide user/system mode per operation, grant required CRUD/FLS in test users or permission sets, and rerun affected tests

Step 5 — Fix Loop

When tests fail, run a disciplined fix loop (max 3 iterations — stop and surface root cause if still failing):

  1. Read the failing test class and the class under test
  2. Identify root cause from error messages and stack traces
  3. Apply fix — adjust test data or assertions for test-side issues; delegate production code issues to the platform-apex-generate skill
  4. Rerun the focused test before broader regression
  5. Repeat until all tests pass, iteration limit reached, or root cause requires design change

Step 6 — Validate Coverage

Level Coverage Purpose
Production deploy 75% minimum Required by Salesforce
Recommended 90%+ Best practice target
Critical paths 100% Business-critical code

Cover all paths: positive, negative/exception, bulk (251+ records), callout/async.

What to Test by Component

Component Key Test Scenarios
Trigger Bulk insert/update/delete, recursion guard, field change detection
Service Valid/invalid inputs, bulk operations, exception handling
Controller Page load, action methods, view state
Batch start/execute/finish, scope matching (batch size >= record count), Database.Stateful tracking, error handling, chaining (separate methods — finish() calling Database.executeBatch() throws UnexpectedException)
Queueable Chaining (only first job runs in tests), bulkification, error handling, callout mocks before Test.startTest()
Callout Success response, error response, timeout
Selector Valid/null/empty inputs, bulk (251+), field population, sort order, WITH USER_MODE via System.runAs
Scheduled Direct execution via execute(null), CRON registration via CronTrigger query
Platform Event Test.enableChangeDataCapture(), Test.getEventBus().deliver(), verify subscriber side effects

Output Expectations

Deliverables per test class:

  • {ClassName}Test.cls + {ClassName}Test.cls-meta.xml (match API version of class under test; default 66.0)
  • TestDataFactory.cls + TestDataFactory.cls-meta.xml (if not already present)

Reference Files

Load on demand for detailed patterns:

Reference When to use
references/test-data-factory.md TestDataFactory patterns, field overrides, duplicate rule handling
references/assertion-patterns.md Assertion best practices, anti-patterns, common pitfalls
references/mocking-patterns.md HttpCalloutMock, DML mocking, StubProvider, SOSL, Email, Platform Events
references/async-testing.md Batch, Queueable, Future, Scheduled job testing

原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。