单元测试插件

请从图标栏中点击 (”双重检查”)的图标,以进入Solidity Unit Testing插件。

If you haven’t used this plugin before and are not seeing the double check icon, you have to activate it from Remix plugin manager.

点击 (插件)图标以进入插件管理器并激活Solidity Unit Testing插件。

Now the double check icon will appear on the left side icon bar. Clicking on the icon will load the plugin in the side panel.

Alternatively, select Solidity environment from Remix IDE Home tab. This will activate Solidity Unit Testing plugin along with Solidity Compiler, Deploy & Run Transactions & Solidity Static Analysis plugins.

成功加载后,插件看起来像这样:

测试目录

Plugin asks you to provide a directory which will be your unit testing workspace (not to be confused with a Workspace in the File Explorer). To select directory, as soon as you add / to the path, it shows the possible options. [Rob Edit]

选定目录后,该目录将用于加载测试文件和存储新生成的测试文件。

默认测试目录是browser/tests。

生成

Select the Solidity file which you want to test and click on the Generate button. In the test directory, a test file will be created for your selected file.

If no file is selected, a generic test file named, newFile_test.sol will be created.

This file contains information about developing tests for a contract.

Below is an example of a generic test file:

pragma solidity >=0.4.22 <0.8.0;
import "remix_tests.sol"; // this import is automatically injected by Remix.
import "remix_accounts.sol";
// Import here the file to test.

// File name has to end with '_test.sol', this file can contain more than one testSuite contracts
contract testSuite {

    /// 'beforeAll' runs before all other tests
    /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll'
    function beforeAll() public {
        // Here should instantiate tested contract
        Assert.equal(uint(1), uint(1), "1 should be equal to 1");
    }

    function checkSuccess() public {
        // Use 'Assert' to test the contract, 
        // See documentation: https://remix-ide.readthedocs.io/en/latest/assert_library.html
        Assert.equal(uint(2), uint(2), "2 should be equal to 2");
        Assert.notEqual(uint(2), uint(3), "2 should not be equal to 3");
    }

    function checkSuccess2() public pure returns (bool) {
        // Use the return value (true or false) to test the contract
        return true;
    }
    
    function checkFailure() public {
        Assert.equal(uint(1), uint(2), "1 is not equal to 2");
    }

    /// Custom Transaction Context
    /// See more: https://remix-ide.readthedocs.io/en/latest/unittesting.html#customization
    /// #sender: account-1
    /// #value: 100
    function checkSenderAndValue() public payable {
        // account index varies 0-9, value is in wei
        Assert.equal(msg.sender, TestsAccounts.getAccount(1), "Invalid sender");
        Assert.equal(msg.value, 100, "Invalid value");
    }
}

编写测试

编写足够的单元测试,以确保您的合约在不同的情况下按预期工作。

Remix injects a built-in assert library for testing. You can visit the library documentation here.

Additionally, Remix allows the usage of special functions in the test file to make testing more structural. They are:

  • beforeEach() - 在每次测试之前运行

  • beforeAll() - 在所有测试之前运行

  • afterEach() - 在每次测试之后运行

  • afterAll() - 在所有测试之后运行

开始前,请看 这个简单的例子

运行

Once you are done with writing tests, select the file(s) and click on Run to execute the tests. The execution will run in a separate environment. After completing the execution of one file, a test summary will be shown:

对于失败的测试,将有更多的断言细节来分析问题。单击失败的测试将在编辑器中高亮显示相关代码行。

停止

如果您选择运行多个文件的测试并想要停止执行,请单击停止按钮。它将在运行当前文件的测试后停止执行。

自定义

Remix 帮助用户通过各种类型的自定义来正确测试合约。

1. 自定义编译器上下文

Solidity Unit Testing插件使用Solidity编译器插件进行编译器配置。在Solidity编译器插件中,配置编译器EVM版本启用优化,这些配置会在Solidity Unit Testing运行单元测试之前合约的编译上。

2. 自定义交易上下文

要与合约的方法交互,交易的主要参数是from地址、valuegas。通常,使用这些参数的不同值来测试方法的行为。

在交易的中,您可以使用NatSpec注释输入自定义的msg.sendermsg.value值,如:

/// #sender: account-0
/// #value: 10
function checkSenderIs0AndValueis10 () public payable {
    Assert.equal(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIs0AndValueis10");
    Assert.equal(msg.value, 10, "wrong value in checkSenderIs0AndValueis10");
}

使用的指令:

  1. 参数必须在方法的NatSpec中定义

  2. 每个参数键都应以 (#) 为前缀,并以一个空格()后缀结束,如#sender:#value:

  3. 目前,仅可为sendervalue参数进行自定义

  4. Sender是交易的发送方地址,可在合约方法中使用msg.sender访问,必须以固定格式“account-<account_index>”定义

  5. <account_index>的取值范围取决于remix-ide版本号,v0.10.0之前为0-2,之后为0-9

  6. 必须在测试文件中导入remix_accounts.sol才能使用自定义的sender

  7. Value是以wei为单位发送的value,可在合约方法中使用msg.value访问,必须是一个数字。

对于gas,Remix会在内部估算每个交易所需的gas。但是,如果合约部署失败并出现gas不足错误,则会尝试通过将gas加倍来重新部署它。如果使用加倍gas的部署仍然失败,则会显示错误信息:

Various test examples can be seen in examples section.

要记住的要点

  • 测试合约不能含有带参数的方法。如果有这样的方法,将显示错误信息:“在测试合约中,方法’methodname’不能带有参数”。

  • 在remix-ide v0.10.0之前,测试账户数为3,在之后为10。

  • 如果导入了remix_accounts.sol的测试文件,Solidity Compiler插件无法成功编译,请不要担心,这不会影响它在Solidity Unit Testing插件中的功能。