Unit Testing

  • create python test files in tests folder.

  • filenames must begin with test_

  • from brownie import <contract_name>, accounts

In this following example, we want to test that favNum initializes to 0.

  • deploy the contract

  • retrieve the starting value

  • compare it with expected starting value

from brownie import SimpleStorage, accounts

def test_deploy():
    # Arrange - setup
    account = accounts[0]

    # Act
    simple_storage = SimpleStorage.deploy({"from": account})
    starting_value = simple_storage.retrieve()
    expected_value = 0

    # Assert
    assert expected_value == starting_value

To run this test, input: brownie test in terminal:

If we get a green dot at the end like above, all tests were successful.

Test updating storage variable

  • deploy contract

  • update favNum storage variable to be 15

  • retrieve storage variable and compare with expected.

Tips

To test 1 function

brownie test -k <function name> brownie test -k test_update_storage

To get into interactive mode:

brownie test --pdb

when a test fails, or an error is encountered, terminal will convert to an interactive python shell:

we can observe the values of variables by typing them in and their values will be returned.

circle-info

reference the other brownie flags from pytest documentation

get accounts

Negative tests

Lets say you want to do a test that results in a revert. Like testing a function that only the owner can call, but calling it from a non-owner address.

We will use pytest to skip tests that we only want conducted in our private local chains (pip install pytest)

You would expect a revert to be thrown, like below, reflecting that an exception had occurred:

exception thrown

How can we conduct a negative test properly?

the correct form of the test would be:

Where should i run my tests

  1. Brownie Ganache chain with Mocks: Always

    1. (tests should clear on brownie spun up ganache-cli env)

  2. Testnet: Always (but only for integration testing)

  3. Brownie mainnet-fork: Optional

  4. Custom mainnet-fork: Optional

  5. Self/Local Ganache: Not necessary, but good for tinkering

Last updated