Truffle-编写精准时间依赖测试

2019-08-13 10:57 栏目:经验之谈 来源: 查看()
当您在以太坊上构建工资单类型Dapp时,有必要编写准确的时间相关测试。 在开始之前,您需要构建的环境如下: ·您的测试框架是Truffle,Ganache + Mocha。 ·尽可能准确地测试(<5秒误差范围)。 在为以太坊智能合约编写的测试中操纵时间可能会导致问题。 陷阱#1:RPC 虽然可以在Ganache中前进和后退,但有很多方法可以实现这一点。要获得准确的结果,必须使用evm_mine RPC方法,如下所示: { 'jsonrpc':'2.0', 'method':'evm_mine', 'params': ['NUMBER_OF_SECONDS'], 'id': 1 } advanceBlockAtTime.json 另外作为javascript的许可证: Const advanceBlockAtTime=(time)=&gt; { 返回新的Promise((resolve,reject)=> { web3.currentProvider.send( { Jsonrpc:'2.0', 方法:'evm_mine', 参数: [时间], Id: new Date()。getTime(), }, (错误,_)=&gt; { 如果(错误){ 返回拒绝(错误); } Const newBlockHash=web3.eth.getBlock('latest')。hash; 返回解析(newBlockHash); }, ); }); }; advanceBlockAtTime.js 笔记: ·如果没有NUMBER_OF_SECONDS参数,则RPC调用仅增加块高度,但不会及时跳转。 ·“id”参数是可选的,但它很好。您在测试中输入的值无关紧要。还有evm_increaseTime,它添加了Ganache的“内部时钟”,以便在下一个块被挖掘时它具有时间戳偏移量。这增加了开销: //不是你想要的 advanceTimeAndBlock=async(time)=&gt; { 等待提前时间(时间) 等待advanceBlock() 返回Promise.resolve(web3.eth.getBlock('latest')) } advanceTimeAndBlock.js 没错,你必须进行两次RPC调用,第一种方法只需要完成一次。 Jakub Wojciechowski提出道具并为ganache-core提供PR#13。如果没有确定性和原子方法在Ganache中及时跳跃,那么编写准确的测试将很困难。 陷阱#2:运行时间 代码本身需要时间来执行。具体来说,Javascript许可需要不可忽视的时间来解决问题。 这很明显,对吗?在为以太坊智能合约编写与时间相关的测试时,事情变得非常微妙。 考虑以下: 1.测试用例运行所需的时间 2.您希望将来跳转的秒数 3.在控制台中提交纱线运行测试时的Unix时间戳 根据这些变量,您的测试块可能会在一秒或多秒内被捕获,因此您的断言可能会被中断。 例如: 描述('流确实开始但不结束',function(){ beforeEach(async function(){ 等待advanceBlockAtTime( 现在。再加(STANDARD_TIME_OFFSET)。再加(5) .toNumber(), ); }); 描述('当提取金额在可用余额内时',function(){ Const amount=new BigNumber(5).multipliedBy(1e18).toString(10); 它('取消',async function(){ Const balance=等待this.token.balanceOf(收件人); 等待this.sablier.withdraw(streamId,amount,opts); Const newBalance=await this.token.balanceOf(recipient); Balance.should.be.bignumber.equal(newBalance.minus(量)); }); }); }); makeWithdrawal.js 这样做是因为它要求Sablier合同撤回先前存入的余额。 ERC-1620指定调用者可以退出的规则数。 我在块之前记录了mocha unix时间戳,并使用节点的性能时序api测量了运行测试所需的时间: T0 1565455128964 调用sablier.withdraw取115.92673601210117毫秒。 1)退出 sablierWithdrawTest.txt 如果你添加115到156545128964,你最终得到一个以9079结尾的数字,所以秒数从8增加到9.这就是打破这个断言的原因,因为当我实际得到X + 1时我期望X的平衡。 (超过秒数=更多钱) 虽然编写可以计算另一个程序P2完成所需时间的程序P1是不可能的(参见图灵的暂停问题),但我们可以安全地假设你的beforeEach及其阻塞时间不应超过1秒。这假设您的节点实例和ganache之间的来回通信几乎是即时的,即使在运行覆盖时也是如此。 这是一个修复: Balance.should.bignumber.satisfy(function(num){ 回归( num.isEqualTo(newBalance.minus(amount))|| num.isEqualTo(newBalance.minus(量)。再加(ONE_UNIT)) ); }); makeWithdrawalFix.js 其中ONE_UNIT是每秒分配的货币单位,根据Sablier模型。它并不完美,但它比使用“大于”或“小于”相等的检查要好。 最后,正如OpenZeppelin团队在这里所说的那样,你可能不需要这种精度。如果您的dapp与时间戳或块号没有直接关系,则容忍更大的时间偏移是完全正常的。 陷阱#3:BeforeEach和AfterEach 您的里程可能会有所不同,但您可能希望在“beforeEach”中向前跳跃并在“afterEach”中向后跳跃。这是因为您的合同可能在“describe”块的范围内定义了一些变量,并且您希望运行一系列“it”块,所有块都具有相同的状态。不回复“afterEach”只会永远增加时间戳。 例如: 描述('流确实开始但不结束',function(){ Const amount=new BigNumber(5).multipliedBy(1e18).toString(10); beforeEach(async function(){ 等待web3.utils.advanceBlockAtTime( 现在。再加(STANDARD_TIME_OFFSET)。再加(5) .toNumber(), ); }); 它('test1',function(){}); 它('test2',function(){}); 它('test3',function(){}); afterEach(async function(){ 等待web3.utils.advanceBlockAtTime(now.toNumber()); }); }); beforeAfterEach.js 正如你在上面的代码片段中看到的,我们有三个测试,我们假设提取的数量是5.在Sabilier的上下文中,在15秒内前进将产生15秒的可提取量,所以我们必须返回“aftereach”区块中的原始状态。 陷阱#4:快照 所有测试完成后返回原始状态。它可能对CI或其他外部环境有帮助。 takeSnapshot=async()=&gt; { 返回新的Promise((resolve,reject)=> { web3.currentProvider.send( { Jsonrpc:'2.0', 方法:'evm_snapshot', Id: new Date()。getTime(), }, (错误,snapshotId)=> { 如果(错误){ 返回拒绝(错误); } 返回解析(snapshotId); }, ); }); }; revertToSnapshot=async(id)=&gt; { 返回新的Promise((resolve,reject)=> { web3.currentProvider.send( { Jsonrpc:'2.0', 方法:'evm_revert', 参数: [id], Id: new Date()。getTime(), }, (错误,结果)=> { 如果(错误){ 返回拒绝(错误); } 返回解决(结果); }, ); }); }; snapshotFunctions.js 在代码库中定义这些函数并将它们插入根测试文件中: 让快照; 让snapshotId; 之前(async()=> { Snapshot=等待takeSnapshot(); snapshotId=snapshot.result; }); 之后(async()=&gt; { 等待revertToSnapshot(snapshotId); }); truffleSnapshots.js 现在,在所有神奇的时间跳跃之后,您的区块链将恢复到其原始时间戳。 本文中使用的一些零碎内容受到启发或从其他作品中获取,例如Ethan Wessel令人惊叹的“使用松露的测试时间”。本文中唯一的警告是使用evm_mine和evm_increaseTime,我们在上面解释了这是不理想的原因。 此外,这是一个非常好的StackExchange线程,具有block.timestamp和一些GitHub线程的固有安全性,它揭示了Ganache(1和2)中确定性跳时的历史。
微信二维码
售前客服二维码

文章均源于网络收集编辑侵删

提示:仅接受技术开发咨询!

郑重申明:资讯文章为网络收集整理,官方公告以外的资讯内容与本站无关!
NFT开发,NFT交易所开发,DAPP开发 Keywords: NFT开发 NFT交易所开发 DAPP开发