Move Unit Tests

Overview

Why Should You Write Unit Tests?

  • Writing tests is always a good practice.
  • For Move smart contract development, it's especially valuable because unit tests allow you to test and debug your code without deploying the contract, which can sometimes be a cumbersome process.

Aptogotchi Example

Source Code

1. Set up the testing environment.


// Setup testing environment
#[test_only]
use aptos_framework::account::create_account_for_test;
#[test_only]
use std::string::utf8;
#[test_only]
fun setup_test(aptos: &signer, account: &signer, creator: &signer){
// create a fake account (only for testing purposes)
create_account_for_test(signer::address_of(creator));
create_account_for_test(signer::address_of(account));
timestamp::set_time_has_started_for_testing(aptos);
init_module(account);
}

2. Write your unit test functions.


// Test creating an Aptogotchi.
// We initialize an Aptogotchi token for this test account with
// name = “test”, parts = [1, 1, 1], and default energy points of 10.
#[test(aptos = @0x1, account = @aptogotchi, creator = @0x123)]
fun test_create_aptogotchi(aptos: &signer, account: &signer, creator: &signer) acquires CollectionCapability, MintAptogotchiEvents {
setup_test(aptos, account, creator);
create_aptogotchi(creator, utf8(b"test"), vector[1, 1, 1]);
let has_aptogotchi = has_aptogotchi(signer::address_of(creator));
assert!(has_aptogotchi, 1);
}
// Test getting an Aptogotchi, when user has not minted.
// We create a test account and call get_aptogotchi(),
// expecting an error thrown because this account has not minted a token.
#[test(aptos = @0x1, account = @aptogotchi, creator = @0x123)]
#[expected_failure(abort_code = 851969, location = aptogotchi::main)]
fun test_get_aptogotchi_without_creation(aptos: &signer, account: &signer, creator: &signer) acquires CollectionCapability, AptoGotchi {
setup_test(aptos, account, creator);
// get aptogotchi without creating it
get_aptogotchi(signer::address_of(creator));
}
// Test feeding and playing with an Aptogotchi
#[test(aptos = @0x1, account = @aptogotchi, creator = @0x123)]
fun test_feed_and_play(
aptos: &signer,
account: &signer,
creator: &signer
) acquires CollectionCapability, MintAptogotchiEvents, AptoGotchi {
setup_test(aptos, account, creator);
create_aptogotchi(creator, utf8(b"test"), vector[1, 1, 1]);
assert!(get_energy_points(signer::address_of(creator)) == ENERGY_UPPER_BOUND, 1);
play(creator, 5);
let energy_points_after_play = ENERGY_UPPER_BOUND - 5;
assert!(get_energy_points(signer::address_of(creator)) == energy_points_after_play, 1);
feed(creator, 3);
let energy_points_after_feed = energy_points_after_play + 3;
assert!(get_energy_points(signer::address_of(creator)) == energy_points_after_feed, 1);
}
// Test getting an Aptogotchi, when user has already minted
#[test(aptos = @0x1, account = @aptogotchi, creator = @0x123)]
#[expected_failure(abort_code = 524292, location = aptogotchi::main)]
fun test_create_aptogotchi_twice(
aptos: &signer,
account: &signer,
creator: &signer
) acquires CollectionCapability, MintAptogotchiEvents {
setup_test(aptos, account, creator);
create_aptogotchi(creator, utf8(b"test"), vector[1, 1, 1]);
create_aptogotchi(creator, utf8(b"test"), vector[1, 1, 1]);
}

3. Run the unit tests.

  • Unit tests for a Move package can be run with the aptos move test command. Every test will either PASSFAIL, or TIMEOUT.
  • To run unit tests, go to your Move folder /move (where your Move.toml file is) and run:


More Resources

You can learn more about unit testing here.

Link