Unit Tests
Unit Tests
Unit testing for Move adds three new annotations to the Move source language:
#[test]
#[test_only]
, and#[expected_failure]
.
They respectively mark a function as a test, mark a module or module member (use
, function, or struct) as code to be included for testing only, and mark that a test is expected to fail. These annotations can be placed on a function with any visibility. Whenever a module or module member is annotated as #[test_only]
or #[test]
, it will not be included in the compiled bytecode unless it is compiled for testing.
Testing Annotations: Their Meaning and Usage
Both the #[test]
and #[expected_failure]
annotations can be used either with or without arguments.
Without arguments, the #[test]
annotation can only be placed on a function with no parameters. This annotation simply marks this function as a test to be run by the unit testing harness.
Expected Failure
A test can also be annotated as an #[expected_failure]
. This annotation marks that the test should is expected to raise an error.
You can ensure that a test is aborting with a specific abort <code>
by annotating it with #[expected_failure(abort_code = <code>)]
, corresponding to the parameter to an abort
statement (or failing assert!
macro).
Instead of an abort_code
, an expected_failure
may specify program execution errors, such as arithmetic_error
, major_status
, vector_error
, and out_of_gas
. For more specificity, a minor_status
may optionally be specified.
If the error is expected from a specific location, that may also be specified: #[expected_failure(abort_code = <code>, location = <loc>)]
. If the test then fails with the right error but in a different module, the test will also fail. Note that <loc>
can be Self
(in the current module) or a qualified name, e.g. vector::std
.
Only functions that have the #[test]
annotation can also be annotated as an #[expected_failure]
.
Test parameters
With arguments, a test annotation takes the form #[test(<param_name_1> = <address>, ..., <param_name_n> = <address>)]
. If a function is annotated in such a manner, the function's parameters must be a permutation of the parameters <param_name_1>, ..., <param_name_n>
, i.e., the order of these parameters as they occur in the function and their order in the test annotation do not have to be the same, but they must be able to be matched up with each other by name.
Only parameters with a type of signer
are supported as test parameters. If a parameter other than signer
is supplied, the test will result in an error when run.
Arbitrary code to support tests
A module and any of its members can be declared as test only. In such a case the item will only be included in the compiled Move bytecode when compiled in test mode. Additionally, when compiled outside of test mode, any non-test use
s of a #[test_only]
module will raise an error during compilation.
Running Unit Tests
Unit tests for a Move package can be run with the endless move test
command. See package for more info.
When running tests, every test will either PASS
, FAIL
, or TIMEOUT
. If a test case fails, the location of the failure along with the function name that caused the failure will be reported if possible. You can see an example of this below.
A test will be marked as timing out if it exceeds the maximum number of instructions that can be executed for any single test. This bound can be changed using the options below, and its default value is set to 100000 instructions. Additionally, while the result of a test is always deterministic, tests are run in parallel by default, so the ordering of test results in a test run is non-deterministic unless running with only one thread (see OPTIONS
below).
There are also a number of options that can be passed to the unit testing binary to fine-tune testing and to help debug failing tests. These can be found using the help flag:
Example
A simple module using some of the unit testing features is shown in the following example:
First create an empty package inside an empty directory:
Next add the following to the Move.toml
:
Next add the following module under the sources
directory:
Running Tests
You can then run these tests with the endless move test
command:
Using Test Flags
-f <str>
or --filter <str>
This will only run tests whose fully qualified name contains <str>
. For example if we wanted to only run tests with "zero_coin"
in their name:
--coverage
This will compute code being covered by test cases and generate coverage summary.
Then by running endless move coverage
, we can get more detailed coverage information. These can be found using the help flag:
Last updated