platform-apex-test-generate について
Salesforce Apex のテストクラスを生成し、カバレッジ分析を通じて失敗を修正するスキルです。同期・非同期コードを対象に、分離されたテストの作成を支援します。
主な機能
- 01動作ごとのテストメソッド
- 02ファクトリーによるテストデータ分離
- 03アサーションとモックのパターン
- 04非同期・一括処理のテスト指針
- 05カバレッジ分析と修正ループ
活用シーン
- 01Apex クラスのテスト作成
- 02トリガーの一括処理を検証
- 03コールアウトと非同期処理のテスト
- 04失敗分析とカバレッジ不足の補完
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill platform-apex-test-generateインストール後、Claude Code で/platform-apex-test-generateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/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 — 結果を分析する
次の点に注目します。
- 失敗したメソッド — 例外の種類とスタックトレース
- カバーされていない行とカバレッジの低い領域
- 失敗の原因が不適切なテストデータ、壊れやすいアサーション、本番ロジックの不具合のいずれであるか
- クラスメタデータがバージョン 66.0 以下から 67.0 以上へ移行する場合は、明示的な共有設定を確認し、操作ごとにユーザーモードかシステムモードかを決定し、テストユーザーまたは権限セットに必要な CRUD/FLS 権限を付与して、影響を受けるテストを再実行します
ステップ 5 — 修正ループ
テストが失敗した場合は、規律ある修正ループを実行します(最大 3 回の反復 — それでも失敗する場合は停止し、根本原因を報告します)。
- 失敗したテストクラスとテスト対象のクラスを読みます
- エラーメッセージとスタックトレースから根本原因を特定します
- 修正を適用します — テスト側の問題であればテストデータまたはアサーションを調整し、本番コードの問題であれば
platform-apex-generateスキルに委任します - より広範な回帰テストの前に、対象を絞ったテストを再実行します
- すべてのテストが成功するか、反復上限に達するか、根本原因の解決に設計変更が必要となるまで繰り返します
ステップ 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 の登録 |
| Platform Event | 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、メール、Platform Events |
| references/async-testing.md | バッチ、Queueable、Future、スケジュール済みジョブのテスト |