Step 4. Implement gear run subcommand that finds test functions and runs them
We need to add a subcommand in gear binary that opens Wasm binary, finds test functions inside it and runs them. cargo test will execute the runner with the test Wasm as an argument.
The good news is that the test binary also contains smart contract exports (init, handle and so on). Therefore, we can use it both as a contract binary and as a test binary. This is true for unit tests but not true (by default) for integration tests. To include contract exports to the integration tests binary we are to include the contract's rlib to the tests module:
use my_program as _;
#[test]
fn my_intgration_test() {
assert!(true);
}
Also, there is a good implementation of such kind of runner in lunatic runtime.
Step 5. Implement a super lightweight library that use minimal number of imports
The good news is we can reuse many functions from gstd for testing purposes. For example, we can use msg::send etc. for sending messages, exec::block_height to get the current block number, prog::create_program to create a new program.
We don't need to rewrite tons of methods that are already declared.
The only thing we are to add in our new gtest2 crate is the minimal count of extrinsics that are not present in the "standard" library (gstd and mates).
Let's imagine what the test can look like.
use gstd::{exec, msg, prog};
use gtest2::test;
use my_program as _;
#[test]
fn my_new_test() {
let code_id = gtest2::upload_self_code();
let (_, prog_id) = prog::create_program(code_id, b"salt", "INIT", 0).expect("Failed to create program");
let msg_id = msg::send(prog_id, "PING", 0).expect("Failed to send");
let reply = gtest2::get_from_mailbox(msg_id).expect("No message in mailbox");
assert_eq!(reply.dest, msg::source());
assert_eq!(reply.payload, "PONG");
}
Pros
Lightweight and blazingly fast test library
Compile/test time dramatically decreases
No excessive dependencies
Same tests for gtest-level and gclient-level tests (can be chosen by additional argument when calling cargo test)
No need to rewrite tons of functions in gtest/gclient
Familiar syntax similar to the program itself
Possibility to test programs against the real blockchain but without engaging network level
No need for .binpath file etc. (as the test binary is the program binary as well).
A new approach to test programs
This approach is mostly inspired by the Lunatic project.
Main concerns with
gtest
andgclient
gtest
gtest
crategtest
has a compatible version withgstd
and matesgclient
target
directorygtest
gclient
crateNew approach details
We don't need to build native binaries for tests but use Wasms with the external runner instead.
Step 1. Configure the program to build to
wasm32-unknown-unknown
targetCreate
config.toml
in.cargo
subdirectory:Step 2. Configure the program to be a dynamic library
Step 3. Implement custom
#[test]
attribute-like macro that exports test functionsWe implement our custom
#[test]
attribute-like macro that is to be used instead of the default#[test]
attribute.See this macro implementation example in
lunatic-test
crate.Step 4. Implement
gear run
subcommand that finds test functions and runs themWe need to add a subcommand in
gear
binary that opens Wasm binary, finds test functions inside it and runs them.cargo test
will execute the runner with the test Wasm as an argument.The good news is that the test binary also contains smart contract exports (
init
,handle
and so on). Therefore, we can use it both as a contract binary and as a test binary. This is true for unit tests but not true (by default) for integration tests. To include contract exports to the integration tests binary we are to include the contract's rlib to the tests module:Also, there is a good implementation of such kind of runner in
lunatic
runtime.Step 5. Implement a super lightweight library that use minimal number of imports
The good news is we can reuse many functions from
gstd
for testing purposes. For example, we can usemsg::send
etc. for sending messages,exec::block_height
to get the current block number,prog::create_program
to create a new program.We don't need to rewrite tons of methods that are already declared.
The only thing we are to add in our new
gtest2
crate is the minimal count of extrinsics that are not present in the "standard" library (gstd
and mates).Let's imagine what the test can look like.
Pros
gtest
-level andgclient
-level tests (can be chosen by additional argument when callingcargo test
)gtest
/gclient
.binpath
file etc. (as the test binary is the program binary as well).Cons
gear
binary before writing tests