
Generating Apex Test
Scaffold Salesforce Apex test classes with bulk (251+), positive, negative, and exception paths so deploys meet Salesforce coverage rules.
Install
npx skills add https://github.com/forcedotcom/sf-skills --skill generating-apex-testWhat is this skill?
- Opinionated @isTest class skeleton with @TestSetup and Given/When/Then sections
- Bulk coverage pattern asserting 251 test accounts for governor-limit realistic runs
- Positive, negative, and exception test stubs with Assert.areEqual messaging
- Placeholder hooks for ClassUnderTest methods and TestDataFactory usage
- Aligns with Salesforce deployment expectations for meaningful assertions, not empty tests
Adoption & trust: 776 installs on skills.sh; 513 GitHub stars; 3/3 security scanners passed (skills.sh audits).
Recommended Skills
Agent Browservercel-labs/open-agents
Tddmattpocock/skills
Use My Browserxixu-me/skills
Test Driven Developmentobra/superpowers
Verification Before Completionobra/superpowers
Webapp Testinganthropics/skills
Journey fit
Common Questions / FAQ
Is Generating Apex Test safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Generating Apex Test
/** * Test class for {ClassUnderTest}. * Tests bulk operations (251+ records), positive/negative paths, * and exception handling. */ @isTest private class {ClassUnderTest}Test { @TestSetup static void setupTestData() { List<Account> accounts = TestDataFactory.createAccounts(251, true); } // ─── Positive Tests ─────────────────────────────────────────────────── @isTest static void shouldPerformExpectedBehavior_WhenValidInput() { // Given List<Account> accounts = [SELECT Id, Name FROM Account]; // When Test.startTest(); // {ClassUnderTest}.methodUnderTest(params); Test.stopTest(); // Then // Assert.areEqual(expected, actual, 'Descriptive failure message'); } @isTest static void shouldHandleBulkRecords_WhenProcessing251() { // Given List<Account> accounts = [SELECT Id FROM Account]; Assert.areEqual(251, accounts.size(), 'Should have 251 test records'); // When Test.startTest(); // {ClassUnderTest}.bulkMethod(accounts); Test.stopTest(); // Then // List<Account> results = [SELECT Id, Status__c FROM Account]; // for (Account acc : results) { // Assert.areEqual('Processed', acc.Status__c, 'All records should be processed'); // } } // ─── Negative Tests ─────────────────────────────────────────────────── @isTest static void shouldThrowException_WhenNullInput() { Test.startTest(); try { // {ClassUnderTest}.methodUnderTest(null); Assert.fail('Expected exception for null input'); } catch (MyCustomException e) { Assert.isTrue(e.getMessage().contains('cannot be null'), 'Exception message should mention null input'); } Test.stopTest(); } @isTest static void shouldReturnEmpty_WhenEmptyInput() { Test.startTest(); // List<SObject> results = {ClassUnderTest}.methodUnderTest(new List<Id>()); Test.stopTest(); // Assert.isTrue(results.isEmpty(), 'Should return empty list for empty input'); } // ─── Edge Case Tests ────────────────────────────────────────────────── @isTest static void shouldHandleMixedRecords_WhenSomeQualify() { // Given List<Account> accounts = [SELECT Id, Status__c FROM Account]; Integer half = accounts.size() / 2; // for (Integer i = 0; i < half; i++) { // accounts[i].Status__c = 'Qualifying'; // } // update accounts; // When Test.startTest(); // {ClassUnderTest}.conditionalMethod(accounts); Test.stopTest(); // Then // List<Account> qualifying = [SELECT Id FROM Account WHERE Processed__c = true]; // Assert.areEqual(half, qualifying.size(), 'Only qualifying records should be processed'); } } /** * @description Centralized factory for creating test data with sensible defaults. * All methods accept a doInsert flag for flexibility. * Bulk methods create multiple records; single-record methods delegate to bulk. */ @isTest public class TestDataFactory { // ─── Accounts ───────────────────────────────────────────────────────── public static List<Account> createAccounts(Integer count, Boolean doInsert) { List<Account> accounts = new List<Account>(); for (Integer i = 0; i < count; i++) { accounts.add(new Account( Name = 'Test Account ' + i, BillingCity = 'San Francisco', BillingState = 'CA', BillingCountry = 'USA', Industry = 'Technology', Type = 'Customer' )); } if (doInsert) insert accounts; return accounts; } public static Account createAccount(Boolean doInsert) { return createAccounts(1, doInsert)[0]; }