編寫 Solidity 測試腳本
與 JavaScript 編寫的測試腳本一樣托修,基本特性也一直,支持凈室環(huán)境恒界,可以訪問任意不說過的合約睦刃。
Truffle的可靠性測試框架是基于以下想法構(gòu)建的:
- Solidity 編寫的腳本不繼承任何合約。這樣就使得你的測試合約盡可能的小仗处,并且給予了你對合約的所有控制權(quán)眯勾。
- 可靠性測試不應(yīng)該依賴于任何斷言庫。Truffle為您提供了一個默認(rèn)的斷言庫婆誓,但是您可以根據(jù)需要隨時更改這個庫吃环。
- 您應(yīng)該能夠?qū)θ魏?Ethereum 客戶機(jī)運(yùn)行您的可靠性測試。
例子
讓我們看一個例子洋幻,在還沒有太深入之前郁轻。下面是 truffle unbox metacoin
提供的實(shí)度測試示例:
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)
測試結(jié)構(gòu)
為了更好的了解發(fā)生了什么,我們深入討論下細(xì)節(jié)文留。
ASSERTIONS
你的斷言像 Assert.equal()
是由 truffle/Assert.sol
提供給你的好唯。這是默認(rèn)的斷言庫,
但是只要庫通過觸發(fā)正確的斷言事件與 Truffle 的測試運(yùn)行器松散集成燥翅,就可以包含您自己的斷言庫骑篙。
您可以在 Assert.sol
中找到所有可用的斷言函數(shù)。
DEPLOYED ADDRESSES 已發(fā)布賬戶
已部署合約的地址(例如森书,作為遷移的一部分部署的合同)可以通過 truffle/DeployedAddresses.sol
獲得靶端。
這是由Truffle提供的谎势,并在運(yùn)行每個套件之前重新編譯和重新鏈接,
以向您的測試提供Truffle的潔凈房間環(huán)境杨名。本庫以如下形式為你的所有已部署合約提供功能:
DeployedAddresses.<contract name>();
這將返回一個地址脏榆,可以用來訪問合約。請參閱上面的示例測試台谍。
為了使用已部署的契約衅檀,您必須將契約代碼導(dǎo)入到您的測試套件中通惫。注意 import"../contracts/ MetaCoin.sol”;
在這個例子中。這個導(dǎo)入是相對于存在于./test目錄中的測試契約的,為了找到MetaCoin契約片习,它會在測試目錄之外延届。
然后它使用該契約將地址轉(zhuǎn)換為MetaCoin類型址貌。
測試合約名
所有合約的測試必須以 test
開頭脚翘,使用大寫的 T
。這樣的命名方式就將測試合約和普通合約區(qū)分開來了炎咖,
讓測試運(yùn)行器知道那個合約代表測試套件赃泡。
測試方法名
跟測試合約類似,所有的測試方法乘盼,都必須以小寫單詞 test
開頭升熊。每個測試方法都會被當(dāng)作一個獨(dú)立的交易,
根據(jù)在測試文件中定義的順序執(zhí)行绸栅。truffle/Assert.sol
提供的斷言函數(shù),測試運(yùn)行程序評估觸發(fā)事件以確定測試的結(jié)果级野。
斷言函數(shù)返回一個布爾值,表示斷言成功或失敗粹胯,你可以使用它從測試早期返回蓖柔,以防止執(zhí)行錯誤(例如,Ganache或Truffle開發(fā)的錯誤將暴露)风纠。
hooks 使用的前后
在如下例子中為你提供了許多測試 hooks 况鸣。這些 hooks 是 beforeAll 、 beforeEach 竹观、 afterEach 镐捧,
它們是 Mocha 在 Javascript 測試中提供的相同的 hooks 。您可以使用這些 hooks 在每個測試之前和之后臭增,
或者在每個套件運(yùn)行之前和之后執(zhí)行安裝和拆卸操作懂酱。和測試方法一樣,每個測試 hooks 都會是一個獨(dú)立的交易誊抛。
您可以通過創(chuàng)建許多帶有不同后綴的 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");
}
}
這個測試合約還表明,您的測試函數(shù)和hook函數(shù)都共享相同的合約狀態(tài)拗窃。您可以在測試之前設(shè)置合約數(shù)據(jù)瞎领,
在測試期間使用該數(shù)據(jù)蔓榄,并在測試之后重置它,為下一個測試做準(zhǔn)備默刚。注意,就像Javascript測試一樣逃魄,
下一個測試函數(shù)將從運(yùn)行的前一個測試函數(shù)的狀態(tài)繼續(xù)荤西。
高級特性
Solidity
有一些新特新可以讓你使用特殊的用力來測試。
異常測試
你可以很容易地測試你的合同應(yīng)不應(yīng)該拋出一個異常伍俘。( 例如:require()/ assert()/revert() 語句;之前的版本的 throw
)邪锌。
這個話題是特約作家西蒙·德·拉·魯維埃(Simon de la Rouviere)在他的 Truffle Solidity 測試教程中首次提出的。
本教程不推薦的關(guān)鍵字 throw
大量使用異常癌瘾。從Solidity v0.4.13開始取而代之的是 revert()觅丰、require()和assert()。
測試以太幣交易
你也可以測試你的合約是如何接收以太幣的妨退,并且用 JavaScript
與 Solidity
交互妇萄。為了達(dá)到這目的,你需要在
Solidity
測試腳本中寫一個名為 initialBalance
的方法咬荷,并且返回 uint
冠句。
這可以直接寫為函數(shù)或公共變量,如下所示幸乒。當(dāng)你的測試合約被部署到網(wǎng)絡(luò)上時懦底,Truffle將從你的測試賬戶發(fā)送到你的測試合約。
你的測試合約中就可以使用這個以太幣來進(jìn)行測試罕扎。注意聚唐,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以不執(zhí)行回退函數(shù)的方式發(fā)送到測試合約,因此您仍然可以在固態(tài)測試中對高級測試用例使用回退函數(shù)宴咧。