Platform Apex Test Generate

forcedotcom/sf-skills/skills/platform-apex-test-generate

作者 forcedotcome5164d94d7511c00fa02a5b8b60754b2361e178f無授權條款1K 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫2 天前更新

Use to generate and validate Apex test classes with TestDataFactory patterns, bulk testing (251+ records), mocking, assertions, and disciplined test-fix loops. Use when creating Apex test classes (for triggers, services, controllers, batch jobs, queueables, and callouts), improving coverage, debugging or fixing failing Apex tests, or running test/coverage analysis. Triggers on *Test.cls files, sf apex run test, coverage reports. Do NOT trigger for production Apex (use platform-apex-generate) or Jest/LWC tests.

AI 產生的概覽

產生並驗證 Salesforce Apex 測試類別,涵蓋 TestDataFactory 模式、大量測試、模擬與涵蓋率分析。

功能
此技能指導建立可用於正式環境的 Apex 測試類別,適用於觸發程序、服務、控制器、批次工作、佇列工作與外部呼叫。它會產出測試類別檔案與中介資料檔案,並在缺少時建立 TestDataFactory 類別,遵循 Given/When/Then 結構與命名慣例。它也透過 Salesforce CLI 執行測試、分析失敗與涵蓋率,並執行有次數上限的測試修正迴圈。
適用情境
適用於撰寫新的 Apex 測試類別、提升測試涵蓋率,或偵錯與修正失敗的 Apex 測試。它僅針對測試程式碼,不用於正式環境 Apex 或 Jest/LWC 測試。
執行需求
需要 Salesforce CLI(sf,2.0.0 或更新版本),並透過 target-org 別名存取 Salesforce 組織以執行測試。它附帶範本資源與參考文件,但不含可執行指令碼。

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 [blocked]
  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 [blocked]
  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 [blocked]
  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 [blocked]
  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-PatternFix
SOQL/DML inside loopsQuery once before the loop; use Map<Id, SObject> for lookups
Magic numbers in assertionsDerive 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 catchCatch 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 [blocked] as starting point)
  2. {ClassName}Test.cls-meta.xml — the metadata file:
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>

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

@TestSetup Example
apex
@TestSetupstatic void setupTestData() {    List<Account> accounts = TestDataFactory.createAccounts(251, true);}
Test Method Structure

Use Given/When/Then:

apex
@isTeststatic 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:

apex
@isTeststatic 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.

bash
# Single test classsf apex run test --class-names MyServiceTest --result-format human --code-coverage --target-org <alias>
# Specific test methodssf apex run test --tests MyServiceTest.shouldUpdateStatus_WhenValidInput --result-format human --target-org <alias>
# All local testssf 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

LevelCoveragePurpose
Production deploy75% minimumRequired by Salesforce
Recommended90%+Best practice target
Critical paths100%Business-critical code

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

What to Test by Component

ComponentKey Test Scenarios
TriggerBulk insert/update/delete, recursion guard, field change detection
ServiceValid/invalid inputs, bulk operations, exception handling
ControllerPage load, action methods, view state
Batchstart/execute/finish, scope matching (batch size >= record count), Database.Stateful tracking, error handling, chaining (separate methods — finish() calling Database.executeBatch() throws UnexpectedException)
QueueableChaining (only first job runs in tests), bulkification, error handling, callout mocks before Test.startTest()
CalloutSuccess response, error response, timeout
SelectorValid/null/empty inputs, bulk (251+), field population, sort order, WITH USER_MODE via System.runAs
ScheduledDirect execution via execute(null), CRON registration via CronTrigger query
Platform EventTest.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:

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

來源與署名

來源:forcedotcom/sf-skills位於skills/platform-apex-test-generate提交e5164d9

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架