Skip to content

reference

Run Apex tests locally ​

glade test discovers Apex test classes from a Salesforce DX project, compiles supported code, runs tests in the local VM, and reports stable outcomes. It uses the same project loader, parser, semantic analyzer, storage, DML, SOQL, trigger, and limit stack as the rest of the CLI.

The RefinementServiceTest.opensFile selectors below match the maintained editor walkthrough. Your project must contain that class and method, or you must substitute its actual test names. For a self-contained first run, use SampleTest.adds in the quickstart. The terminal output below is illustrative; timings are not a benchmark.

Run all tests ​

bash
glade test --project .
text
Glade test

1 selected, 1 passed, 0 failed

Selected: 1
Passed:   1
Failed:   0
Runtime:  420ms

  ✓  RefinementServiceTest.opensFile  42ms

Next:
  glade test --watch
  glade test failed

Machine-readable output:

bash
glade test --project . --json

--json writes the versioned envelope described in Automation and JSON.

JUnit output for CI:

bash
mkdir -p reports
glade test --project . --junit reports/glade-junit.xml

Capture local telemetry ​

Write CPU and heap profiles for check or a local test run. A local one-shot test run can also write opt-in performance counters:

bash
mkdir -p reports
glade check --project . --cpu-profile reports/check.cpu.pprof --mem-profile reports/check.mem.pprof --perf-json reports/check.perf.json
glade test --project . --no-serve --no-cache --cpu-profile reports/test.cpu.pprof --mem-profile reports/test.mem.pprof --perf-json reports/test.perf.json

These local telemetry artifacts do not replace Salesforce validation. CPU and heap profiles capture the lifetime of the local command and may also profile daemon or watch mode; they are written when that command exits and cannot be used with --connect. --perf-json is for a local one-shot run and cannot be combined with daemon, watch, watch-once, connect, wizard, last-failed, or shard-plan-only modes.

Check performance JSON reports the project and semantic cache provenance. semanticCache.source records whether the exact result came from memory, disk, or build; related fields cover waits, safe-miss reasons, retained bytes, and evictions. Check counters also cover source reads, reused logical views, allocations, and garbage collection.

Test performance JSON adds an execution object with invocation arguments, requested and effective parallelism, method-parallel policy, GOMAXPROCS, disk cache policy, and execution mode. Its remaining counters cover cache phases and slow classes or methods. These versioned local artifacts contain project paths and, for tests, command arguments, so review them before sharing.

glade check and the test semantic gate keep exact results under .glade/semantic/. Use glade check --no-cache or test --no-cache to bypass semantic cache reads, writes, and memory reuse. Immutable source-generation validation still runs before a cached result is published or returned.

Filter tests ​

Run a test class:

bash
glade test --project . --class RefinementServiceTest

Run a single method (replace the example names with a test in your project):

bash
glade test --project . --class RefinementServiceTest --method opensFile

Use exact class and method selectors for the short inner loop. Then run the wider suite before shipping.

Use --parallelism to set the total worker budget. Method-level parallelism is enabled by default; within that fixed budget, the scheduler uses recorded class durations when available and shifts freed capacity to methods in the remaining classes. Use --no-parallel-methods only for tests that share mutable local state.

bash
glade test --project . --parallelism 8 --json

Split and balance suites ​

Use an exact class file, one class per line, when a wrapper already owns selection. Blank and # comment lines are ignored:

bash
glade test --project . --class-file test-classes.txt
glade test --project . --shard-count 4 --shard-index 0
glade test --project . \
  --shard-count 4 \
  --duration-history .glade/test-durations.json \
  --write-class-shards reports/test-shards
glade test --project . --test-timeout 2m

A hand-written class file must contain at least one class. An empty or comment-only file is a selector failure; JSON mode returns status=failed with problem.type=Selector and never widens the run to the whole suite. Generated empty shards contain # glade-empty-class-shard-v1; running one is an intentional no-op reported as status=empty with exit code 0. Both outcomes write requested --junit and --trace artifacts. Because no test runs, --perf-json, --cpu-profile, and --mem-profile are rejected for an empty class file instead of silently omitting their outputs.

Unfiltered, unsharded runs maintain .glade/test-durations.json. Duration history balances later shards; the assignment is deterministic for the same selected classes, shard count, and history. --write-class-shards writes shard-NNN.txt class lists and exits without running tests.

The per-test wall-clock cap defaults to 10 minutes and also applies to @TestSetup. Choose a Go duration such as 90s or 15m with GLADE_TEST_TIMEOUT; --test-timeout takes precedence over the environment, then the default. Invalid or negative settings are errors. 0 disables the per-test cap. This policy also applies to daemon, watch, and glade dev test/watch runs. CPU and governor limits are independent and unchanged. Timeout failures name the applied setting and explain how to raise or disable it. The VM checks cancellation every 64 Apex statements. A long native operation (such as a SOQL/DML scan, JSON conversion, regex or sort) can run beyond the cap before reaching the next cancellation check.

Keep an explicit cap in CI:

bash
glade test --test-timeout 2m

For a longer local run or to disable the cap:

bash
GLADE_TEST_TIMEOUT=15m glade test
GLADE_TEST_TIMEOUT=0 glade test

With a finite memory limit, --gc-aggressive sets GOGC=off so Go's soft memory limit drives garbage collection instead of a heap-growth percentage. glade test uses a 4 GiB default limit and honors an explicit GOMEMLIMIT. If the effective limit is unlimited (GOMEMLIMIT=off or Go's maximum int64 limit), the flag falls back to GOGC=50, keeping heap-growth collection enabled. The memory limit is a soft target for Go runtime memory, not a hard process RSS cap. Use --no-serve to apply these settings to the process executing the tests; an existing test server retains its own startup GC settings.

Limit modes ​

Glade supports limit modes for local execution. strict enforces supported governor limits closer to Salesforce behavior. permissive keeps the local loop moving when a project depends on unfinished areas.

bash
glade test --project . --limit-mode strict
glade test --project . --limit-mode permissive --json

Use strict for gates. Use permissive when you are carving into unsupported terrain and want the next useful diagnostic.

Watch mode ​

Run tests on file changes:

bash
glade test --project . --watch

Run the initial suite, or the explicit class and method selection, and exit:

bash
glade test --project . --watch-once

--watch-once does not wait for a change or select tests from a git diff. Use glade test changed --since <base-ref> for a single run selected by git changes.

Run the daemon-backed watch loop:

bash
glade test --project . --daemon --watch

Eligible Apex-only edits update incrementally. Metadata, configuration, project-topology, uncertain, and recovery changes use an authoritative rebuild. Selection remains conservative and runs the full suite when Glade cannot prove a narrower set is safe.

Run tests affected by a git ref without remembering the lower-level flag:

bash
glade test changed --project . --since HEAD

Rerun failures from the last completed run:

bash
glade test failed --project .
glade test --project . --last-failed

Print the next likely loop commands without running tests:

bash
glade test --project . --wizard

Local preview surfaces ​

LWC and Visualforce preview have their own workflow and product pages.

Warm startup across CLI runs ​

Large projects rebuild local org state and helper compilation on cold start. Eligible glade test modes write that harness to .glade/test/startup.meta.json plus a hashed payload and reload it when fingerprint checks pass. One-shot parallel-method runs with more than one effective worker deliberately bypass restored-runtime disk caching to protect test isolation; glade test --wizard prints the effective policy.

Semantic analysis is independent. glade check and glade test can reuse an exact result under .glade/semantic/ from memory, disk, or build even when the restored-runtime payload is bypassed. Exact source, companion metadata, schema, dependency, analyzer and platform ABI, and option identity must match.

Test Startup Cache explains when the cache is created, how it stays up to date, when it can be wrong, and how to recover.

bash
glade test serve --project .
glade test daemon status --project .
glade test --project . --class RefinementServiceTest
glade test daemon stop --project .
glade test clear-cache --project .
glade test --project . --no-cache --class RefinementServiceTest

glade test clear-cache removes the startup and semantic caches for the project. Test --no-cache bypasses the startup and semantic caches, including semantic memory reuse, when debugging harness or analysis issues. A separately running test server keeps its own memory until stopped or restarted.

CI pattern ​

A small CI gate can check the project, run affected tests, then write JUnit output for test reporting. Replace <base-ref> with the intended existing comparison ref and ensure it is available in the checkout:

bash
glade check --project . --json
glade test changed --project . --since <base-ref> --json --no-progress
mkdir -p reports
glade test --project . --junit reports/glade-junit.xml

Saved run artifacts and CI annotations are covered in Add Glade to CI.

Running user and limits ​

The default local running user uses America/Los_Angeles. Local Datetime construction, date components, and format() follow the current user's time zone; GMT methods keep GMT semantics. Set TimeZoneSidKey explicitly on users you insert for System.runAs rather than relying on a default.

When the project has no profile metadata, Glade keeps that running user permissive for custom-object CRUD and field-level security. Salesforce's Standard User can have no access to a new custom object. In the captured restricted-user cases, native describe access is false, user-mode DML is denied, and API 67 plain INSERT without grants raises System.SecurityException (the captured API 62 insert succeeds).

Three captured differences are intentional: the no-profile Glade default stays permissive; Security.stripInaccessible(CREATABLE) retains Name where native Salesforce removes it; and an API 67 plain COUNT() denial reports System.QueryException locally versus System.SecurityException natively. Use test.permissionSets: [Access_Set] in glade.yml to assign a project's permission-set grants to the running test user. This does not select a profile or change the no-profile default. For restricted access, use a restricted profile and that user's own assignments under System.runAs.

The checked Winter '27 Limits.getLimitHeapSize() values are 10,000,000 bytes for synchronous Apex (including tests and Scheduled Apex) and 25,000,000 for Queueable, future, and Batchable execution. Local heap usage is an approximation; these reported caps do not establish exact hosted allocation accounting.

During Test.stopTest(), ordinary Apex exceptions from platform-event subscribers do not fail the enclosing test. Writes made before the exception remain visible. Retry/checkpoint handling and internal VM errors have separate paths; this rule does not suppress every asynchronous failure.

Outcomes ​

Local test runs separate assertion failures from load errors, compile errors, unsupported features, and internal errors. That split matters. A failing assertion means the test ran and failed. An unsupported feature means the runtime stopped at a known unsupported Salesforce API. Unsupported test outcomes count as errors and exit with code 1.

A compile error blocks only the classes it reaches. A class with a compile error, and every class that references it directly or through other classes, is excluded and its tests report compile_error; all other tests run. A local variable, parameter, field, method, inner class, or setter value that shares a class's name is not a reference, and neither is a Type.forName string. A class with errors of its own reports them, even when it also references an invalid class. The console, JUnit, GitHub annotation, and HTML reports, and the JSON excludedClasses list, name each excluded class, the class it depends on, and the root class with the error. The run exits with code 1 while any class is excluded, even when every test that ran passed. Triggers referencing an invalid class are excluded too; unrelated tests still run. An attributable missing-package dependency excludes static references to its namespace and their dependents. Unattributed errors and class metadata errors, such as an unsupported apiVersion, retain the whole-project fallback.

Read the JSON summary counts: total, passed, failed, errors, skipped, unsupported, and excludedClasses. A run with zero selected tests can exit with code 0; it does not provide test execution evidence. Run an explicit relevant test or suite if an affected selection is empty. JSON status=partial means at least one selected test was skipped without a failure; inspect the skipped cases before treating the run as CI evidence.

text
  ✓  RefinementServiceTest.opensFile  42ms
  ✗  RefinementServiceTest.testRejectsBlankFileRow  12ms

  RefinementServiceTest.testRejectsBlankFileRow
  System.AssertException: expected 1, got 0

  force-app/main/default/classes/RefinementServiceTest.cls:42

Check what Glade runs locally before relying on platform service APIs, exact hosted Visualforce behavior, live side effects, or REST behavior outside the checked local baseline.

Try it

Exercise the runtime your tests rely on - DML, triggers, and governor limits - in the local playground:

bash
glade playground --examples --addr 127.0.0.1:1789 --open

Glade is an independent project and is not affiliated with, sponsored by, or endorsed by Salesforce. Salesforce and Apex are trademarks of Salesforce, Inc. · Contributors · Security · Releases · Apache-2.0