
Sf Testing
Scaffold Salesforce Apex test classes with TestSetup, positive/negative cases, and a 90%+ coverage goal using the Test Data Factory pattern.
Overview
SF Testing is an agent skill for the Ship phase that generates structured Salesforce Apex test class templates targeting 90%+ coverage with factory-based setup.
Install
npx skills add https://github.com/jaganpro/sf-skills --skill sf-testingWhat is this skill?
- Opinionated Apex test skeleton with @TestSetup and Test Data Factory hooks
- Separates positive, negative, and bulk test sections in the template
- Documents Given/When/Then style blocks inside each test method
- States a 90%+ coverage target in the class header
- Uses naming pattern testMethodUnderTest_ValidInput_Success for traceability
- 90%+ stated coverage target in test class header
Adoption & trust: 1.3k installs on skills.sh; 418 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have Apex logic on a Salesforce org but lack consistent test classes that cover positive, negative, and bulk paths before deploy.
Who is it for?
Solo Salesforce devs and small SI teams standardizing Apex tests on Claude Code, Cursor, or Codex before sandboxes or production pushes.
Skip if: Non-Salesforce stacks or teams that only need UI or integration tests outside Apex.
When should I use this skill?
When authoring or expanding Salesforce Apex tests that need TestSetup, factory data, and positive/negative/bulk sections.
What do I get? / Deliverables
You get deployment-ready @IsTest classes with shared setup and named scenarios so agents can fill assertions and raise coverage systematically.
- Apex @IsTest class file with structured test methods
- Documented coverage-oriented test scenarios
Recommended Skills
Journey fit
Apex unit tests gate Salesforce deployments and production confidence, which sits in Ship testing rather than initial feature coding. The skill outputs @IsTest classes and coverage-oriented scenarios—the core Ship testing shelf for CRM extensions.
How it compares
Apex test class template skill—not a full Salesforce CI pipeline or org-wide test runner.
Common Questions / FAQ
Who is sf-testing for?
Salesforce builders who write Apex and need repeatable test scaffolding with factory setup and coverage-minded structure.
When should I use sf-testing?
In Ship testing when adding coverage for new triggers, services, or batches, or refactoring legacy tests before a release.
Is sf-testing safe to install?
It is a code template skill; review the Security Audits panel on this Prism page and scan generated tests before running in production orgs.
SKILL.md
READMESKILL.md - Sf Testing
/** * @description Test class for {{ClassName}} * Tests core functionality with positive, negative, and bulk scenarios. * @author {{Author}} * @created {{Date}} * @coverage Target: 90%+ */ @IsTest private class {{ClassName}}Test { // ═══════════════════════════════════════════════════════════════════════════ // TEST DATA SETUP // ═══════════════════════════════════════════════════════════════════════════ @TestSetup static void setupTestData() { // Create test data using Test Data Factory pattern // This data is available to all test methods and rolled back after each List<{{ObjectName}}> records = TestDataFactory.create{{ObjectName}}s(5); insert records; } // ═══════════════════════════════════════════════════════════════════════════ // POSITIVE TESTS // ═══════════════════════════════════════════════════════════════════════════ /** * @description Tests successful {{methodUnderTest}} with valid input */ @IsTest static void test{{MethodUnderTest}}_ValidInput_Success() { // ───────────────────────────────────────────────────────────────────── // GIVEN - Set up test conditions // ───────────────────────────────────────────────────────────────────── {{ObjectName}} testRecord = [SELECT Id, Name FROM {{ObjectName}} LIMIT 1]; // TODO: Add any additional setup needed // ───────────────────────────────────────────────────────────────────── // WHEN - Execute the method under test // ───────────────────────────────────────────────────────────────────── Test.startTest(); {{ReturnType}} result = {{ClassName}}.{{methodUnderTest}}(testRecord); Test.stopTest(); // ───────────────────────────────────────────────────────────────────── // THEN - Verify expected outcomes // ───────────────────────────────────────────────────────────────────── Assert.isNotNull(result, 'Result should not be null'); // TODO: Add specific assertions for expected values // Assert.areEqual(expectedValue, result, 'Result should match expected value'); } // ═══════════════════════════════════════════════════════════════════════════ // NEGATIVE TESTS // ═══════════════════════════════════════════════════════════════════════════ /** * @description Tests {{methodUnderTest}} throws exception with null input */ @IsTest static void test{{MethodUnderTest}}_NullInput_ThrowsException() { // ───────────────────────────────────────────────────────────────────── // GIVEN - Null input // ───────────────────────────────────────────────────────────────────── {{ObjectName}} nullRecord = null; // ───────────────────────────────────────────────────────────────────── // WHEN/THEN - Verify exception is thrown // ───────────────────────────────────────────────────────────────────── try { Test.startTest(); {{ClassName}}.{{methodUnderTest}}(nullRecord); Test.stopTest(); Assert.fail('Expected exception was not thrown'); } catch (IllegalArgumentException e) { Assert.isTrue( e.getMessage().containsIgnoreCase('null') || e.getMessage().containsIgnoreCase('required'), 'Error message should indicate null/required issue: ' + e.getMessage() ); } } /** * @description Tests {{methodUnderTest}} handles invalid data gracefully */ @IsTest static void test{{MethodUnderTest}}_InvalidData_ReturnsError() { // ───────────────────────────────────────────────────────────────────── // GIVEN - Invalid input data // ───────────────────────────────────────────────────────────────────── {{ObjectName}} invalidRecord = new {{ObjectName}}( // TODO: Set inval