Test Data

A TestDataFactory
built from your schema.

nimbus fixture Account Contact reads the schema your Salesforce Apex tests already run against and writes a create<SObject>() method per object, with the required fields filled in. Not a template you adapt - output that matches this org. Free.

Every Salesforce project ends up with a test data factory, and every one of them is written the same way: insert a record, read the REQUIRED_FIELD_MISSING, add a field, run it again. The information was in the schema the whole time. This command reads it.

The same schema your tests run against

Nimbus executes your tests against an embedded PostgreSQL shaped by your org's real describes. The factory generator reads that schema - not a bundled approximation of it, and not the object definitions in your repo. It is the reason the generated class compiles and inserts on the first try instead of the fourth.

Standard objects work with no setup: Nimbus ships their describes. Custom objects need one nimbus sync first - after that they generate exactly like standard objects, including their required fields and their picklist value sets.

1

Read the local schema

Nimbus already holds a describe for every object your tests run against. The generator reads that same schema - which fields are required, which are createable, what a picklist actually allows.

2

Fill what the schema vouches for

Required, createable fields get a literal of the right type. Picklists get a real value from the field's value set, because a restricted picklist rejects anything else. OwnerId is skipped - it populates itself on insert.

3

Follow the required lookups

A required lookup pulls its parent object into the factory even if you never named it, and the methods come out parents-first so they can be inserted in that order.

4

Say so when it cannot know

A picklist with no value set in the local schema, a field type with no sensible default, a required parent with no schema at all - each becomes a named TODO plus a warning, never a fabricated value.

What it actually prints

Three objects, one command. Account and Contact need one required field each. Contract needs a status - and an account to hang off.

Status is a restricted picklist, so the value comes from the field's own value set rather than a placeholder that would be rejected on insert.

The output is deterministic: the same project generates the same file every time, so regenerating after a schema change produces a diff you can actually review.

bash
# Print a factory for three objects
nimbus fixture Account Contact Contract

# Save it into the default package
nimbus fixture Contract --write

# Name it something else
nimbus fixture Contract --class BillingFactory --write
apex
@IsTest
public class TestDataFactory {

    static Account createAccount() {
        return new Account(
            Name = 'Test'
        );
    }

    static Contact createContact() {
        return new Contact(
            LastName = 'Test'
        );
    }

    static Contract createContract() {
        // TODO: required lookup AccountId (lookup to Account) — set after inserting its parent
        return new Contract(
            Status = 'In Approval Process'
        );
    }

    // Inserts the required parents, then returns an un-inserted Contract wired to them.
    static Contract createContractWithParents() {
        Account parent0 = createAccount();
        insert parent0;
        Contract record = createContract();
        record.AccountId = parent0.Id;
        return record;
    }
}

A parent Id is a decision, not a guess

Note that Account appears in the output above even though Contract needs it - and it would appear even if you had never typed it. A required lookup pulls its parent in, and the methods are emitted parents-first so the chain can be inserted in order.

But createContract() still leaves AccountId unset, with a TODO naming the field and the object it points at. That is deliberate. Which account a contract belongs to is a decision your test is making; a generator that silently picks one has made it for you, invisibly, in every test that calls the method.

createContractWithParents() is the explicit opt-in: it inserts a fresh parent and wires the child to it. You choose which one you want at the call site, and the choice is visible in the test.

apex
// I already have an account
Contract c = TestDataFactory.createContract();
c.AccountId = existingAccount.Id;
insert c;

// I just need a valid contract
Contract c = TestDataFactory
    .createContractWithParents();
insert c;
The edges are named, not smoothed over. A required lookup to the object's own type becomes a TODO rather than infinite recursion. A lookup cycle between two objects is reported as a warning instead of being broken at an arbitrary point. A required parent with no local schema becomes a named TODO plus a prompt to run nimbus sync - never a call to a method that was never generated, which would produce a factory that does not compile.

Three flags

The command has a small surface on purpose. Everything else it needs it reads from the schema.

--write

Save it instead of printing it

Writes the class and its -meta.xml into the project's default package and prints the path. Without it, the class goes to stdout - pipe it, diff it, or read it before you commit to anything.

--class

Name the generated class

Defaults to TestDataFactory. Set it when the name is taken, or when you want one factory per domain - nimbus fixture Contract --class BillingFactory.

--api-version

API version for the -meta.xml

Defaults to 62.0. Only used with --write, since stdout has no metadata file to stamp.

Also available: the global -o/--org and --profile flags, if the schema you want to generate from belongs to a different org or config profile than your default. Full reference at /docs/run-and-test#cmd-fixture.

Where it fits

nimbus fixture generates a starting point, not a test data strategy. It gets you a class that compiles and inserts; what you build on top of it is the part that matters, and the tradeoffs there are real ones.

We wrote up those tradeoffs separately - static factory methods against the builder pattern, when Test.loadData and a static resource beat both, and why a @testSetup block that creates everything for everyone tends to age badly: Apex test data factories.

Generation is also a reasonable answer to a factory that has drifted. Regenerate against the current schema, diff it against what you have, and the required fields somebody added in the org three months ago show up as a line in the diff rather than as a failing insert.

apex
@IsTest
private class ContractServiceTest {

    @TestSetup
    static void setup() {
        insert TestDataFactory
            .createContractWithParents();
    }

    @IsTest
    static void activatesApprovedContracts() {
        Contract c = [SELECT Id, Status FROM Contract LIMIT 1];
        Test.startTest();
        ContractService.activate(c.Id);
        Test.stopTest();
        // ...
    }
}
It feeds the normal loop. Fixtures are ordinary Apex in your project - they run in the same local test runs, and the code they exercise shows up in the same coverage reports. See coverage reports for the JSON, HTML, and Cobertura output.

Stop writing factories by trial and error.

The required fields are already in the schema Nimbus runs your tests against. nimbus fixture reads them and hands you the class. Free, no org connection needed for standard objects.