Apex Test List

September 24, 2026 · View on GitHub

NPM Downloads/week GitHub Marketplace License Mutation testing badge Codecov

A plugin that generates a list of tests that your automated process should run, so you can save time by not running all tests in your Salesforce org and avoid specifying them manually. Available as a Salesforce CLI plugin for any provider, and as a native GitHub Action for GitHub Actions users who want to skip installing the CLI.

Table of Contents

Install

Simply install the plugin using sf:

sf plugins install apextestlist

Usage

This tool identifies Apex tests using either 3 Apex annotations or a separate metadata filter.

1. @Tests: (Custom Comment Annotation)

Classes can specify which tests should be run using a comment with the @Tests: prefix. Multiple tests can be separated by commas, spaces, or both.

// @Tests: SampleTest, SuperSampleTest
public class Sample {
  // ...
}

This means that SampleTest and SuperSampleTest should be executed when Sample.cls is modified.

2. @TestSuites: (Custom Comment Annotation)

Test suites can be specified using the @TestSuites: prefix. Multiple suites can be separated by commas or spaces.

// @TestSuites: SampleSuite SampleSuite2
public class Sample {
  // ...
}

This tells the tool to include all tests contained in SampleSuite and SampleSuite2.

3. @isTest (Apex Annotation)

The tool also detects all Apex classes marked with the @isTest annotation. Any class or method marked with this annotation is assumed to be a test.

@isTest
private class SampleTest {
  // This test will be included automatically
}

4. .test-dependencies.yml (Centralized Metadata Filter)

Instead of using the Apex annotations described previously, you can use this plugin to determine Apex tests with specific Salesforce metadata.

This approach is designed to work seamlessly with the -x/--manifest flag using a manifest file generated by the sfdx-git-delta plugin.

  1. Create a .test-dependencies.yml file in the root of your project.
  2. Map test classes to metadata entries (in MetadataType:MetadataMember format).
    1. Use wildcards (*) to match all children under a metadata namespace (e.g., all custom fields in an object).
    2. The plugin will fail if the entries in the YAML don't match the expected format.
MyFooTest:
  - CustomField:Account__c.field__c
  - Flow:OpportunityFlowX
  - ValidationRule:Account.RequiredEmail
  - CustomField:Opportunity__c.*

MyBarTest:
  - CustomObject:Lead__c
  - Flow:LeadFlowY
  1. Run this plugin's command with the filter-by-metadata/-m flag and the -x/--manifest flag.
sf apextests list -x package/package.xml -m

Running the Tool

To generate a test list, run the command in any Salesforce DX project:

sf apextests list --format sf

Example output:

--tests SampleTest SuperSampleTest Sample2Test SuperSample2Test

This command is useful in CI/CD pipelines, dynamically generating the test list for deployments:

sf project deploy start --test-level RunSpecifiedTests $(sf apextests list)

The final deployment command would look like:

sf project deploy start --test-level RunSpecifiedTests --tests SampleTest SuperSampleTest Sample2Test SuperSample2Test SampleTriggerTest

Explicit Test Level for Deploy and Validate

When you append sf apextests list output (or the GitHub Action command output) to sf project deploy start or sf project deploy validate, explicitly pass --test-level RunSpecifiedTests. Without it, the deploy or validation can fail immediately with:

Error (1): INVALID_OPERATION: runTests can only be used with a testLevel of RunSpecifiedTests

Salesforce CLI documentation suggests that providing --tests should infer RunSpecifiedTests, but behavior differs between deploy subcommands. In practice, sf project deploy validate does not set the level implicitly (a fix is tracked in salesforcecli/plugin-deploy-retrieve#1650). Using an explicit test level works for both start and validate.

With a manifest:

sf project deploy start -x package/package.xml --test-level RunSpecifiedTests $(sf apextests list -x package/package.xml)

If no test methods are found, the command output will be empty and will present this warning:

No test methods found

Handling Missing Tests

By default, this tool does not verify if the test methods found exist in the project. To enable warnings for missing tests, use:

sf apextests list --ignore-missing-tests

This will print warnings for missing tests and exclude them from the output.

Handling Missing Annotations

By default, the tool will print a warning for each file scanned that is missing any annotation.

File "Sample.cls" does not contain @tests, @testsuites, or @istest annotations

To remove these warnings from the terminal, use:

sf apextests list --no-warnings

Failing When No Tests Are Found

By default, the command exits with code 0 even when no test methods are found — it just prints an empty result and a warning. To have it fail the run instead, use:

sf apextests list --fail-on-empty

Combined with -x/--manifest, this is manifest-aware: it only fails when the manifest actually declares ApexClass/ApexTrigger members but no tests could be resolved for them. If the manifest contains no Apex at all (e.g., a delta package with only non-Apex metadata), the command still exits 0, since there's nothing to test.

# Exits 0: package.xml has no ApexClass/ApexTrigger members, nothing to check
sf apextests list --manifest package.xml --fail-on-empty

# Exits 1: package.xml declares Apex, but no tests were found for it
sf apextests list --manifest package.xml --fail-on-empty

This is useful as a CI guardrail: skip the deploy/validate step cleanly when a manifest has no Apex changes, but fail loudly when Apex changed and no tests cover it.

The GitHub Action's fail-on-empty input behaves the same way — see Inputs.

GitHub Action

For GitHub Actions, this is also available as a native Action — no sf CLI or plugin install required:

- name: List Apex tests
  id: list
  uses: wisefoxme/apex-test-list@v1
  with:
    manifest: package.xml
    ignore-missing-tests: 'true'

- name: Deploy with the specified tests
  run: sf project deploy start -x package.xml --test-level RunSpecifiedTests ${{ steps.list.outputs.command }}

Inputs

InputDescriptionRequiredDefault
formatOutput format. Available options: sf (default), sfdx, or csv.Nosf
manifestPath to a manifest XML file (package.xml). When set, only classes/triggers declared in it are considered.No
ignore-missing-testsIgnore test methods that are not found in any local package directory.Nofalse
ignore-package-directoryDirectory to ignore when searching for test annotations, one per line.No
no-warningsDo not print warnings for each Apex file missing annotations.Nofalse
filter-by-metadataOnly include tests that explicitly declare metadata dependencies matching changed metadata. Requires manifest.Nofalse
fail-on-emptyFail the action if no test methods are found. Manifest-aware when manifest is set — see Failing When No Tests Are Found.Nofalse

Outputs

OutputDescription
testsNewline-separated list of Apex test class names.
test-countNumber of Apex test class names found.
commandThe formatted test list, ready to append to a Salesforce CLI deploy/validate command.
warningsNewline-separated list of warnings emitted while listing tests, if any.

Command Reference

USAGE
  $ sf apextests list -f <value> -x <value> -s -n -d <value> -m -e [--json]

FLAGS
  -f, --format=<value>            Output format. Available options:
                                    - `sf` (default): CLI-friendly test list
                                    - `csv`: Comma-separated values
  -x, --manifest=<value>          Manifest XML file (package.xml) to filter test annotations.
  -s, --ignore-missing-tests      [default: false] Ignore test methods that are not found in any local package directories.
  -n, --no-warnings               [default: false] Do not print warnings for each file missing annotations.
  -d, --ignore-package-directory  Ignore a package directory when looking for test annotations.
                                  Should match how they are declared in "sfdx-project.json".
                                  Can be declared multiple times.
  -m, --filter-by-metadata        [default: false] When enabled with `manifest`, test selection is based on metadata changes (e.g., Flow, CustomObject) rather than Apex annotations.
  -e, --fail-on-empty             [default: false] Exit with code 1 if no test methods are found. With `--manifest`, exits 0 instead when the manifest has no ApexClass/ApexTrigger members.

GLOBAL FLAGS
  --json  Format output as JSON.

EXAMPLES
  List all test annotations found in package directories in Salesforce CLI format:

    $ sf apextests list --format sf

  List all test annotations in CSV format:

    $ sf apextests list --format csv

  List test annotations only for Apex classes/triggers in a manifest file:

    $ sf apextests list --format sf --manifest package.xml

  List test annotations only if they exist in the package directories:

    $ sf apextests list --format sf --ignore-missing-tests

  Exclude annotations found in the "force-app" directory:

    $ sf apextests list -d "force-app"

  Fail with exit code 1 if a manifest declares Apex but no tests are found for it (exit 0 if the manifest has no Apex at all):

    $ sf apextests list --format sf --manifest package.xml --fail-on-empty

  List test annotations without printing warnings for each file missing annotations:

    $ sf apextests list -n

Issues

If you encounter any issues or would like to suggest features, please create an issue.

License

This project is licensed under the BSD-3 license. Please see the LICENSE file for details.