Truffle 有一个标准的自动化测试框架,让你可以非常方便地测试您的合约.这个框架允许您以两种不同的方式编写简单可控的测试:
1. 在 中, 用于执行来自外部世界的合约,就像您的应用程序一样。
2. 在 中, 用于在先进的,裸露的金属场景中执行您的合约。
Truffle 使用 测试框架 和 断言来给你提供一个可靠的框架编写JavaScript测试,让我们深入研究一下,看看Truffle 是如何构建在Mocha之上,让你可以轻松地测试你的合约的。
注意:如果您不熟悉在Mocha上做单元测试,请在继续之前查看一下 的文档。
从结构上说,您的测试文件应该与Mocha基本保持一致: 您的测试文件应该放在 ./test 目录, 以 .js作为后缀,而且,它们应该包含Mocha能够识别的自动化测试代码。让 Truffle 和 Mocha 不一样的是这个 contract() 函数: 这个函数基本和 describe() 一样,只不过它可以启用 . 其过程如下:
1. 每次contract()函数运行之前,您的合约会被重新部署到正在运行的以太坊客户端,因此测试是在一个干净的合约环境下进行的。
2. 这个contract()函数提供一个由您的以太坊客户端生成的,可以在编写测试合约使用的账户列表。
合约抽象是 JavaScript 实现合约交互的基础。因为Truffle 无法检测出在测试中需要与哪些合约进行交互,所以您需要明确地指出这些合约。您可以使用一个由Truffle提供的方法 artifacts.require()来做这些事情,它可以让您为一个特定的合约,请求一个可用的合约抽象。就如您在下面的例子中所看到的,然后您可以使用这个抽象来确保您的合约工作正常。 有关使用合约抽象的更多信息,查看 章节。
在测试中使用artifacts.require()的方式和在迁移中使用的方式相同,您只需要指定合约名称.更多信息,请查看 。
每个测试文件都有一个配置了正确提供者的web3实例,所以web3.eth.getBalance直接调用就行了。
这里是一个由 提供的测试案例. 注意这 contract() 函数的使用, 这个 accounts 数组是指定的可用的以太坊账户, artifacts.require() 则是为了和合约直接交互用的.
运行truffle test ./test/metacoin.js输出如下内容:
这是个类似的实例,只不过使用的是:
指定测试文件
我们通过如下命令限制执行测试的文件:
更多命令请参考
进阶
Truffle提供访问Mocha配置的能力,因此你可以通过改变Mocha配置来改变Mocha的行为,更多信息,请参考
Solidity测试合约以.sol文件格式与javascript测试文件一起工作.当truffle test运行时,它们将作为测试合约的独立测试套件包括在内.这些合约保留了JavaScript测试的所有优点:即每个测试套件都有一个洁净室环境,可以直接访问已部署的合同以及拥有导入任何合约依赖的能力.除了这些功能外,Truffle的Solidity测试框架还考虑到如下问题:
- Solidity测试不需要继承任何合约,这让你的测试尽可能的小,同时你也能对你写的合约能有一个完全的控制。
- Solidity不受任何断言库的影响,Truffle提供了默认的断言库,而且您可以按需修改此断言库。
- 您可以针对任何以太坊客户端运行您的Solidity测试。
实例
在深入探索之前,我们来看一个示例Solidity测试。以下是truffle unbox metacoin为您提供的示例Solidity测试:
运行truffle test ./test/TestMetacoin.sol输出如下:
你的断言方法,比如Assert.equal(),是由truffle/Assert.sol库提供的。这是默认的断言库,您也可以包含您自己的断言库,只要这个库能通过触发正确的断言事件与Truffle的测试运行器进行交互。您能在 找到所有能用的断言方法。
您通过truffle/DeployedAddresses.sol部署的合约(合约会作为migration的一部分被部署)是可用的,这是由truffle提供的并且会在每个套件提供洁净室测试运行环境之前被重新编译和重新链接。这个库以如下形式为您部署的所有合约提供函数:
DeployedAddress.<contract name>();这将返回一个您能用来访问合约的地址,具体使用方法请参考上面的实例。为了使用部署的合约,您必须将合约代码引入到你的测试套件里去,注意import “../contracts/MetaCoin.sol”;在这个实例中,import导入的是./test目录下与之相关的合约,然后使用合约将地址强转为Metacoin类型。
所有的测试合约必须以Test开头,使用一个大写的T。这使之区别于测试帮助类和项目合约,让测试器知道哪些合约代表测试套件。
跟测试合约名一样,所有的测试方法名必须以test开头(小写的),每个测试方法作为单个交易以出现在测试文件中的顺序执行。由truffle/Assert.sol提供的断言函数出发时间,测试运行器评估改事件以确定测试结果。断言函数返回一个表示断言结果的布尔值,您可以使用它提前从测试中返回以防止执行错误(如Ganache或Truffle Develop将会暴露的错误)。
truffle提供给您许多测试钩子,在下面的实例中展示。这些钩子是beforeAll,beforeEach,afterAll和afterEach,这与Mocha在JavaScript测试中提供的钩子是一样的。您能使用这些钩子在测试前后或者在每个测试套件运行前后做setup和teardown的操作。和测试函数一样,每个钩子都是作为单个交易运行的。请注意,一些复杂的测试需要执行大量的设置,这可能会溢出单个事务的gas限制;您可以通过创建许多带有后缀的钩子来绕过这个限制,就像下面例子所描述的:
这个测试合约也展示了您的测试函数和hook函数可以共享合约状态。您可以在测试之前设置合约数据,在测试中使用这些数据以及重置数据以准备下一个测试。注意,就像您的JavaScript测试一样,您的下一个测试函数将以之前运行的测试函数状态继续运行。
Solidity 测试具有一些高级功能,可以让你测试特殊用例。
您可以很容易地测试你的合同是否应该引发一个异常(例如require()/assert()/revert()语句;throw在早期的Solidity版本上抛出。这个主题首先由作者Simon de la Rouviere在他的教程“在Truffle Solidity测试中抛出异常”中提出。注:该教程大量使用弃用的关键词throw来抛出异常,并从Solidity v0.4.13版本开始被require(),assert()和revert()所取代。
您也可以测试您的合同如何对接收Ether做成出反应,并在Solidity中编写该交互脚本。为了达到这个目的,您的测试应该有一个叫initialBalance,返回值为uint的公有函数。这可以直接写作一个方法或者公用变量,就像下例所示。当您的测试合约部署到网络上,Truffle将从您的测试账户发送大量的Ether到您的测试合约。然后,您的测试合约可以使用这些Ether来在您的合约测试中编写与以太坊的交互。注意:initialBalance是可选的,不是必须的。
请注意,Truffle以不执行回退函数的方式将Ether发送到您的测试合同,因此您仍然可以在您的Solidity测试中使用回退函数进行高级测试用例。
来源:区块链兄弟
原文链接:
http://www.blockchainbrother.com/article/2082