• Start

Testing

Testing

SurrealKit includes a built-in testing framework for validating schema correctness, permissions, and API behaviour across multiple actor types.

SurrealKit includes a testing framework that lets you write declarative test suites for your SurrealDB schema. Tests run against an isolated ephemeral database per suite, so they are safe to run in any environment without affecting persistent data.

surrealkit test

SurrealKit reads all suite files from database/tests/suites/*.toml, runs them in parallel (configurable), and exits non-zero if any case fails.

database/tests/
├── config.toml # global defaults
└── suites/
├── security.toml
└── api.toml

database/tests/config.toml sets defaults shared across all suites:

[defaults]
timeout_ms = 10000
base_url = "http://localhost:8000"

[actors.root]
kind = "root"

SurrealKit supports five test types, specified via the kind field on each test case.

Runs a SurrealQL statement and asserts whether it succeeds or fails:

[[cases]]
name = "guest_cannot_create_order"
kind = "sql_expect"
actor = "guest"
sql = "CREATE order CONTENT { total: 10 };"
allow = false
error_contains = "permission"

Optional assertions check the returned data:

[[cases]]
name = "user_sees_own_profile"
kind = "sql_expect"
actor = "user_alice"
sql = "SELECT * FROM user WHERE id = $auth.id;"
allow = true

[[cases.assertions]]
path = "0.id"
equals_auth = "$auth.id"

Validates that a single actor has the expected create / select / update / delete permissions on a table or record:

[[cases]]
name = "reader_cannot_modify_orders"
kind = "permissions_matrix"
actor = "reader"
table = "order"
record_id = "order:test"

[[cases.rules]]
action = "select"
allow = true

[[cases.rules]]
action = "update"
allow = false
error_contains = "permission"

Asserts structural facts about the schema: that a field exists with a given type, that an index is defined, and so on.

Tests computed fields, functions, and record relations by asserting on the values returned after specific operations.

Tests HTTP API endpoints, useful when your SurrealDB instance exposes a custom API layer:

[[cases]]
name = "orders_endpoint_returns_200"
kind = "api_request"
actor = "root"
method = "GET"
path = "/api/orders"
expected_status = 200

[[cases.body_assertions]]
path = "0.id"
exists = true

Each test case runs as a named actor with a specific authentication method. Actors are defined in config.toml or at the suite level.

Actor kindWhen to use
rootFull root-level access
databaseDatabase-level user credentials
recordRecord access via signup / signin
tokenJWT token from an environment variable
headersCustom HTTP headers (e.g. tenant ID)
[actors.user_alice]
kind = "record"
access = "app_access"

[actors.user_alice.signin_params]
email = "alice@example.com"
password = "secret"

[actors.tenant_a]
kind = "headers"
headers = { "x-tenant-id" = "tenant_a" }
FlagDescription
--suite <glob>Run only suites whose name matches the glob
--case <glob>Run only cases whose name matches the glob
--tag <tag>Run only cases tagged with the given tag (repeatable)
--fail-fastStop on the first failure
--parallel <N>Number of parallel execution threads
FlagDescription
--keep-dbPreserve the ephemeral database after the run for manual inspection
--no-syncSkip the schema sync phase before running tests
--no-seedSkip the seeding phase before running tests
--json-out <path>Write a machine-readable JSON report to the specified file
  • CI / CD: integrate tests into automated pipelines with GitHub Actions and Docker Compose

Was this page helpful?