afv-library/skills/generating-apex-test/SKILL.md

7.0 KiB

name description
generating-apex-test Generate and validate Apex test classes with TestDataFactory patterns, bulk testing (251+ records), mocking strategies, assertion best practices, and structured test-fix loops. Use when creating new Apex test classes, improving test coverage, fixing failing 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 generating-apex) or Jest/LWC tests.

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
  2. Bulkify tests — test with 251+ records to cross the 200-record trigger batch boundary
  3. Isolate test data — use @TestSetup and TestDataFactory; never rely on org data (SeeAllData=false) or hardcoded IDs
  4. Assert meaningfully — test behavior, not just coverage; always include failure messages
  5. Use Assert class only — use Assert.areEqual, Assert.isTrue, Assert.fail, etc. Never use legacy System.assert, System.assertEquals, or System.assertNotEquals
  6. Mock external dependencies — use HttpCalloutMock, Test.setMock(), DML mocking for integrations
  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

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 expectation (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 below. Reference the appropriate asset templates and reference docs for the component type.

Test Class Structure

@IsTest
private class MyServiceTest {

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

    @IsTest
    static void shouldProcessAllAccounts_WhenValidInput() {
        // Given
        List<Account> accounts = [SELECT Id, Name 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');
        for (Account acc : updated) {
            Assert.areEqual('Processed', acc.Status__c, 'Status should be updated');
        }
    }

    @IsTest
    static void shouldThrowException_WhenInputIsEmpty() {
        // 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

Use descriptive method names: test[SubjectOrAction]_[Scenario]_[ExpectedResult]

  • testAccountUpdate_ChangeName_Success
  • testEmailValidation_InvalidFormat_ThrowsException
  • testOpportunity_ClosedWon_SendsNotification
  • testBatchExecution_RunningAsBatch_TriggerBypassed

Step 3 — Run the Smallest Useful Test Set

Start narrow when debugging a failure; widen only after the fix is stable. See references/cli-commands.md for sf apex run test usage.

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

Step 5 — Fix Loop

When tests fail, run a disciplined fix loop:

  1. Read the failing test class and the class under test
  2. Identify root cause from error messages and stack traces
  3. Apply the fix (test data, assertion, or production code)
  4. Rerun the focused test before broader regression
  5. Repeat until all tests pass or root cause requires design change

See references/test-fix-loop.md for the full loop protocol.

Step 6 — Validate Coverage

Ensure coverage meets thresholds:

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, chunking, error records
Queueable Chaining, bulkification, error handling
Callout Success response, error response, timeout
Scheduled Execution, CRON validation

Output Format

When reporting test results, use this structure:

Test run: <scope>
Org: <alias>
Result: <passed / partial / failed>
Coverage: <percent / key classes>
Issues: <highest-signal failures>
Next step: <fix class, add test, rerun scope, or widen regression>

Reference Files

Load these on demand for detailed patterns:

Reference When to use
references/test-data-factory.md TestDataFactory class patterns and field defaults
references/assertion-patterns.md Assertion best practices, anti-patterns, common pitfalls
references/mocking-patterns.md HttpCalloutMock, DML mocking, StubProvider, Selector mocking, Email and Platform Event testing
references/async-testing.md Batch, Queueable, Future, Scheduled job testing
references/test-patterns.md Test patterns by component type with asset template pointers
references/test-fix-loop.md Structured test-fix loop protocol
references/cli-commands.md sf CLI test execution commands
references/performance-optimization.md Test execution speed and optimization