Skip to content

Commit 79ceaf9

Browse files
authored
Merge pull request #489 from ProvableHQ/rr-test-framework
Content for native testing framework section of the Leo-lang docs
2 parents f9d8f06 + b9ffc53 commit 79ceaf9

File tree

1 file changed

+127
-2
lines changed

1 file changed

+127
-2
lines changed

documentation/testing/01_test_framework.md

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,131 @@ title: Leo's Native Testing Framework
44
sidebar_label: Testing
55
---
66

7-
<!--TODO:-->
7+
## Introduction
8+
The Leo testing frameworks enables developers to validate their Leo program logic by writing unit and integration tests. Tests are written in Leo and are located in a `tests/` subdirectory of the main Leo project directory.
9+
10+
```bash
11+
example_program
12+
├── build
13+
│ ├── imports
14+
│ │ └── test_example_program.aleo
15+
│ ├── main.aleo
16+
│ └── program.json
17+
├── outputs
18+
├── src
19+
│ └── main.leo
20+
├── tests
21+
│ └── test_example_program.leo
22+
└── program.json
23+
```
24+
The test file is a Leo program that imports the program in `main.leo`. The test functions will all be annotated with `@test` above the function declaration.
25+
26+
This tutorial will use an example program which can be found in the [example's repository](https://github.com/ProvableHQ/leo-examples/tree/main/example_with_test).
27+
28+
:::info
29+
Developers can add multiple `leo` files to the test directory but must ensure that the name of the test file matches the test program name. For example, if the name of the test file is `test_example_program.leo`, the test program name must be `test_example_program.aleo`.
30+
:::
31+
32+
33+
## Testing transition functions.
34+
35+
### Function logic
36+
37+
The `example_program.leo` program contains a transition function which returns the sum of two `u32` inputs.
38+
39+
```Leo
40+
transition simple_addition(public a: u32, b: u32) -> u32 {
41+
let c: u32 = a + b;
42+
return c;
43+
}
44+
```
45+
46+
The `test_example_program.leo` contains two tests to ensure that the transition logic returns a correct output and fails when the output does not match the sum of the input values.
47+
```Leo
48+
@test
49+
transition test_simple_addition() {
50+
let result: u32 = example_program.aleo/simple_addition(2u32, 3u32);
51+
assert_eq(result, 5u32);
52+
}
53+
```
54+
55+
The `@should_fail` annotation should be added after the `@test` annotation for tests that are expected to fail.
56+
```Leo
57+
@test
58+
@should_fail
59+
transition test_simple_addition_fail() {
60+
let result: u32 = example_program.aleo/simple_addition(2u32, 3u32);
61+
assert_eq(result, 3u32);
62+
}
63+
```
64+
65+
## Leo types
66+
67+
Developers can test that record and struct fields match their expected values. In `example_program.leo`, a record is minted transition function shown here:
68+
69+
```Leo
70+
record Example {
71+
owner: address,
72+
x: field,
73+
}
74+
75+
transition mint_record(x: field) -> Example {
76+
return Example {
77+
owner: self.signer,
78+
x,
79+
};
80+
}
81+
```
82+
83+
The corresponding test in `test_example_program.leo` checks that the Record field contains the correct value:
84+
85+
```Leo
86+
@test
87+
transition test_record_maker() {
88+
let r: example_program.aleo/Example = example_program.aleo/mint_record(0field);
89+
assert_eq(r.x, 0field);
90+
}
91+
```
92+
93+
:::info
94+
Each test file is required to have at least one transition function.
95+
:::
96+
97+
98+
## Using interpreted tests for modelling on-chain state
99+
While the testing framework cannot access on-chain state from either `testnet` or `mainnet`, developers can simulate on-chain state in `script`s. A script is interpreted Leo code in which developers are able to await `Future`s and update mappings using interpreted tests. When using interpreted tests, the `transition` or `function` keyword is replaced with the `script` keyword.
100+
101+
```Leo
102+
@test
103+
script test_async() {
104+
const VAL: field = 12field;
105+
let fut: Future = example_program.aleo/set_mapping(VAL);
106+
fut.await();
107+
assert_eq(Mapping::get(example_program.aleo/map, 0field), VAL);
108+
109+
let rand_val: field = ChaCha::rand_field();
110+
Mapping::set(example_program.aleo/map, VAL, rand_val);
111+
let value: field = Mapping::get(example_program.aleo/map, VAL);
112+
assert_eq(value, rand_val);
113+
}
114+
```
115+
116+
:::info
117+
External transitions -- async or not -- may be called from test transitions or scripts, but external async functions may only be called directly from scripts.
118+
:::
119+
120+
121+
## Running tests
122+
Invoking the `leo test` command will run all of the compiled and interpreted tests. Developer may optionally select an individual tests by supplying a a test function name or a string that is contained within a test function name. For instance, to run the test for `test_async`, developers would use the following command:
123+
```bash
124+
leo test test_async
125+
```
126+
Either of the following commands will run both of the addition function tests:
127+
```bash
128+
leo test simple
129+
```
130+
or
131+
```bash
132+
leo test addition
133+
```
8134

9-
Coming soon!

0 commit comments

Comments
 (0)