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.
{
"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.
{
"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