Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 30 Oct 2026. What's built · Install 0.1.0
jadpo
Reference: Testing

Testing

Shared test data: fixtures

On this page

When several test files need the same data, write a fixture. A fixture is a test-only action, in the domain's fixtures/ folder, that creates data by calling the application's own actions and returns what the tests need:

example
// domains/planning/fixtures/alice_with_todos.jadpo/// Alice, signed up, with two open todos.fixture alice_with_todos() -> Principal.user {    var user: User = attempt register_user("alice@example.test")    var alice: Principal.user = Principal.user(user)    attempt create_todo(CreateTodo { title: "Buy milk" }, alice)    attempt create_todo(CreateTodo { title: "Book dentist" }, alice)    return alice}

A test calls a fixture by name, like any action. Because the fixture goes through the real actions, validation, lifecycle and policy apply exactly as they do for a user. Seeds build their data the same way (Seeds). A failure inside a fixture fails the test that called it, so a fixture has no fails list.

Who can call a fixture

Only tests, other fixtures and seeds can call a fixture. An action that calls one is semantic.not_callable.

A fixture for other domains: public

A fixture is private to its domain unless it is marked public. Another domain's tests, fixtures and seeds, and a scenario in root tests/, call a public fixture through its domain, like an action: planning.alice_with_todos(). Calling a private one from outside its domain is visibility.private_cross_domain. public offers a fixture to tests, fixtures and seeds only: application code still never calls it.

Here planning offers a public fixture, and both a reminders test and a scenario call it:

example
// domains/planning/fixtures/two_open_todos.jadpouse planning/types { TodoCount }use planning/actions { add_todo }/// Two open todos, added the way a user adds them.public fixture two_open_todos() -> TodoCount {    var one: TodoCount = add_todo(0)    return add_todo(one)}
example
// domains/reminders/actions/send_reminders.test.jadpouse planningtest "reminders start from planning's open todos" {    send_reminders()    assert planning.two_open_todos() == 2}
example
// tests/a_plan_starts_with_two_todos.test.jadpouse planningtest "a plan starts with two open todos" {    assert planning.two_open_todos() == 2}

Seeds and fixtures

A seed is data for local development and demos, made the same way:

Seed Fixture
Lives in database/seeds/ a domain's fixtures/
Used by jadpo seed <name>, for local development and demos tests
Creates data by calling actions calling actions
Data lasts until you reset the local database until the test ends
In production refused never compiled in

A seed may call fixtures, so demo data and test data share their builders. A test never loads a seed: seeds change whenever the demo changes.

Data builders

A data builder makes one record with valid defaults, for a test that needs a record in a particular state. The compiler generates one for each entity: make.Todo { title: "Buy milk" } fills every other required field with a valid default and goes through the real create operation, so validation and policy apply. A builder may set any field that isn't generated, including ones ordinary inputs don't accept, so hard-to-reach states are easy to build.

With builders, fixtures remain for meaningful scenarios. They return a named object holding what they made (setup.alice, setup.todos), so a test never has to look its own data up again.

Data builders, and the named object a fixture returns with them, aren't built yet. Until they are, build the data with a fixture that returns what the tests need, as above.

Markdown for agents: /docs/shared-test-data-fixtures.md.Built from Jadpo main at a707efb.