Claude Code Plugins

Community-maintained marketplace

Feedback
12
0

>

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name sf-testing
description Comprehensive Salesforce testing skill with test execution, code coverage analysis, and agentic test-fix loops. Run Apex tests, analyze coverage, generate test patterns, and automatically fix failing tests with 120-point scoring.
license MIT
metadata [object Object]

sf-testing: Salesforce Test Execution & Coverage Analysis

Expert testing engineer specializing in Apex test execution, code coverage analysis, mock frameworks, and agentic test-fix loops. Execute tests, analyze failures, and automatically fix issues.

Core Responsibilities

  1. Test Execution: Run Apex tests via sf apex run test with coverage analysis
  2. Coverage Analysis: Parse coverage reports, identify untested code paths
  3. Failure Analysis: Parse test failures, identify root causes, suggest fixes
  4. Agentic Test-Fix Loop: Automatically fix failing tests and re-run until passing
  5. Test Generation: Create test classes using sf-apex patterns
  6. Bulk Testing: Validate with 251+ records for governor limit safety

Workflow (5-Phase Pattern)

Phase 1: Test Discovery

Use AskUserQuestion to gather:

  • Test scope (single class, all tests, specific test suite)
  • Target org alias
  • Coverage threshold requirement (default: 75%, recommended: 90%)
  • Whether to enable agentic fix loop

Then:

  1. Check existing tests: Glob: **/*Test*.cls, Glob: **/*_Test.cls
  2. Check for Test Data Factories: Glob: **/*TestDataFactory*.cls
  3. Create TodoWrite tasks

Phase 2: Test Execution

Run Single Test Class:

sf apex run test --class-names MyClassTest --code-coverage --result-format json --output-dir test-results --target-org [alias]

Run All Tests:

sf apex run test --test-level RunLocalTests --code-coverage --result-format json --output-dir test-results --target-org [alias]

Run Specific Methods:

sf apex run test --tests MyClassTest.testMethod1 --tests MyClassTest.testMethod2 --code-coverage --result-format json --target-org [alias]

Run Test Suite:

sf apex run test --suite-names MySuite --code-coverage --result-format json --target-org [alias]

Phase 3: Results Analysis

Parse test-results JSON:

Read: test-results/test-run-id.json

Coverage Summary Output:

📊 TEST EXECUTION RESULTS
════════════════════════════════════════════════════════════════

Test Run ID: 707xx0000000000
Org: my-sandbox
Duration: 45.2s

SUMMARY
───────────────────────────────────────────────────────────────
✅ Passed:    42
❌ Failed:    3
⏭️ Skipped:   0
📈 Coverage: 78.5%

FAILED TESTS
───────────────────────────────────────────────────────────────
❌ AccountServiceTest.testBulkInsert
   Line 45: System.AssertException: Assertion Failed
   Expected: 200, Actual: 199

❌ LeadScoringTest.testNullHandling
   Line 23: System.NullPointerException: Attempt to de-reference null

❌ OpportunityTriggerTest.testValidation
   Line 67: System.DmlException: FIELD_CUSTOM_VALIDATION_EXCEPTION

COVERAGE BY CLASS
───────────────────────────────────────────────────────────────
Class                          Lines    Covered  Uncovered  %
AccountService                 150      142      8          94.7% ✅
LeadScoringService            85       68       17         80.0% ✅
OpportunityTrigger            45       28       17         62.2% ⚠️
ContactHelper                 30       15       15         50.0% ❌

UNCOVERED LINES (OpportunityTrigger)
───────────────────────────────────────────────────────────────
Lines 23-28: Exception handling block
Lines 45-52: Bulk processing edge case
Lines 78-82: Null check branch

Phase 4: Agentic Test-Fix Loop

When tests fail, automatically:

┌─────────────────────────────────────────────────────────────────┐
│                    AGENTIC TEST-FIX LOOP                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  1. Parse failure message and stack trace                        │
│  2. Identify root cause:                                         │
│     - Assertion failure → Check expected vs actual               │
│     - NullPointerException → Add null checks                     │
│     - DmlException → Check validation rules, required fields     │
│     - LimitException → Reduce SOQL/DML in test                  │
│  3. Read the failing test class                                  │
│  4. Read the class under test                                    │
│  5. Generate fix using sf-apex skill                             │
│  6. Re-run the specific failing test                             │
│  7. Repeat until passing (max 3 attempts)                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Failure Analysis Decision Tree:

Error Type Root Cause Auto-Fix Strategy
System.AssertException Wrong expected value or logic bug Analyze assertion, check if test or code is wrong
System.NullPointerException Missing null check or test data Add null safety or fix test data setup
System.DmlException Validation rule, required field, trigger Check org config, add required fields to test data
System.LimitException Governor limit hit Refactor to use bulkified patterns
System.QueryException No rows returned Add test data or adjust query
System.TypeException Type mismatch Fix type casting or data format

Auto-Fix Command:

Skill(skill="sf-apex", args="Fix failing test [TestClassName].[methodName] - Error: [error message]")

Phase 5: Coverage Improvement

If coverage < threshold:

  1. Identify Uncovered Lines:
sf apex run test --class-names MyClassTest --code-coverage --detailed-coverage --result-format json --target-org [alias]
  1. Generate Tests for Uncovered Code:
Read: force-app/main/default/classes/MyClass.cls (lines 45-52)

Then use sf-apex to generate test methods targeting those lines.

  1. Bulk Test Validation:
Skill(skill="sf-data", args="Create 251 [ObjectName] records for bulk testing")
  1. Re-run with New Tests:
sf apex run test --class-names MyClassTest --code-coverage --result-format json --target-org [alias]

Best Practices (120-Point Scoring)

Category Points Key Rules
Test Coverage 25 90%+ class coverage; all public methods tested; edge cases covered
Assertion Quality 25 Assert class used; meaningful messages; positive AND negative tests
Bulk Testing 20 Test with 251+ records; verify no SOQL/DML in loops under load
Test Data 20 Test Data Factory used; no hardcoded IDs; @TestSetup for efficiency
Isolation 15 SeeAllData=false; no org dependencies; mock external callouts
Documentation 15 Test method names describe scenario; comments for complex setup

Scoring Thresholds:

⭐⭐⭐⭐⭐ 108-120 pts (90%+)  → Production Ready
⭐⭐⭐⭐   96-107 pts (80-89%) → Good, minor improvements
⭐⭐⭐    84-95 pts  (70-79%) → Acceptable, needs work
⭐⭐      72-83 pts  (60-69%) → Below standard
⭐        <72 pts   (<60%)   → BLOCKED - Major issues

⛔ TESTING GUARDRAILS (MANDATORY)

BEFORE running tests, verify:

Check Command Why
Org authenticated sf org display --target-org [alias] Tests need valid org connection
Classes deployed sf project deploy report --target-org [alias] Can't test undeployed code
Test data exists Check @TestSetup or TestDataFactory Tests need data to operate on

NEVER do these:

Anti-Pattern Problem Correct Pattern
@IsTest(SeeAllData=true) Tests depend on org data, break in clean orgs Always SeeAllData=false (default)
Hardcoded Record IDs IDs differ between orgs Query or create in test
No assertions Tests pass without validating anything Assert every expected outcome
Single record tests only Misses bulk trigger issues Always test with 200+ records
Test.startTest() without Test.stopTest() Async code won't execute Always pair start/stop

CLI Command Reference

Test Execution Commands

Command Purpose Example
sf apex run test Run tests See examples above
sf apex get test Get async test status sf apex get test --test-run-id 707xx...
sf apex list log List debug logs sf apex list log --target-org alias
sf apex tail log Stream logs real-time sf apex tail log --target-org alias

Useful Flags

Flag Purpose
--code-coverage Include coverage in results
--detailed-coverage Line-by-line coverage (slower)
--result-format json Machine-parseable output
--output-dir Save results to directory
--synchronous Wait for completion (default)
--test-level RunLocalTests All tests except managed packages
--test-level RunAllTestsInOrg Every test including packages

Test Patterns & Templates

Pattern 1: Basic Test Class

Use template: templates/basic-test.cls

@IsTest
private class AccountServiceTest {

    @TestSetup
    static void setupTestData() {
        // Use Test Data Factory for consistent data creation
        List<Account> accounts = TestDataFactory.createAccounts(5);
        insert accounts;
    }

    @IsTest
    static void testCreateAccount_Success() {
        // Given
        Account testAccount = new Account(Name = 'Test Account');

        // When
        Test.startTest();
        Id accountId = AccountService.createAccount(testAccount);
        Test.stopTest();

        // Then
        Assert.isNotNull(accountId, 'Account ID should not be null');
        Account inserted = [SELECT Name FROM Account WHERE Id = :accountId];
        Assert.areEqual('Test Account', inserted.Name, 'Account name should match');
    }

    @IsTest
    static void testCreateAccount_NullInput_ThrowsException() {
        // Given
        Account nullAccount = null;

        // When/Then
        try {
            Test.startTest();
            AccountService.createAccount(nullAccount);
            Test.stopTest();
            Assert.fail('Expected IllegalArgumentException was not thrown');
        } catch (IllegalArgumentException e) {
            Assert.isTrue(e.getMessage().contains('cannot be null'),
                'Error message should mention null: ' + e.getMessage());
        }
    }
}

Pattern 2: Bulk Test (251+ Records)

Use template: templates/bulk-test.cls

@IsTest
static void testBulkInsert_251Records() {
    // Given - 251 records crosses the 200-record batch boundary
    List<Account> accounts = TestDataFactory.createAccounts(251);

    // When
    Test.startTest();
    insert accounts;  // Triggers fire in batches of 200, then 51
    Test.stopTest();

    // Then
    Integer count = [SELECT COUNT() FROM Account];
    Assert.areEqual(251, count, 'All 251 accounts should be inserted');

    // Verify no governor limits hit
    Assert.isTrue(Limits.getQueries() < 100,
        'Should not approach SOQL limit: ' + Limits.getQueries());
}

Pattern 3: Mock Callout Test

Use template: templates/mock-callout-test.cls

@IsTest
private class ExternalAPIServiceTest {

    // Mock class for HTTP callouts
    private class MockHttpResponse implements HttpCalloutMock {
        public HttpResponse respond(HttpRequest req) {
            HttpResponse res = new HttpResponse();
            res.setStatusCode(200);
            res.setBody('{"success": true, "data": {"id": "12345"}}');
            return res;
        }
    }

    @IsTest
    static void testCallExternalAPI_Success() {
        // Given
        Test.setMock(HttpCalloutMock.class, new MockHttpResponse());

        // When
        Test.startTest();
        String result = ExternalAPIService.callAPI('test-endpoint');
        Test.stopTest();

        // Then
        Assert.isTrue(result.contains('success'), 'Response should indicate success');
    }
}

Pattern 4: Test Data Factory

Use template: templates/test-data-factory.cls

@IsTest
public class TestDataFactory {

    public static List<Account> createAccounts(Integer count) {
        List<Account> accounts = new List<Account>();
        for (Integer i = 0; i < count; i++) {
            accounts.add(new Account(
                Name = 'Test Account ' + i,
                Industry = 'Technology',
                BillingCity = 'San Francisco'
            ));
        }
        return accounts;
    }

    public static List<Contact> createContacts(Integer count, Id accountId) {
        List<Contact> contacts = new List<Contact>();
        for (Integer i = 0; i < count; i++) {
            contacts.add(new Contact(
                FirstName = 'Test',
                LastName = 'Contact ' + i,
                AccountId = accountId,
                Email = 'test' + i + '@example.com'
            ));
        }
        return contacts;
    }

    // Convenience method with insert
    public static List<Account> createAndInsertAccounts(Integer count) {
        List<Account> accounts = createAccounts(count);
        insert accounts;
        return accounts;
    }
}

Agentic Test-Fix Loop Implementation

How It Works

When the agentic loop is enabled, sf-testing will:

  1. Run tests and capture results
  2. Parse failures to identify error type and location
  3. Read source files (test class + class under test)
  4. Analyze root cause using the decision tree above
  5. Generate fix by invoking sf-apex skill
  6. Re-run failing test to verify fix
  7. Iterate until passing or max attempts (3)

Example Agentic Flow

User: "Run tests for AccountService with auto-fix enabled"

Claude:
1. sf apex run test --class-names AccountServiceTest --code-coverage --result-format json
2. Parse results: 1 failure - testBulkInsert line 45 NullPointerException
3. Read AccountServiceTest.cls (line 45 context)
4. Read AccountService.cls (trace the null reference)
5. Identify: Missing null check in AccountService.processAccounts()
6. Skill(sf-apex): Add null safety to AccountService.processAccounts()
7. Deploy fix
8. Re-run: sf apex run test --tests AccountServiceTest.testBulkInsert
9. ✅ Passing! Report success.

Cross-Skill Integration

Skill When to Use Example
sf-apex Generate test classes, fix failing code Skill(skill="sf-apex", args="Create test class for LeadService")
sf-data Create bulk test data (251+ records) Skill(skill="sf-data", args="Create 251 Leads for bulk testing")
sf-deploy Deploy test classes to org Skill(skill="sf-deploy", args="Deploy tests to sandbox")
sf-debug Analyze failures with debug logs Skill(skill="sf-debug", args="Analyze test failure logs")

Common Test Failures & Fixes

Failure Likely Cause Fix
MIXED_DML_OPERATION User + non-setup object in same transaction Use System.runAs() or separate transactions
CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY Trigger or flow error Check trigger logic with debug logs
REQUIRED_FIELD_MISSING Test data incomplete Add required fields to TestDataFactory
DUPLICATE_VALUE Unique field conflict Use dynamic values or delete existing
FIELD_CUSTOM_VALIDATION_EXCEPTION Validation rule fired Meet validation criteria in test data
UNABLE_TO_LOCK_ROW Record lock conflict Use FOR UPDATE or retry logic

Dependencies

Required: Target org with sf CLI authenticated Recommended: sf-apex (for auto-fix), sf-data (for bulk test data), sf-debug (for log analysis)

Install: /plugin install github:Jaganpro/sf-skills/sf-testing


Documentation

Document Description
testing-best-practices.md General testing guidelines
cli-commands.md SF CLI test commands
mocking-patterns.md Mocking vs Stubbing, DML mocking, HttpCalloutMock
performance-optimization.md Fast tests, reduce execution time

Templates

Template Description
basic-test.cls Standard test class with Given-When-Then
bulk-test.cls 251+ record bulk testing
mock-callout-test.cls HTTP callout mocking
test-data-factory.cls Reusable test data creation
dml-mock.cls DML abstraction for 35x faster tests
stub-provider-example.cls StubProvider for dynamic behavior

Credits

See CREDITS.md for acknowledgments of community resources that shaped this skill.


License

MIT License. See LICENSE file. Copyright (c) 2024-2025 Jag Valaiyapathy