generating-apex-test について
Salesforce Apex のテストクラス生成と、テスト修正・カバレッジ分析の手順を定めたスキルです。Apex テストを作成・保守する開発者向けに、データ分離、明確なアサーション、非同期処理、正常系・異常系・一括処理のテストを扱います。
主な機能
- 011つの動作ごとにテストメソッドを構成
- 02TestDataFactory によるデータ分離
- 03Assert による明確な検証
- 04外部呼び出しのモックと異常系テスト
- 05テスト実行とカバレッジ分析
- 06最大3回のテスト修正ループ
活用シーン
- 01Apex クラスのテストクラスとメタデータを生成
- 02251件以上のレコードによるトリガー検証
- 03Queueable、Batch、Scheduled の非同期処理をテスト
- 04テスト結果とカバレッジから失敗箇所を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill generating-apex-testインストール後、Claude Code で/generating-apex-testを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CREDITS.mdassets/test-class-template.clstest-data-factory-template.clsreferences/assertion-patterns.mdasync-testing.mdmocking-patterns.mdtest-data-factory.md詳細
Apex テストの生成
本番環境で使用できる Apex テストクラスを生成し、カバレッジ分析を伴う規律あるテスト・修正サイクルを実行します。
基本原則
- 1 メソッドにつき 1 つの動作 — 各テストメソッドでは単一のシナリオを検証します。正常系、異常系、バルクテストは分けてください。関連するものの異なる入力(例:null と空)を 1 つのメソッドにまとめてはいけません。
_NullInput_と_EmptyInput_を別々のテストメソッドとして作成してください - テストをバルク化する — 200 レコードのトリガーバッチ境界を超えるため、251 件以上のレコードでテストしてください。**Batch Apex の例外:**テストコンテキストでは
execute()の呼び出しは 1 回のみ実行されるため、batchSize >= testRecordCountを設定してください。references/async-testing.md を参照してください - テストデータを分離する — すべての
@TestSetupでは、レコードの作成をTestDataFactoryクラスに委譲する必要があります。存在しない場合は、まず作成してください。@TestSetup内でレコードリストを直接構築してはいけません。組織のデータ(SeeAllData=false)やハードコードされた ID に依存してはいけません。重複ルールの処理については、references/test-data-factory.md を参照してください - 意味のあるアサーションを行う — テストデータのセットアップから算出した、厳密な期待値を使用してください。値が決定的な場合、範囲によるアサーションや概算の件数を使用してはいけません。必ず失敗メッセージを含めてください。references/assertion-patterns.md を参照してください
Assertクラスのみを使用する —Assert.areEqual、Assert.isTrue、Assert.failなどを使用してください。従来のSystem.assert、System.assertEquals、System.assertNotEqualsは使用しないでください- 外部境界をモックする — コールアウトには
HttpCalloutMock、SOSL にはTest.setFixedSearchResults、データベース分離には DML モッククラスを使用してください。コンストラクターインジェクションを用いて、テストしやすい設計にしてください。references/mocking-patterns.md を参照してください - 異常系をテストする — 正常系だけでなく、エラー処理と例外のシナリオも検証してください
- start/stop で囲む —
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 — コンテキストを収集する
テストを生成または修正する前に、次を特定します。
- テスト対象となる本番クラス
- 既存のテストクラス、テストデータファクトリー、セットアップヘルパー
- 希望するテスト範囲(単一クラス、特定のメソッド、スイート、またはローカルテスト)
- カバレッジのしきい値(デプロイには最低 75%、90% 以上を推奨)
- 組織に対してテストを実行する際の組織エイリアス
ステップ 2 — テストクラスを生成する
アセットテンプレートと参考ドキュメントに記載された構成、命名規則、パターンを適用します。
**必須 — ファイルの成果物:**各テストクラスについて、次の BOTH ファイルを作成します。
{ClassName}Test.cls— テストクラス(出発点として assets/test-class-template.cls を使用){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');
}
異常系テスト — 例外のパターン
期待される例外を検証するには、Assert.fail を使った try/catch を使用します。
@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[ExpectedResult]_When[Scenario]:shouldSendNotification_WhenOpportunityClosedWon[SubjectOrAction]_[Scenario]_[ExpectedResult]:AccountUpdate_ChangeName_Success
ステップ 3 — テストを実行する
デバッグ時は対象を絞って開始し、修正が安定したら範囲を広げます。
# 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>
ステップ 4 — 結果を分析する
次の点に注目します。
- 失敗したメソッド — 例外の種類とスタックトレース
- カバーされていない行とカバレッジの低い領域
- 失敗の原因が不適切なテストデータ、壊れやすいアサーション、本番ロジックの不具合のいずれであるか
ステップ 5 — 修正ループ
テストが失敗した場合は、規律をもって修正ループを実行します(最大 3 回。失敗が続く場合は中断し、根本原因を報告します)。
- 失敗したテストクラスとテスト対象クラスを読む
- エラーメッセージとスタックトレースから根本原因を特定する
- 修正を適用する — テスト側の問題にはテストデータまたはアサーションを調整し、本番コードの問題は
generating-apexスキルに委任する - より広範な回帰テストの前に、対象を絞ったテストを再実行する
- すべてのテストが成功するか、反復回数の上限に達するか、設計変更が必要な根本原因が判明するまで繰り返す
ステップ 6 — カバレッジを検証する
| レベル | カバレッジ | 目的 |
|---|---|---|
| 本番環境へのデプロイ | 75% 以上 | Salesforce の必須条件 |
| 推奨 | 90% 以上 | ベストプラクティスの目標 |
| クリティカルパス | 100% | ビジネス上重要なコード |
すべての経路をカバーします。正常系、異常系/例外、バルク(251 件以上のレコード)、コールアウト/非同期処理が対象です。
コンポーネント別のテスト対象
| コンポーネント | 主なテストシナリオ |
|---|---|
| トリガー | バルクでの挿入/更新/削除、再帰ガード、項目変更の検出 |
| サービス | 有効/無効な入力、バルク操作、例外処理 |
| コントローラー | ページの読み込み、アクションメソッド、ビューステート |
| バッチ | start/execute/finish、スコープの一致(バッチサイズ >= レコード数)、Database.Stateful の追跡、エラー処理、チェーン(個別のメソッド — finish() から Database.executeBatch() を呼び出すと UnexpectedException がスローされます) |
| Queueable | チェーン(テストでは最初のジョブのみ実行)、バルク化、エラー処理、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 | Batch、Queueable、Future、Scheduled ジョブのテスト |