Skip to content

Latest commit

 

History

History
73 lines (58 loc) · 4.3 KB

func_tests_new.md

File metadata and controls

73 lines (58 loc) · 4.3 KB

New version of the test framework!

New tests use new tvm op codes, which are not available in the stable version of TON, so you need to install the dev version of func/fift. You need to compile func/fift binaries from toncli-local branch of ton from here. (see INSTALLATION.md) You also need to make sure you use new versions of Asm.fif and AsmTests.fif from this repository.

Note: if you try to run tests written in an old way with a new toncli version, you will probably see an error like PROC:<{:procedure already defined. You need to either rewrite tests in a new way (which is preferred!) or pass --old flags as argument of toncli run_tests.

What is new?

  • No need to manually specify method_ids for test functions.
  • No need to hardcode function selectors of contract's functions.
  • No need to split the test into "prepare" and "check" code.
  • You can invoke more than one contract's method in each test.
  • If one test corrupts the stack in some way, other tests will not be affected.
  • Easily write tests which require sending messages signed with private keys.

Things you need to know

  • Each test function name should start with "__test" (e.g. int __test_example() {). This way we can determine which functions are tests, and which functions are just helpers.
  • Every time you call a contract's method, you need to use invoke_method (which assumes code will not throw) or invoke_method_expect_fail (which assumes code will throw) functions. They catch exceptions and compute gas usage.
  • From each test you can return any number of values, they will be added to the printed report. For example, you can return consumed gas there.

Examples

A lot of tests written in a new way could be found in nft_collection and nft_item projects examples. Also, a lot of helpers in tests-libs can be founded.

Assume we have a contract, which stores the 64-bit integer inside, increases it when receiving an internal message, and reports current value on get_total. We can write a test like this:

int __test_example() {
    set_data(begin_cell().store_uint(0, 64).end_cell());
    cell message = begin_cell().store_uint(10, 32).end_cell();
    var (int gas_used1, _) = invoke_method(recv_internal, [message.begin_parse()]);
    var (int gas_used2, stack) = invoke_method(get_total, []);
    [int total] = stack;
    throw_if(101, total != 10);
    return gas_used1 + gas_used2;
}

invoke_method takes two arguments: a method name, and arguments (which will be passed to the method) as a tuple. It returns two values: used gas, and values returned from the method (as tuple). If method throws, invoke_method will also throw, and the test will fail.

If you expect a method to throw, you should use invoke_method_expect_fail:

int __test_no_initial_data_should_fail() {
    int gas_used = invoke_method_expect_fail(get_total, []);
    return gas_used;
}

It takes two arguments in the same way as invoke_method, but returns only the amount of gas used by the method.

set_now(...)

You can use set_now(12345) inside the test to make now equal to 12345.

get_actions()

If you expect method to generate some actions (e.g. via send_raw_message), after invoke_method you can use get_actions() to get generated c5. There is also a special function assert_no_actions(), which you can use to check that no actions were generated by the method.

Actions are cleared before each invoke_method, so you need to check them after each invoke_method call, not at the end of the whole test.

sign and priv_to_pub

There are some helper functions, which could be used for cryptography. You can find specific examples here.

get_prev_c4() and get_prev_c5()

You can use get_prev_c4() to get persistent data of the last successful test. But personally I'd discourage people from using it. It is better to create a helper function, which sends all needed queries to the contract to change persistent data as required, and use it from different tests.