Skip to main content

CLI tests

To run CLI tests, you will need the kwil-cli binary installed. To download the binary, see the downloads page of GitHub.

This documentation explains how to define JSON tests using an example Kuneiform schema. The schema is a basic application that stores and retrieves users:

users.sql
CREATE TABLE users (
id UUID PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
address TEXT NOT NULL UNIQUE
);

CREATE ACTION create_user($name text) public {
// derive a deterministic uuid from the blockchain transaction ID
// https://www.postgresql.org/docs/16.1/uuid-ossp.html#UUID-OSSP-FUNCTIONS-SECT
$uuid := uuid_generate_v5('f541de32-5ede-4083-bdbc-b29c3f02be9e'::uuid, @txid);

insert into users (id, name, address)
values ($uuid, $name, @caller);
}

CREATE ACTION get_users() public view returns table (name text, address text) {
return select name, address from users;
}

Defining A Test

To define a test, create a new JSON file called tests.json. This test assumes we have the current directory setup:

working-dir/
|- tests.json
|- users.sql

The below file gives our tests a top-level name of "my users.sql tests". It will read in the schema in the file users.sql. It defines an insert statement to seed data (defined in the "seed_statements" field) into the n. All data is wiped and the seed statements are re-applied before each test case is run.

tests.json
{
"name": "my users.sql tests",
"seed_scripts": ["users.sql"],
"seed_statements": {
"users_db": ["INSERT INTO users (id, name, address) VALUES ('42f856df-b212-4bdc-a396-f8fb6eae6901'::uuid, 'satoshi', '0xAddress')"]
},
"test_cases": []
}

Defining Individual Test Cases

Within the test_cases array, you can define individual test cases. Each test case can define the following fields. Optional fields are marked with an asterisk:

  • name: The name of the test case, which will be used to identify the test case if it fails.
  • namespace*: The namespace in the n that you are targeting, defaults to 'main'.
  • action: The name of the action that you are targeting.
  • args*: An array of arguments that will be passed to the action. It must match the expected parameters of the action. It can be empty if the action does not take any arguments.
  • returns*: A 2-dimensional array of expected return values. This matches the expected return table of the action. This can be empty if the action does not return anything, or if an error is expected.
  • error*: If the test case is expected to return an error, you can define the expected error message here. The tool will check that the returned error contains this string as a substring. If empty, the test case is expected to succeed.
  • caller*: The wallet address (or any other string) that will be assigned to @caller. If empty, the caller will be set to the same wallet address as the n deployer.
  • height*: The height of the block that the test case will be run at. If empty, the height will be set to 0.

Below, we add two test cases to our schema. The first test case tests the create_user action, and the second tests the get_users action. All data will be wiped after each test case is run, except for the data that was seeded in the seed_statements field.

tests.json
{
"name": "my users.sql tests",
"seed_scripts": ["users.sql"],
"seed_statements": {
"users_db": ["INSERT INTO users (id, name, address) VALUES ('42f856df-b212-4bdc-a396-f8fb6eae6901'::uuid, 'satoshi', '0xAddress')"]
},
"test_cases": [
{
"name": "create_user test",
"target": "create_user",
"args": ["alice"],
"caller": "0xOtherAddress"
},
{
"name": "get_users test",
"target": "get_users",
"args": [],
"returns": [["satoshi", "0xAddress"]]
}
]
}

Running Tests

To run the test, use the kwil-cli utils test command. The test file path can be passed using the --file flag. Multiple test files can be specified by simply adding more --file flags. The test also needs a Postgres instance to run against. You can use the --test-container flag to have the test automatically start a Postgres instance in a Docker container. Alternatively, you can connect to your own Postgres image using the --host, --port, --user, --password, and --n flags.

kwil-cli utils test --file tests.json --test-container