编译、执行、测试脚本

2020-04-25  本文已影响0人  _微光角落_

目的:利用solc更方便的执行合约,不必在命令行中拷贝粘贴abi等内容。
首先建立一个文件夹contract_workflow,然后项目进行初始化和安装solc

npm init
npm install solc

然后在里面新建四个子文件夹(主要是为了便于管理文件)

contracts:放置合约
tests:用于测试
scripts:放置js脚本
compiled:放置输出内容

然后一份简单的测试源码(car.sol),放置在contracts中

pragma solidity >0.4.22;
contract Car{
    string public brand;
    constructor(string memory initialBrand) public{
        brand = initialBrand;
    }

    function setBrand(string memory newBrand) public{
        brand = newBrand;
    }

    function getBrand()public view returns(string memory){
        return brand;
    }
}

开始编辑脚本(compile.js),放置于scripts中

//引入所需要的工具
const fs = require('fs');
const solc = require('solc');
const path = require('path');

//清空compile文件
// const compilePath = path.resolve(__dirname,'../compiled');
// fs.removeSync(compilePath);
// fs.ensureDirSync(compilePath);

//拼接路径
const contractPath = path.resolve(__dirname, '../contracts', 'Car.sol');
console.log("路径:" + contractPath);
//读取源文件
const contractSource = fs.readFileSync(contractPath, 'utf-8');

//预先定义好编译源json对象
let jsonContractSource = JSON.stringify({
  language: 'Solidity',
  sources: {
    'Car.sol': {  // 指明编译的文件名
      content: contractSource, // solidity 源代码
    },
  },
  settings: { // 自定义编译输出的格式。以下选择输出全部结果。
    outputSelection: {
      '*': { 
        '*': ['*']
      }
    }
  },
});

// 编译得到结果
let output = JSON.parse(solc.compile(jsonContractSource));

console.log("json对象源文件:" + output);

compileJson = {
  'abi': {},
  'bytecode': ''
};

// output 为json对象,根据json结构保存对应的abi和bytecode
for (var contractName in output.contracts['Car.sol']) {
  compileJson.abi = output.contracts['Car.sol'][contractName].abi;
  compileJson.bytecode = output.contracts['Car.sol'][contractName].evm.bytecode.object;
}

console.log(compileJson);  

// 将compileJson数据输出到compile.json文件

const compileJsonPath = path.resolve(__dirname,'../compiled','compile.json');

fs.writeFile(compileJsonPath, JSON.stringify(compileJson), function(err){
  if(err)
    console.error(err);
  console.log("Car contract compiled sucessfully.")
})

这样就完成了简本编辑,然后开始编辑部署脚本deploy.js,放置在scripts文件夹中。

const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
const fs = require('fs-extra');
const path = require('path');

//读取abi和code
const filePath = path.resolve(__dirname, '../compiled', 'compile.json');
const compileJson = JSON.parse(fs.readFileSync(filePath));

//
(async () => {
  //异步获取账户
  let accounts = await web3.eth.getAccounts();
  //直接创建合约,链式调用
  let result = await new web3.eth.Contract(compileJson.abi)
    .deploy({ data: compileJson.bytecode, arguments: ['BMW'] })
    .send({ from: accounts[0], gas: 5000000 });

//返回合约地址
  console.log('contractAddress:', result.options.address);
})();

此时在terminal中,cd至scripts文件夹使用命令

node deploy.js

就会返回合约地址
接着使用mocha框架进行测试,先在contract_workflow中安装mocha

//安装到本地开发环境依赖中去,会在package.json中显示
//dependencies:运行环境依赖,需要随项目打包(--save实现)
//devDependencies:开发环境依赖(--save-dev实现)
npm install mocha --save-dev

//本地安装ganache-cli
npm install ganache-cli  --save-dev

编辑测试文件Car.spec.js代码,放置于tests文件夹中:

const assert = require('assert');
const path = require('path');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const contractPath = path.resolve(__dirname, '../compiled','compile.json');

const compileJson = require(contractPath);
// const fs = require('fs');
// const compileJson = JSON.parse(fs.readFileSync(contractPath));
let contract;
let accounts;
const initialBrand = 'BMW';

//describe 是测试套件,it是测试用例,第一个参数都是名称,第二个参数是实际执行的函数
describe('#contract', () => {
    //每次执行测试之前都会执行一遍
    beforeEach(async () => {
        accounts = await web3.eth.getAccounts();
        contract = await new web3.eth.Contract(compileJson.abi)
            .deploy({ data: compileJson.bytecode, arguments:[initialBrand]})
            .send({ from: accounts[0], gas: 5000000});
    });

    it('deploy contract successfully', () => {
        assert.ok(contract.options.address);
    });

    //1.0全部都是异步调用
    it('should has a initial brand',async()=>{
        let brand =await contract.methods.brand().call();
        assert.equal(brand,initialBrand);
    })

    it('should set a new brand',async()=>{
        const newBrand = 'Audi';
        await contract.methods.setBrand(newBrand)
        .send({from:accounts[0]});

        const brand = await contract.methods.brand().call();
        assert.equal(brand,newBrand);
    });
});

但是当使用node执行时会出现describe未定义问题,查询后改为全局安装,用mocha执行test文件

//全局安装
npm install -g mocha

//执行
mocha Car.spec.js

通过npm机制,将整个自动化流程串起来。
修改package.json中的scripts

"scripts": {
    "compile":"node scripts/compile.js",
    "predeploy":"npm run compile",
    "deploy":"node scripts/deploy.js",
    "pretest":"npm run compile",
    "test": "mocha tests"
  },

之后在terminal中contract_workflow目录下执行

 npm run test
上一篇 下一篇

猜你喜欢

热点阅读