建议和反馈

请填写你的反馈内容

以太坊智能合约的测试

2019-12-02 ·959次阅读 ·读完需要13分钟

其实本章另外还有web3的调用方法,但因为从没使用过nodejs做应用,我一直也没用过web3的方式调用。所以就先删掉了。

truffle的安装与使用

项目地址:http://truffleframework.com/

项目文档:http://truffleframework.com/docs/

truffle是一个去中心化应用的开发框架,也可以被用来测试、部署智能合约。项目说明里说自己为一个开发环境[目瞪狗呆脸]。但是我必须得说现在连UltraEdit都比它更像个IDE好吧?不过目前来看,还是最好用的一个DAPP(decentralized application去中心化应用)开发环境。

类似的项目有dapple(项目文档:http://dapple.readthedocs.io/en/master/)以及以太坊官方的meteor(项目文档:https://github.com/ethereum/wiki/wiki/Dapp-using-Meteor)。功能上都大同小异,如果有机会可以再试用一下,写相关的说明文档。

1 truffle安装与配置

1.1前置需求

nodejs5.0+

安装nodejs,需要去官网(nodejs.org)下载安装。在几年9月份,nodejs最新版本是6.8,推荐版本是4.5;到笔者发稿时,最新版本已经是7.0+,推荐版本是6.9了。所以考虑到比较高频率的版本更新,安装方法请直接参考官网。

1.2 truffle安装

使用npm安装

npm install -g truffle

2 truffle的使用

truffle是一个构建DAPP(decentralized application去中心化应用)的快捷工具。它主要由几个工具组成

2.1创建新项目

init命令的作用是在当前目录下建立一个truffle项目。在执行该命令之前,强烈建议先建立一个新目录。

$ mkdir myproject

$ cd myproject

$ truffle init

truffle项目的目录结构包括:

-app/:dapp目录,默认生成的dapp的建立目录;

-contracts/:合约目录,用于存放合约;

-migrations/:部署目录,用于存放部署合约用的脚本;

-test/:测试目录,用于存放测试应用程序和合约用的脚本;

-truffle.js-Truffle配置文件。

tips:在执行truffle init命令的时候,目录中会有一个范例项目MetaCoin。有兴趣的读者可以看一看这个项目的构成,本文在稍后的章节也会略微介绍一下这个项目。

2.2编译合约

在之前init建立的路径下执行编译命令。

$ truffle compile

编译所有位于contracts目录下的.sol文件,并生成相应的js文件,放入./build/contracts目录下。

需要注意的是,在编译合约时,合约文件中,必须存在与文件名完全一致的合约(包括大小写)。这句话的意思是,如果我的文件名叫MyContract.sol,那么这个文件中必须包含一个叫MyContract的合约,就像这样:

contract MyContract{

...

}




作者:gloriow
链接:https://www.jianshu.com/p/b2326d7be151
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

或者

library MyContract{

...

}

如果合约之间存在import依赖,那么也没关系,compile命令会自动按顺序来处理。

tips:第二次执行truffle compile命令时,只会编译那些与第一次编译相比有改动的合约。如果要强制全部编译,加上--compile-all选项。

tips:我经常用不到compile命令,而使用build命令代替。如果不构建基于javascript的去中心化app,只是测试智能合约的时候,使用二者是等同的。

2.3构建去中心化应用

在之前init建立的路径下执行构建命令。

$ truffle build

build命令的作用是构建去中心化应用。其作用是,首先执行编译合约,将生成合约的js文件放入./build/contracts/路径下(这一步与truffle compile功能一样)。之后将./app/目录下的文件拷贝到./build/目录下。

./app/目录结构如下:

app/

- javascripts/

- app.js

- stylesheets/

- app.css

- images/

- index.html

在配置文件truffle.js中,有一段代码是这样的:

build:{

"index.html": "index.html",

"app.js": [

"javascripts/app.js"

],

"app.css": [

"stylesheets/app.css"

],

"images/": "images/"

},

这段代码代表执行build命令时,会做出这样的操作:

(1)把./app/index.html拷贝到./build/index.html

(2)将app.js后面数组中的所有文件连接到一起(当前只有./javascripts/app.js一个文件),生成一个app.js文件。

tips:默认项目的./app/javascripts/app.js只有55行,而生成的app.js有44024行。前面的将近44000行代码,全部都是建立web3对象等等等等前置需求。最后把那55行代码复制到文件末尾……

(3)将app.css后面数组中的所有文件连接到一起(当前只有./stylesheets/app.js一个文件),生成一个app.css文件。

(4)将./app/images目录拷贝到./build/images

我们可以看到这里有个index.html。实际上,我们构建成功的应用,就是一个网站。如果要使用这个网站,需要之后执行serve命令。

2.4部署合约

2.4.1部署合约

在之前init建立的路径下执行部署命令。

$ truffle migrate

作用是执行migrations文件夹中的js脚本,通常功能是部署合约。其中migrations目录下的文件名称前缀必须是一个数字,部署时按顺序执行。在建立项目(init)时,会自动默认生成migration合约,其作用是将migrate的历史记录保存到区块链中。用来记录Migrate命令是否执行成功。

具体执行的脚本可以参考默认生成的项目脚本。比如,要部署一个叫做MyContract的合约,其Migration中就可以新建一个prefixNum_example_migration.js文件,内容如下:

module.exports = function(deployer) {

// deploymentsteps

deployer.deploy(MyContract);

};

Truffle要求我们在使用Migration机制的时候,必须使用Migration合约,这个Migration合约中会保存若干特殊的接口。正常情况下,这个Migration合约是第一个被部署的,而且以后再也不会被执行。

tips:如果第一次执行成功,第二次执行truffle migrate命令时,只会执行新的合约部署。如果要强制重新部署,要加上--reset选项。

./contracts/Migrations.sol合约内容如下:

contract Migrations {

addresspublic owner;

// Afunction with the signature `last_completed_migration()`, returning a uint, is required.

uintpublic last_completed_migration;

modifierrestricted() {

if(msg.sender == owner) _

}

functionMigrations() {

owner= msg.sender;

}

// Afunction with the signature `setCompleted(uint)` is required.

functionsetCompleted(uint completed) restricted {

last_completed_migration= completed;

}

functionupgrade(address new_address) restricted {

Migrationsupgraded = Migrations(new_address);

upgraded.setCompleted(last_completed_migration);

}

}

为了部署它,./migrations/1_initial_migration.js文件内容如下:

module.exports = function(deployer) {

deployer.deploy(Migrations);

};

2.4.2 deployer对象的使用

如果有两个合约A和B,在Migrations目录下的脚本中写入这样的代码

deployer.deploy(A);

deployer.deploy(B);

它们会按顺序先部署合约A,后部署合约B。

如果合约B的部署需要合约A的地址怎么办呢?Truffle也可以实现先部署合约A,再部署合约B,同时将A的地址传入。

deployer.deploy(A).then(function() {

returndeployer.deploy(B, A.address);

});

我们还可以在部署合约的时候,要求目标网络畅通:

module.exports = function(deployer, network){

// Adddemo data if we're not deploying to the live network.

if(network != "live") {

deployer.exec("add_demo_data.js");

}

}

到这里,我们可以看到deployer对象有很多的api接口,在这里列举一下。

(1)deployer.deploy(contract, args...)

在部署合约的时候,有些合约可能会需要一些参数,有些不需要,这些参数会作为合约构造函数的传入参数保存下来。那么我们部署合约的时候,就需要满足构造函数的要求。

示例代码:

//如果合约A的构造函数没有参数

deployer.deploy(A);

//如果合约A的构造函数有多个参数。

deployer.deploy(A, arg1, arg2, ...);

//如果同时部署多个合约。这样可以发起一个批量请求,而不是三个单独的请求。

deployer.deploy([

[A,arg1, arg2, ...],

B,

[C,arg1]

]);

(2)deployer.link(library, destinations)

将一个已经部署的合约库Library,链接到一个或多个合约。

示例代码:

// Deploy library LibA, then link LibA to contractB

deployer.deploy(LibA);

deployer.link(LibA, B);

// Link LibA to many contracts

deployer.link(LibA, [B, C, D]);

(3)deployer.autolink(contract)

自动将某个合约,链接到它依赖的已经部署的合约库Library

示例代码:

// Assume A depends on a LibB and LibC

deployer.deploy([LibB, LibC]);

deployer.autolink(A);

// Link *all* libraries to all available contracts

deployer.autolink();

(4)deployer.then(function() {...})

这个就像是一个条件,感受一下……

示例代码:

deployer.then(function() {

// Createa new version of A

returnA.new();

}).then(function(instance) {

// Setthe new instance of A's address on B.

varb = B.deployed();

returnb.setA(instance.address);

});

(5)deployer.exec(pathToFile)

示例代码:

deployer.exec("../path/to/file/demo_data.js");

部署的时候,执行程序。

2.5去中心化应用测试

在之前init建立的路径下执行测试命令。

$ truffle test

作用是执行test目录下的全部脚本文件(js/es/es6/jsx),通常功能是测试合约。

$ truffle test ./path/to/test/file.js

作用是执行指定路径下的测试脚本文件。

这些脚本应以contract()函数开头。(然而亲测不使用contract函数开头也不会报错……)contract()函数提供两个特性,①在运行脚本之前会重新部署合约,②可以输入账户地址。

这里给一个默认例子,作用是先部署合约,之后执行it块内的代码。

contract('MetaCoin', function(accounts) {

it("should put 10000 MetaCoin in thefirst account", function() {

// Get a reference to the deployed MetaCoincontract, as a JS object.

var meta = MetaCoin.deployed();

// Get the MetaCoin balance of the firstaccount and assert that it's 10000.

return meta.getBalance.call(accounts[0]).then(function(balance){

assert.equal(balance.valueOf(),10000, "10000 wasn't in the first account");

});

});

});

2.6与合约交互

(暂略)

2.7提供服务

$ truffle serve

作用是提供对外服务,启动truffle项目服务,部署到http 8080端口上。在build应用之后,项目的build目录下已经有了一个index.html、js脚本以及相应的网站设计css文件。如何把这个项目部署到Tomcat服务器上呢?只需要运行本命令就可以了!

2.8去中心应用MetaCoin

MetaCoin合约是Truffle默认建立的一个项目,简单的说,它是一个代币合约,类似于比特币,是基于智能合约建立的一种用于支付的数字货币。

2.8.1如何运行MetaCoin示例项目

简单的说,按照如下的步骤即可生成:

(1)建立目录

$ mkdir truffletest

$ cd truffletest

(2)建立项目

$ truffle init

(3)构建应用

$ truffle build

(4)部署合约

$ truffle migrate

(5)提供服务

$ truffle serve

打开浏览器,访问http://localhost:8080就可以运行这个去中心化应用了。


 

(默认项目MetaCoin的网站是这样子的,这里因为没有部署合约,显示的有点问题,正常情况下会显示有多少meta代币)

之后可以运行一些转账给另一个账户之类的功能。

2.9测试智能合约的简单说明

(1)建立项目

$ truffle init

(2)编写合约,将合约文件(*.sol)拷贝到./contracts目录下

(3)编译合约

$ truffle build

(4)修改配置

修改truffle.js,要部署的目标ip和端口,比如使用本地测试区块链testrpc,就修改为

rpc: {

host:"localhost",

port:8545

}

修改./migrations/目录下面的2_deploy_contracts.js文件,更改要部署的合约。

(5)部署合约,部署之前要确保测试区块链已经启动。如果使用testrpc,需要打开新终端,输入testrpc;如果使用pyethapp,需要运行pyethapp。诸如此类,等等等等。

$ truffle migrate

(6)编写测试脚本,拷贝到./test目录下

(7)测试合约

$ truffle test

class=MsoNorma



作者:gloriow
链接:https://www.jianshu.com/p/b2326d7be151
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


评论(0)问答(0)
请先登录或注册

请先登陆或注册

相关推荐

币圈小蝶:币圈几千个币,99%可能是垃圾……

 1、努力学习,重点是2方面:一是区块链基础知识,二是金融交易的基础知识。第一块内容是让你进一步了解这个行业,熟悉这个行业的规律,甚至找到一些其它的盈利模式。第二块内容是给那些致力于通过二级......
ofkings95币圈 · 2019-12-11
159阅读 · 0赞赏 · 0问答

炒币机器人:在币圈你真的知道该怎么屯币吗?

短线操作、追涨杀跌、加大杠杆、焦虑难安...这都是散户很难在这个市场上获得财富的原因。  那么普通人,到底应该如何避开这些坑,真正去享受到比特币带来的财富增长呢?方式有很多,今天要聊的是其中......
ofbing88 · 2019-12-10
407阅读 · 0赞赏 · 0问答

币圈小蝶:币圈现在的行情适合定投么?

 定投是什么?定投首先是建立在对一个币种的共识价值和潜力预期基础上的,进行的时间和价格上两种形式的定向投资。什么意思,比如btc,这个币永远都会有人认可,那么他就是有共识价值的,说白就是不会......
ofkings95币圈 · 2019-12-10
445阅读 · 0赞赏 · 0问答

三两谈币:币圈追求财富自由的几种姿势?

有人说币圈一日,股市一年,币圈在不断演绎创富神话的同时,也会让人一夜返贫。如果说币圈里面,什么是最吸引眼球的字眼,别说什么科技,也别说什么信仰,最最吸引眼球的是四个字“财富自由”。不同的币圈众人用不同......
ofbing88 · 2019-12-09
636阅读 · 0赞赏 · 0问答

李向午:主流币处于震荡上行状态,多头可区间内操作

李向午:主流币处于震荡上行状态,多头可区间内操作  比特币行情分析  昨日比特币价格如笔者所料上行至7600后遇阻回调以7500附近收盘得阳。近日来比特币还是未能脱离震荡区间。今日价格继续在7300-......
李向午 · 2019-12-08
613阅读 · 0赞赏 · 0问答

李向午:保持短空间内操作,狭道亦可获利

李向午:保持短空间内操作,狭道亦可获利  比特币行情分析  比特币上行突破7500点,在触及7600上方位置后触顶回弹。日线图中,布林带呈收口状态,价格在布林带上行通道运行,布林带中轨在7500位置给......
李向午 · 2019-12-07
631阅读 · 0赞赏 · 0问答

千斤

1814

LK币

5

粉丝

26

笔记

感谢"千斤"

这篇精彩的笔记,目前已经帮助

  • 0
  • 0
  • 9
  • 5
  • 9
喜欢0
链客社群 加入

微博进入

商务合作>

广告投放>

公司名称:北京链客行科技有限公司

联系方式:010-67707199

ICP备案号:京ICP备18032136号

Copyright:链客区块链技术问答社区 版权所有

感谢您的提问,问题被社区永久收入以便新人查看。一定要记得采纳最佳答案哦!加油!

感谢您的善举,每一次解答会成为新人的灯塔,回答被采纳后获得20算力和相应的LK币奖励

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!

您将赞赏给对方2LK币的奖励哦!感谢您的赞赏!