How-to

How to run Apex tests locally

Install renmy runtime and run your existing test suite on your laptop, with no scratch org, no DevHub, and no Docker. It works on the SFDX project you already have and takes about five minutes.

Short version

Install the binary, cd into your SFDX project, run renmy test "*". If your project has a standard layout and isn't using features renmy runtime doesn't yet implement, the suite that runs in your org runs on your laptop.

What you need

  • An SFDX project, with the same force-app/main/default layout you'd push to an org.
  • macOS, Linux, or Windows. No JVM, Docker, or Postgres install is needed; the embedded database ships with the binary.
  • 5 minutes.

Step 1: Install renmy runtime

One line, no admin required:

bash
# macOS / Linux
curl -sSL https://renmy.net/install.sh | bash

# Windows (PowerShell)
iwr -useb https://renmy.net/install.ps1 | iex

Verify the install:

bash
renmy --version

Step 2: Run the doctor once

renmy doctor looks at your project, validates the layout, and lists anything it needs you to set up. On a clean SFDX project, it usually reports green and you skip the rest of this section.

bash
cd path/to/your/sfdx-project
renmy doctor

Step 3: Run your tests

Same command structure as the Salesforce CLI, but local:

bash
# Run everything
renmy test "*"

# Run a specific test class
renmy test "OrderServiceTest"

# Run a single method
renmy test "OrderServiceTest.testDiscountApplies"

# Glob patterns
renmy test "Order*Test.*"

Output mirrors what you'd expect from sf apex run test: pass/fail counts, failure messages, stack traces, code coverage. Failures point at the file and line.

Step 4: Re-run on save with watch mode

renmy test:watch re-runs affected tests on save. It tracks which classes each test exercises, so editing a single trigger only re-runs the tests that touch it.

bash
renmy test:watch

Watch mode is a Pro feature. The Free tier supports one-shot runs and the full Dev UI.

The same tests in CI

Same binary, same project, JUnit XML and Cobertura XML output for whatever CI you use:

yaml
# .github/workflows/test.yml
name: Apex Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: curl -sSL https://renmy.net/install.sh | bash
      - run: renmy test "*" --results-xml results.xml --coverage-report cobertura.xml
        env:
          NIMBUS_LICENSE_KEY: ${{ secrets.NIMBUS_LICENSE_KEY }}
      - uses: actions/upload-artifact@v4
        with: { name: test-results, path: results.xml }

Test runs in CI need a licence key from the portal, stored as the NIMBUS_LICENSE_KEY secret. The free tier does not run tests in CI; pricing lists the plans that do.

For a deeper walkthrough see Apex CI without a connected org.

Common gotchas

  • Multi-currency org behaviour. Set nimbus.org.features=MultiCurrency in nimbus.properties (or pass --feature MultiCurrency) so CurrencyIsoCode fields and UserInfo.isMultiCurrencyOrganization() behave the way they do in a multi-currency org. It is off by default, like a new org.
  • Managed package types. If your code references a managed package, pull stubs for it with renmy stub pull --org <alias> --namespaces <namespace>. See Managed Packages.
  • Org defaults. Custom settings need seeding. Add them in nimbus.properties with nimbus.seed.org-default.MySetting__c=... rather than relying on @testSetup boilerplate everywhere.

Next steps

If your suite is green, you no longer need an org to run it. If something failed, the failures show which platform features still need a scratch org. The doctor output and the failure trace both name the missing capability.