编写 Solidity 测试脚本

编写 Solidity 测试脚本

与 JavaScript 编写的测试脚本一样,基本特性也一直,支持净室环境,可以访问任意不说过的合约。
Truffle的可靠性测试框架是基于以下想法构建的:

  • Solidity 编写的脚本不继承任何合约。这样就使得你的测试合约尽可能的小,并且给予了你对合约的所有控制权。
  • 可靠性测试不应该依赖于任何断言库。Truffle为您提供了一个默认的断言库,但是您可以根据需要随时更改这个库。
  • 您应该能够对任何 Ethereum 客户机运行您的可靠性测试。

例子

让我们看一个例子,在还没有太深入之前。下面是 truffle unbox metacoin 提供的实度测试示例:

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MetaCoin.sol";

contract TestMetacoin {
  function testInitialBalanceUsingDeployedContract() {
    MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin());

    uint expected = 10000;

    Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
  }

  function testInitialBalanceWithNewMetaCoin() {
    MetaCoin meta = new MetaCoin();

    uint expected = 10000;

    Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
  }
}

你将会看到如下输出:

$ truffle test
Compiling ConvertLib.sol...
Compiling MetaCoin.sol...
Compiling truffle/Assert.sol
Compiling truffle/DeployedAddresses.sol
Compiling ../test/TestMetacoin.sol...

  TestMetacoin
    ✓ testInitialBalanceUsingDeployedContract (61ms)
    ✓ testInitialBalanceWithNewMetaCoin (69ms)

  2 passing (3s)

测试结构

为了更好的了解发生了什么,我们深入讨论下细节。

ASSERTIONS

你的断言像 Assert.equal() 是由 truffle/Assert.sol 提供给你的。这是默认的断言库,
但是只要库通过触发正确的断言事件与 Truffle 的测试运行器松散集成,就可以包含您自己的断言库。
您可以在 Assert.sol 中找到所有可用的断言函数。

DEPLOYED ADDRESSES 已发布账户

已部署合约的地址(例如,作为迁移的一部分部署的合同)可以通过 truffle/DeployedAddresses.sol 获得。
这是由Truffle提供的,并在运行每个套件之前重新编译和重新链接,
以向您的测试提供Truffle的洁净房间环境。本库以如下形式为你的所有已部署合约提供功能:

DeployedAddresses.();

这将返回一个地址,可以用来访问合约。请参阅上面的示例测试。

为了使用已部署的契约,您必须将契约代码导入到您的测试套件中。注意 import"../contracts/ MetaCoin.sol”;
在这个例子中。这个导入是相对于存在于./test目录中的测试契约的,为了找到MetaCoin契约,它会在测试目录之外。
然后它使用该契约将地址转换为MetaCoin类型。

测试合约名

所有合约的测试必须以 test 开头,使用大写的 T 。这样的命名方式就将测试合约和普通合约区分开来了,
让测试运行器知道那个合约代表测试套件。

测试方法名

跟测试合约类似,所有的测试方法,都必须以小写单词 test 开头。每个测试方法都会被当作一个独立的交易,
根据在测试文件中定义的顺序执行。truffle/Assert.sol 提供的断言函数,测试运行程序评估触发事件以确定测试的结果。
断言函数返回一个布尔值,表示断言成功或失败,你可以使用它从测试早期返回,以防止执行错误(例如,Ganache或Truffle开发的错误将暴露)。

hooks 使用的前后

在如下例子中为你提供了许多测试 hooks 。这些 hooks 是 beforeAll 、 beforeEach 、 afterEach ,
它们是 Mocha 在 Javascript 测试中提供的相同的 hooks 。您可以使用这些 hooks 在每个测试之前和之后,
或者在每个套件运行之前和之后执行安装和拆卸操作。和测试方法一样,每个测试 hooks 都会是一个独立的交易。
您可以通过创建许多带有不同后缀的 hooks 来绕过这个限制,如下面的示例所示:

import "truffle/Assert.sol";

contract TestHooks {
  uint someValue;

  function beforeEach() {
    someValue = 5;
  }

  function beforeEachAgain() {
    someValue += 1;
  }

  function testSomeValueIsSix() {
    uint expected = 6;

    Assert.equal(someValue, expected, "someValue should have been 6");
  }
}

这个测试合约还表明,您的测试函数和hook函数都共享相同的合约状态。您可以在测试之前设置合约数据,
在测试期间使用该数据,并在测试之后重置它,为下一个测试做准备。注意,就像Javascript测试一样,
下一个测试函数将从运行的前一个测试函数的状态继续。

高级特性

Solidity 有一些新特新可以让你使用特殊的用力来测试。

异常测试

你可以很容易地测试你的合同应不应该抛出一个异常。( 例如:require()/ assert()/revert() 语句;之前的版本的 throw)。
这个话题是特约作家西蒙·德·拉·鲁维埃(Simon de la Rouviere)在他的 Truffle Solidity 测试教程中首次提出的。
本教程不推荐的关键字 throw 大量使用异常。从Solidity v0.4.13开始取而代之的是 revert()、require()和assert()。

测试以太币交易

你也可以测试你的合约是如何接收以太币的,并且用 JavaScriptSolidity 交互。为了达到这目的,你需要在
Solidity 测试脚本中写一个名为 initialBalance 的方法,并且返回 uint
这可以直接写为函数或公共变量,如下所示。当你的测试合约被部署到网络上时,Truffle将从你的测试账户发送到你的测试合约。
你的测试合约中就可以使用这个以太币来进行测试。注意,initialBalance是可选的,不是必需的。

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/MyContract.sol";

contract TestContract {
  // Truffle will send the TestContract one Ether after deploying the contract.
  uint public initialBalance = 1 ether;

  function testInitialBalanceUsingDeployedContract() {
    MyContract myContract = MyContract(DeployedAddresses.MyContract());

    // perform an action which sends value to myContract, then assert.
    myContract.send(...);
  }

  function () {
    // This will NOT be executed when Ether is sent. \o/
  }
}

请注意,Truffle以不执行回退函数的方式发送到测试合约,因此您仍然可以在固态测试中对高级测试用例使用回退函数。

你可能感兴趣的:(编写 Solidity 测试脚本)