Testing and Debugging

Configuring the Debugger

Neo3-Boa is compatible with the Neo Debugger. Debugger launch configuration example:

{
    //Launch configuration example for Neo3-Boa.
    //Make sure you compile your smart-contract before you try to debug it.
    "version": "0.2.0",
    "configurations": [
        {
            "name": "example.nef",
            "type": "neo-contract",
            "request": "launch",
            "program": "${workspaceFolder}\\example.nef",
            "operation": "main",
            "args": [],
            "storage": [],
            "runtime": {
                "witnesses": {
                    "check-result": true
                }
            }
        }
    ]
}

It’s necessary to generate the nef debugger info file to use Neo Debugger.

Using CLI

$ neo3-boa compile path/to/your/file.py -d|--debug

Using Python Script

from boa3.boa3 import Boa3

Boa3.compile_and_save('path/to/your/file.py', debug=True)

Neo Test Runner

Downloading

Install Neo-Express and Neo Test Runner.

Testing

Before writing your tests, make sure you have a Neo-Express network for local tests. If you do not yet have a local network, open a terminal and run neoxp create. Please refer to Neo-Express documentation for more details of how to configure your local network.

Create a Python Script, import the NeoTestRunner class, and define a function to test your smart contract. In this function you’ll need a NeoTestRunner object, which takes the path of your Neo-Express network configuration file as an argument to set up the test environment.

You’ll have to call the method call_contract() to interact with your smart contract. Its parameters are the path of the compiled smart contract, the smart contract’s method, and the arguments if necessary. This call doesn’t return the result directly, but includes it in a queue of invocations. To execute all the invocations set up, call the method execute(). Then assert the result of your invoke to see if it’s correct.

Note that invoke.result won’t be set if the execution fails, so you should also assert if runner.vm_state is valid for your test case.

Your Python Script should look something like this:

from boa3.builtin.interop.blockchain.vmstate import VMState
from boa3_test.test_drive.testrunner.neo_test_runner import NeoTestRunner


def test_hello_world_main():
    neoxp_config_file = '{path-to-neo-express-config-file}'
    project_root_folder = '{path-to-project-root-folder}'
    path = f'{project_root_folder}/boa3_test/examples/hello_world.nef'
    runner = NeoTestRunner(neoxp_config_file)

    invoke = runner.call_contract(path, 'main')
    runner.execute()
    assert runner.vm_state is VMState.HALT
    assert invoke.result is None

Alternatively you can change the value of env.NEO_EXPRESS_INSTANCE_DIRECTORY to the path of your .neo-express data file:

from boa3.builtin.interop.blockchain.vmstate import VMState
from boa3_test.test_drive.testrunner.neo_test_runner import NeoTestRunner
from boa3.internal import env

env.NEO_EXPRESS_INSTANCE_DIRECTORY = '{path-to-neo-express-config-file}'


def test_hello_world_main():
    root_folder = '{path-to-project-root-folder}'
    path = f'{root_folder}/boa3_test/examples/hello_world.nef'
    runner = NeoTestRunner()  # the default path to the Neo-Express is the one on env.NEO_EXPRESS_INSTANCE_DIRECTORY

    invoke = runner.call_contract(path, 'main')
    runner.execute()
    assert runner.vm_state is VMState.HALT
    assert invoke.result is None