mocha测试框架-truffle

时间:2022-05-05 09:26:08

https://mochajs.org/
学习网址:
https://www.jianshu.com/p/9c78548caffa
https://www.jb51.net/article/106463.htm
在truffle框架的简单使用中,我们了解到它的测试模块是包装了mocha测试框架的,在这里我们选择cryptopunks的truffle例子来相应讲解:

https://github.com/larvalabs/cryptopunks

为什么要使用mocha这个测试模块:

当我们在开发,我们往往会有以下的问题:

参考:https://blog.csdn.net/imwebteam/article/details/53310958

需求和开发脱节

当一份需求来了, 开发人员往往不能百分百的理解需求的内容(抛弃产品自己变更需求的可能性。。),这往往会让开发人员开发出的功能会有跟需求有所差别,这会带来额外的工作量

开发和测试脱节

什么是开发和测试脱节,说的是,当开发人员按照自己的想法开发完了一个需求。然后测试人员也按照自己的想法去测试这个需求,然后由于双方的分歧,导致测试认为开发有bug,开发认为测试是sb.

那么如何解决上面的问题呢?

答案就是 选择一种软件敏捷开发模式

敏捷开发模式

目前比较流行的开发模式有两种: TDD 和 BDD

TDD (Test Driven Development 测试驱动开发)

  • 测试来驱动开发
  • 其重点偏向开发
  • 测试用例是在约束开发者,使开发者的目标明确,设计出满足需求的系统

BDD (Behaviour Driven Development 行为驱动开发)

  • 基于TDD发展,保持测试先行的理念
  • 其重点偏向设计
  • 在测试代码中用一种自然通用语言的方式把系统的行为描述出来
  • 将系统的设计和测试用例结合起来,进而驱动开发工作

两种方式各有其特点,我们通常选择的是BDD的方式

为了方便我们编写测试用例,我们需要使用一些前端测试用例工具——mocha

在这个例子中我们能够看见在其的test文件夹中写了一些测试文件,比如我们以cryptopunksmarket-setinitia.jsl这个文件为例,看cryptopunks测试代码cryptopunksmarket-setinitial.js

(1)Truffle测试框架学习:

参考:http://www.blockchainbrother.com/article/2082

Truffle 使用 Mocha 测试框架 和 Chai 断言来给你提供一个可靠的框架编写JavaScript测试。这里需要注意到的一个很大的不同是它使用了contract()测试套件替代了describe()测试套件,这个函数基本和 describe() 一样,只不过它可以启用clean-room 功能.  其过程如下:

     1. 每次contract()函数运行之前,您的合约会被重新部署到正在运行的以太坊客户端,因此测试是在一个干净的合约环境下进行的。
     2. 这个contract()函数提供一个由您的以太坊客户端生成的,可以在编写测试合约使用的账户列表。
比如:
contract('CryptoPunksMarket-setInitial', function (accounts) {});
在这里accounts就是会返回在区块链环境上的所有用户的账户来让测试使用
如果您不需要一个清洁的测试环境,那么您仍然可以使用describe()函数来运行普通的Mocha测试。
Truffle 无法检测出在测试中需要与哪些合约进行交互,所以您需要明确地指出这些合约。您可以使用一个由Truffle提供的方法 artifacts.require()来做这些事情,它可以让您为一个特定的合约,请求一个可用的合约抽象。
比如:var CryptoPunksMarket = artifacts.require("./CryptoPunksMarket.sol");
在测试中使用artifacts.require()的方式和在迁移中使用的方式相同,您只需要指定合约名称,比如:
var CryptoPunksMarket = artifacts.require("CryptoPunksMarket");
CryptoPunksMarket就是在contracts文件夹中的智能合约文件的名字
因为truffle中已经将断言库 Chai 也包装了进去,所以当想使用断言,如assert时,可以直接使用,不用导入模块
其他的部分基本上就与mocha相同了,详细内容继续往下看

(2)后面想要使用测试框架mocha,但是又不想使用truffle,所以就来学习这个框架怎么单独使用了,下面就是学习的过程:
当然,首先要安装:

使用npm全局安装:
npm install --g mocha
或者仅仅只是安装在某个模块:

npm install --save mocha
然后你就可以使用了

1.要测试上面的代码是否对的,因此就要编写测试脚本,测试脚本与所要测试的源码脚本同名,但是后缀名为 .test.js或 .spec.js, 如:xx.test.js 或 xx.spec.js

2.测试脚本可以包含一个或多个describe块,describe块称为 "测试套件",表示一组相关的测试,它是一个函数,有两个参数,第一个参数是测试套件的名称,第二个参数是一个实际执行的函数。
每个describe块也可以包含一个或多个it块,it块称为 “测试用例",表示一个单独的测试,是测试的最小单位,它也是一个函数,第一个参数也是测试用例的名称,第二个参数是一个实际执行的函数,it块之间是同步运行的。

describe 和 it 大量嵌套后,就形成了一颗树。树的非叶子节点都是测试集合,叶子节点即 it ,就是测试用例。

注意,如果一个describe 里面没有 it (比如下面:), Mocha将不会执行这个 describe。

3.理解断言库

学习文档:http://www.chaijs.com


断言库可以理解为比较函数,也就是断言函数是否和预期一致,如果一致则表示测试通过,如果不一致表示测试失败。mocha本身是不包括断言库的,所以必须引入第三方断言库的,目前比较受欢迎的断言库有
should.js, expect.js, chai.
should.js是BDD风格
expect.js是expect风格的断言
//下面介绍的是chai


chai的expect(), assert() 和
should的断言
Mocha默认使用的是BDD的风格。expect和should都是BDD的风格,二者使用相同的链式语言来组织断言的,但不同在于他们初始化断言的方式,expect使用
构造函数来创建断言对象实例,而should通过为
Object.prototype新增方法来实现断言(should不支持IE),expect直接指向 chai.expect,
should则是
chai.should();
上面的代码中 expect 是断言的意思,该作用是判断源码的实际执行结果与预期结果是否一致,如果不一致就抛出一个错误

三种的使用方法简单如下所示:

var expect = require('chai').expect;

expect(2).to.be.equal(2);

var assert = require('chai').assert;

assert.equal((await contract.totalSupply()).toNumber(), 10);

var should = require('chai').should();

cookies.should.not.be.empty;

cookies.id.should.equal('10001','not equal to 10001');

因此在执行上面代码之前,
我们需要在项目中安装 chai, 如下命令:
npm install --save-dev chai

1)var expect = require('chai').expect;
即引用 chai 断言库,使用的是 expect断言风格。
expect 官网API(http://chaijs.com/api/bdd/).

2)mocha测试代码如何运行?
上面的add.test.js 编写完成后,我们需要运行测试代码了,进入add.test.js代码的目录后,执行如下命令可运行:
mocha add.test.js

mocha命令后面也可以指定多个文件,如下命令:
mocha xx.test.js yy.test.js
使用通配符:
或者我们可以运行如下命令,执行多个测试脚本文件:
mocha spec/{add,reduce}.js //目录spec下的add.js和reduce.js文件
mocha spec/*.js //所有文件
mocha默认运行test子目录里面的测试脚本,我们一般情况下,可以把测试脚本放在test目录下,然后进入test的上层目录,直接执行mocha命令即可:
mocha
然后你就会发现test目录下第一层的所以测试文件都被运行了。命令只会执行test第一层目录下所有文件,并不能执行嵌套目录下的文件。
为了执行所有嵌套目录下的文件,我们可以 mocha命令后面加一个参数 --recursive 参数
更多的细节信息可以看:https://www.cnblogs.com/tugenhua0707/p/8419534.html,当然之后你要补充一下

3)测试用例的钩子
Mocha在describe块之中,提供了测试用例的四个钩子,before(), after(), beforeEach()和afterEach(),他们会在指定的时间内执行。
before(): 将会在所有测试用例执行之前运行,比如在之前插入数据等等操作。
after(): 会在所有测试执行之后运行,用于清理测试环境,回滚到清空数据状态。
beforeEach(): 将会在每个测试用例执行之前执行,可用于测试测试需要准备相关数据的条件。
afterEach(): 将会在每个测试用例之后执行,可用于准备测试用例所需的后置条件。

4)理解异步钩子函数
例子1:
var expect = require('chai').expect;
describe('异步钩子函数', function() {
  var foo = false;
  beforeEach(function(){
    setTimeout(function(){
      foo = true;
    }, 50)
  });
  it('异步钩子函数成功', function() {
    expect(foo).to.be.equal(true);
  })
});

结果:
异步钩子函数
       异步钩子函数成功:

AssertionError: expected false to equal true
      + expected - actual

-false
      +true

如上可以看到测试失败,原因是因为setTimeout 是异步的,在setTimeout执行完之前,it函数已经被执行了,所以foo当时数据还是false,
因此false不等于true了。

这时候 done参数出来了,在回调函数存在时候,它会告诉mocha,你正在编写一个异步测试,会等到异步测试完成的时候来调用done函数,或者超过2秒后超时,如下代码就可以成功了;
var expect = require('chai').expect;
describe('异步钩子函数', function() {
  var foo = false;
  beforeEach(function(done){
    setTimeout(function(){
      foo = true;
      // complete the async beforeEach
      done();
    }, 50)
  });
  it('异步钩子函数成功', function() {
    expect(foo).to.be.equal(true);
  });
});

(3)这篇文章不是要很详细地告诉大家概念性的内容,只是让有跟我一样想法(即学习了truffle框架后,发现里面的那个测试十分有意思,想之后做测试的时候也用这种测试方法),但是突然不知道怎么入手的人一个方向,知道那是个什么测试框架,以及去哪里学习,以及一些比较简单的必须知道的概念和内容,知道这些其实你就可以写一个十分简单的测试例子了,建议结合别人的测试代码进行学习,如https://github.com/larvalabs/cryptopunks/tree/master/test

在下面进行测试:

1)一开始,当我想要直接复制truffle中写好的测试文件,进行小部分更改直接进行使用时,发现出错:

truffle中只需要这两句话就可以部署好合约,但是在没框架的情况下是不可以的
var testToken = artifacts.require(“./test-punk.sol”);
instance = await testToken.deployed(50);

这样会报错:
1.ReferenceError: artifacts is not defined
2.(function (exports, require, module, __filename, __dirname) { pragma solidity ^0.4.20;
                                                                     ^^^^^^^^
SyntaxError: Unexpected identifier

所以这就说明了在框架外是不可以这样子进行合约的编译的

通过上面我们就能够知道truffle到使用上面两句部署指令前,还进行了编译compile和部署migrate,所以在测试前要将合约的编译和部署都弄好,你可以通过查看我写的remix的使用来学怎么使用remix进行编译和部署或者是看nodejs部署智能合约的方法来自己编写代码进行编译和部署,最终得到合约的部署地址NFMAddress

部署成功后,之后如果想在别的地方进行使用,需要以下几句话句话:

const NFMAbi = require("./testToken.json");//合约生成的Abi,一般为json文件

const NFMContract = web3.eth.contract(NFMAbi);
const instance = NFMContract.at(NFMAddress);

此时就能够调用该函数中的函数及变量了

2)其次,还要记得将相应的模块包下载下来,这里要添加package.json文件配置等内容

Error: Cannot find module ‘web3'
你安装的web3一定要放在本地的node_modules文件夹下,不然是读不出来的

3)使用nodejs来进行合约的编译和部署时,发现出现下面的错误
1.let abi = compiledContract.contracts['testToken'].interface;
出错:
TypeError: Cannot read property 'interface' of undefined

然后输出compiledContract进行查看
2.console.log(compiledContract);
发现在编译处就出错了
{ contracts: {},
  errors:
   [ ':49:17: ParserError: Expected identifier, got \'LParen\'\n    constructor (uint number) public{\n                ^\n' ],
  sourceList: [ '' ],
  sources: {} }
还有:
{ contracts: {},
  errors:
   [ ':26:9: TypeError: Wrong argument count for function call: 2 arguments given but expected 1.\n        require(propertyValueToOwner[propertyValue] == 0x0,\'this is not the first-sell\');\n        ^------------------------------------------------------------------------------^\n',
发现可能是版本的问题,因为这里声明构造函数使用了新的声明方式,但是在这里没能被识别出。所以下载了新版本的solc,然后就成功了

4)

contract('testToken',async (accounts) => {
出错:ReferenceError: contract is not defined
因为contract是truffle框架弄的,不在框架中是不能够这样使用的,这时候想要使用账号只能老实地连接区块链,通过web3模块去调用API接口

var Web3 = require("web3");

web3.setProvider(new Web3.providers.HttpProvider("http://localhost:8201"));

account1 = web3.eth.accounts[0];

5)最后运行结果也有问题:
用户deMBP:testToken 用户$ mocha test-mocha.js

testToken Test
check tokenNumber
    1) deploy contract
    2) sell token
    3) buy token
    4) check the balance
    5) withdrawl the balance

0 passing (118ms)
  5 failing

1) testToken Test
       deploy contract:
     TypeError: Cannot read property 'call' of undefined
      at Context.<anonymous> (test-mocha.js:56:43)

2) testToken Test
       sell token:
     TypeError: Cannot read property 'sellToken' of undefined
      at Context.<anonymous> (test-mocha.js:77:19)

3) testToken Test
       buy token:
     TypeError: Cannot read property 'testTokenIdToOwner' of undefined
      at Context.<anonymous> (test-mocha.js:90:25)

4) testToken Test
       check the balance:
     TypeError: Cannot read property 'pendingDrawalOfUser' of undefined
      at Context.<anonymous> (test-mocha.js:112:38)

5) testToken Test
       withdrawl the balance:
     TypeError: Cannot read property 'pendingDrawalOfUser' of undefined
      at Context.<anonymous> (test-mocha.js:124:31)

Contract mined! address: 0x3cb4464f73eda60ac3ba1d46cd0544cd7ae18040 transactionHash: 0x62f27e3ccdfcb6ba54547107bbc8f1f9f152f0f588eddec9b1dc3a65d1d7d047

后面发现这个原因是部署回调得到instance前,it函数中的内容就已经开始调用了,这样的话怎么着instance都是undefined的,那么肯定是不可能能够调用合约中的函数的。而且在这里将部署函数放在了一个单独的it测试用例当中,但是下面的测试用例都是应该等待部署完成后才能够测试成功的,那么这样就不可能成功测试了,因为it测试用例是同步进行的,在部署的同时,其他测试用例也都开始运行了,⚠️有前后关系的测试内容应该要写在一个测试用例当中。

所以就不做在这之前进行部署的事情了,毕竟我们肯定在测试之前是已经把合约部署上去的了,那么只要用
let instance = MyContract.at('0x86757c9bdea10815e7d75a1577b6d9d2825dae0a');
这句话就行了

6)然后再运行也出错:
mocha Error: Timeout of 2000ms exceeded.
则需要你再运行的时候添加
mocha -t 20000 test.js
因为其默认的时间是2000ms,你的时间如果过大,可以进行自己设置

7)当你使用describe这些mocha的形式语句的时候,使用node test.js是不能运行成功的,会返回错误:

用户MBP:testToken 用户$ node test.js
/Users/用户/testToken/test.js:165
describe('testToken',function(){
^
ReferenceError: describe is not defined

所以一定要用mocha开头,mocha test.js

实现:

const debug = require("debug")("testToken");
const assert = require('assert')
// var testToken = require("./test-punk.sol");
const Web3 = require('web3');
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider('http://127.0.0.1:7545'));
const fs = require("fs");
const solc = require("solc");
let source = fs.readFileSync("testToken.sol",'utf8');//read file
let compiledContract = solc.compile(source,1);//compile
// console.log(compiledContract); for (let contractName in compiledContract.contracts) {
console.log("in");
var bytecode = compiledContract.contracts[contractName].bytecode;
var abi = JSON.parse(compiledContract.contracts[contractName].interface); //将abi写成json形式
console.log("out"); }
// 你要测试的是接口
// console.log(bytecode);
// console.log(abi); let gasEstimate = web3.eth.estimateGas({data:'0x'+bytecode});
let MyContract = web3.eth.contract(abi);
debug("deploying contract");
// let instance;
let instance = MyContract.at('0x86757c9bdea10815e7d75a1577b6d9d2825dae0a');//可改 var user1 = web3.eth.accounts[0];
console.log(user1);
var user2 = web3.eth.accounts[1];
var user3 = web3.eth.accounts[2];
var user4 = web3.eth.accounts[3];
var user5 = web3.eth.accounts[4];
var propertyValues = ['0x00000001','0x00000002','0x00000003','0x00000004','0x00000005'];
var prices = [11,12,13,14,15];
var users = [user1,user2,user3,user4,user5]; //这个地方是想要在这里同时部署合约,但是发现总是不成功,部署异步总是太慢,before()函数好像也没有什么用,所以后面我也只能放弃部署了,只能先部署完得到地址再来调用了
// function deployContract() {
// instance = MyContract.new(50,{from:user1,data:'0x'+bytecode,gas:47000000},function(e,contract){
// if(typeof contract.address !== 'undefined'){
// console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
// }
// });
// }
// before(deployContract);
// var instance;
describe("testToken Test",function(){ // it("deploy contract",async function(){ it("contract begin",async function(){ let num = propertyValues.length;
// instance = await testToken.deployed(50); console.log(instance.address);
console.log('check tokenNumber');
console.log(await instance.tokenNumber.call());
debug("create token");
     //首先先创建5个token
for(let i=0; i<num; i++){
await instance.create(propertyValues[i],prices[i],{from:users[i],value:prices[i],gas:30000000});
} debug("display token");
     //然后查看生成的token的属性
let nextTokenId = await instance.nextTokenToCreate.call();
console.log("nextTokenId is :"+ nextTokenId); if(parseInt(nextTokenId) != 5){
console.log("initial token failed");
}else{
for(let i =0; i<num; i++){
console.log(await instance.propertyOfToken.call(i));
} }
});
  //然后sell token
it("sell token",async function(){
await instance.sellToken(0,21,{from:user1,gas:30000000});
await instance.sellToken(1,22,{from:user2,gas:30000000});      //查看是否成功sell
console.log(await instance.tokenIdToSell.call(0));
console.log(await instance.tokenIdToSell.call(1)); });
   //其他用户对sell的token进行购买
it("buy token",async function(){
     //查看购买前token的拥有者是谁
console.log(instance.testTokenIdToOwner.call(0));
console.log(instance.testTokenIdToOwner.call(1)); await instance.buyToken(0,{from:user3,value:21,gas:30000000});
await instance.buyToken(1,{from:user4,value:22,gas:30000000}); let buyer1 = await instance.testTokenIdToOwner.call(0);
let buyer2 = await instance.testTokenIdToOwner.call(1);
    //查看购买后的拥有者是谁来核实购买成功进行
console.log(buyer1);
console.log(buyer2); console.log("check the sell after buying");
console.log(await instance.tokenIdToSell.call(0));
console.log(await instance.tokenIdToSell.call(1)); assert.equal(buyer1,user3,"buying 0 is failed");
assert.equal(buyer2,user4,"buying 1 is failed"); });
   //查看用户临时账户中此时有多少积蓄
it("check the balance",async function(){
let user1Balance = await instance.pendingDrawalOfUser.call(user1);
let user2Balance = await instance.pendingDrawalOfUser.call(user2); console.log(user1Balance);
console.log(user2Balance); assert.equal(user1Balance,21,"user1 balance number is not right");
assert.equal(user2Balance,22,"user1 balance number is not right"); });
  //然后将临时账户中的钱转到钱包中
it("withdrawl the balance",async function(){
console.log(await instance.pendingDrawalOfUser.call(user1));
console.log(await instance.pendingDrawalOfUser.call(user2)); await instance.withdrawl({from:user1,gas:30000000});
await instance.withdrawl({from:user2,gas:30000000}); console.log(await instance.pendingDrawalOfUser.call(user1));
console.log(await instance.pendingDrawalOfUser.call(user2)); }); }); 结果是:
用户deMBP:testToken 用户$ mocha test-mocha.js
in
out
0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8 testToken Test
0x86757c9bdea10815e7d75a1577b6d9d2825dae0a
check tokenNumber
BigNumber { s: 1, e: 1, c: [ 50 ] }
nextTokenId is :5
//生成的token的属性
[ BigNumber { s: 1, e: 0, c: [ 0 ] },
'0x0000000100000000000000000000000000000000000000000000000000000000',
'0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8',
BigNumber { s: 1, e: 1, c: [ 11 ] } ]
[ BigNumber { s: 1, e: 0, c: [ 1 ] },
'0x0000000200000000000000000000000000000000000000000000000000000000',
'0x7ddad6a67544efb0c51808c77009a7b98cc81630',
BigNumber { s: 1, e: 1, c: [ 12 ] } ]
[ BigNumber { s: 1, e: 0, c: [ 2 ] },
'0x0000000300000000000000000000000000000000000000000000000000000000',
'0xe9478ebcf4c755ad945a351261c8fa046672963b',
BigNumber { s: 1, e: 1, c: [ 13 ] } ]
[ BigNumber { s: 1, e: 0, c: [ 3 ] },
'0x0000000400000000000000000000000000000000000000000000000000000000',
'0x920f422b761976972a9eadbec1f5341a9747ea6a',
BigNumber { s: 1, e: 1, c: [ 14 ] } ]
[ BigNumber { s: 1, e: 0, c: [ 4 ] },
'0x0000000500000000000000000000000000000000000000000000000000000000',
'0xa17a7fa74a7dd57dff005b45234292e7daaf150c',
BigNumber { s: 1, e: 1, c: [ 15 ] } ]
✓ contract begin (1541ms)
//
[ true,
'0x0000000100000000000000000000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 0 ] },
'0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8',
BigNumber { s: 1, e: 1, c: [ 21 ] } ]
[ true,
'0x0000000200000000000000000000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 1 ] },
'0x7ddad6a67544efb0c51808c77009a7b98cc81630',
BigNumber { s: 1, e: 1, c: [ 22 ] } ]
✓ sell token (663ms)
0x3455f15cc11f2e77c055f931a6c918ccc7c18fd8
0x7ddad6a67544efb0c51808c77009a7b98cc81630
0xe9478ebcf4c755ad945a351261c8fa046672963b
0x920f422b761976972a9eadbec1f5341a9747ea6a
check the sell after buying
[ false,
'0x0000000100000000000000000000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 0 ] },
'0x0000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 0 ] } ]
[ false,
'0x0000000200000000000000000000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 1 ] },
'0x0000000000000000000000000000000000000000',
BigNumber { s: 1, e: 0, c: [ 0 ] } ]
✓ buy token (954ms)
BigNumber { s: 1, e: 1, c: [ 21 ] }
BigNumber { s: 1, e: 1, c: [ 22 ] }
✓ check the balance (206ms)
BigNumber { s: 1, e: 1, c: [ 21 ] }
BigNumber { s: 1, e: 1, c: [ 22 ] }
BigNumber { s: 1, e: 0, c: [ 0 ] }
BigNumber { s: 1, e: 0, c: [ 0 ] }
✓ withdrawl the balance (631ms) 5 passing (4s)

注意:在这里看好像这个例子也能够顺序执行,但是后面发现上面例子的所以it应该合成一个it来写,不然顺序是不一定能保证的,因为it测试用例在运行时是同步运行的,但是我这里的测试用例其实是有希望它按照顺序来运行,所以改为:

describe("testToken Test",function(){

    it("contract begin",async function(){

        let num = propertyValues.length;
// instance = await testToken.deployed(50); console.log(instance.address);
console.log('check tokenNumber');
console.log(await instance.tokenNumber.call());
debug("create token");
     //首先先创建5个token
for(let i=0; i<num; i++){
await instance.create(propertyValues[i],prices[i],{from:users[i],value:prices[i],gas:30000000});
} debug("display token");
     //然后查看生成的token的属性
let nextTokenId = await instance.nextTokenToCreate.call();
console.log("nextTokenId is :"+ nextTokenId); if(parseInt(nextTokenId) != 5){
console.log("initial token failed");
}else{
for(let i =0; i<num; i++){
console.log(await instance.propertyOfToken.call(i));
} } //然后sell token
await instance.sellToken(0,21,{from:user1,gas:30000000});
await instance.sellToken(1,22,{from:user2,gas:30000000});      //查看是否成功sell
console.log(await instance.tokenIdToSell.call(0));
console.log(await instance.tokenIdToSell.call(1)); //其他用户对sell的token进行购买
     //查看购买前token的拥有者是谁
console.log(instance.testTokenIdToOwner.call(0));
console.log(instance.testTokenIdToOwner.call(1)); await instance.buyToken(0,{from:user3,value:21,gas:30000000});
await instance.buyToken(1,{from:user4,value:22,gas:30000000}); let buyer1 = await instance.testTokenIdToOwner.call(0);
let buyer2 = await instance.testTokenIdToOwner.call(1);
    //查看购买后的拥有者是谁来核实购买成功进行
console.log(buyer1);
console.log(buyer2); console.log("check the sell after buying");
console.log(await instance.tokenIdToSell.call(0));
console.log(await instance.tokenIdToSell.call(1)); assert.equal(buyer1,user3,"buying 0 is failed");
assert.equal(buyer2,user4,"buying 1 is failed");    //查看用户临时账户中此时有多少积蓄
let user1Balance = await instance.pendingDrawalOfUser.call(user1);
let user2Balance = await instance.pendingDrawalOfUser.call(user2); console.log(user1Balance);
console.log(user2Balance); assert.equal(user1Balance,21,"user1 balance number is not right");
assert.equal(user2Balance,22,"user1 balance number is not right");      //然后将临时账户中的钱转到钱包中
console.log(await instance.pendingDrawalOfUser.call(user1));
console.log(await instance.pendingDrawalOfUser.call(user2)); await instance.withdrawl({from:user1,gas:30000000});
await instance.withdrawl({from:user2,gas:30000000}); console.log(await instance.pendingDrawalOfUser.call(user1));
console.log(await instance.pendingDrawalOfUser.call(user2));
}); });