solidity測(cè)試用例分析

本篇內(nèi)容介紹了“solidity測(cè)試用例分析”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信平臺(tái)小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了海州免費(fèi)建站歡迎大家使用!

1、以太坊智能合約測(cè)試概述

作為軟件開發(fā)者,我們都知道要讓代碼正常運(yùn)行,測(cè)試是非常重要的一個(gè)環(huán)節(jié)?;趨^(qū)塊鏈的去中心化軟件也不例外,而且由于區(qū)塊鏈的不可修改特性,測(cè)試對(duì)于區(qū)塊鏈軟件來(lái)說(shuō)就更重要了。

總體上來(lái)說(shuō)有兩種類型的軟件測(cè)試:?jiǎn)卧獪y(cè)試和集成測(cè)試。單元測(cè)試聚焦于單個(gè)函數(shù)的測(cè)試,而集成測(cè)試的目標(biāo)則是確保各部分代碼組合起來(lái)也可以按期望的方式運(yùn)行。

Truffle是應(yīng)用最廣的以太坊智能合約與DApp開發(fā)框架,它提供了兩種用于測(cè)試以太坊智能合約的方法:Solidity測(cè)試和JavaScript測(cè)試。問(wèn)題是,我們應(yīng)該選擇哪一種方法?

答案是都需要。

solidity測(cè)試用例分析

用Solidity編寫智能合約的測(cè)試用例讓我們可以在區(qū)塊鏈層級(jí)進(jìn)行測(cè)試。這種測(cè)試用例可以調(diào)用合約方法,就像用例部署在區(qū)塊鏈里一樣。為了測(cè)試智能合約的內(nèi)部行為,我們可以:

  • 編寫Solidity單元測(cè)試來(lái)檢查智能合約函數(shù)的返回值以及狀態(tài)變量的值

  • 編寫Solidity集成測(cè)試來(lái)檢查智能合約之間的交互。這些集成測(cè)試可以確保像繼承或者 依賴注入這樣的機(jī)制的運(yùn)行符合預(yù)期

我們也需要確保智能合約能夠表現(xiàn)出正確的外部行為。為了從區(qū)塊鏈外部測(cè)試智能合約,我們?cè)贘avaScript測(cè)試用例中使用web3.js,就像在開發(fā)DApp時(shí)一樣。我們需要對(duì)DApp前端可以正確調(diào)用智能合約建立信心。這方面的測(cè)試屬于集成測(cè)試。

因此,簡(jiǎn)單地說(shuō),Solidity測(cè)試用例主要用于智能合約內(nèi)部實(shí)現(xiàn)邏輯的驗(yàn)證,可以用于單元測(cè)試和集成測(cè)試;而JavaScript用例則主要用于智能合約外部行為的驗(yàn)證,通常用于集成測(cè)試。

2、以太坊智能合約測(cè)試的示例項(xiàng)目

假設(shè)我們有兩個(gè)以太坊智能合約需要測(cè)試:Background和Entrypoint。

Background是一個(gè)內(nèi)部合約,我們的DApp前端不會(huì)直接和它交互。EntryPoint則是專門供DApp交互的智能合約,在EntryPoint合約內(nèi)部會(huì)訪問(wèn)Background合約。

下面是Background合約的solidity代碼:

pragma solidity >=0.5.0;

contract Background {
    uint[] private values;

    function storeValue(uint value) public {
        values.push(value);
    }

    function getValue(uint initial) public view returns(uint) {
        return values[initial];
    }

    function getNumberOfValues() public view returns(uint) {
        return values.length;
    }
}

在上面,我們看到Background合約提供了三個(gè)函數(shù):

  • storeValue(uint):寫入值

  • getValue(uint) :讀取值

  • getNumberOfValues():獲取值的數(shù)量

這三個(gè)合約函數(shù)都很簡(jiǎn)單,因此也很容易進(jìn)行單元測(cè)試。

下面是EntryPoint合約的Solidity代碼:

pragma solidity >=0.5.0;

import "./Background.sol";

contract EntryPoint {
    address public backgroundAddress;

    constructor(address _background) public{
        backgroundAddress = _background;
    }

    function getBackgroundAddress() public view returns (address) {
        return backgroundAddress;
    }

    function storeTwoValues(uint first, uint second) public {
        Background(backgroundAddress).storeValue(first);
        Background(backgroundAddress).storeValue(second);
    }

    function getNumberOfValues() public view returns (uint) {
        return Background(backgroundAddress).getNumberOfValues();
    }
}

在EntryPoint合約的構(gòu)造函數(shù)中,我們注入了Background合約的部署地址,并將其存入一個(gè)狀態(tài)變量backgroundAddress。EntryPoint合約暴露出三個(gè)函數(shù):

  • getBackgroundAddress():返回Background合約的部署地址

  • storeTwoValues(uint, uint):保存兩個(gè)值

  • getNumberOfValues():返回值的數(shù)量

由于storeTwoValues(uint, uint)函數(shù)兩次調(diào)用Background合約中的一個(gè)函數(shù),因此對(duì)這個(gè)函數(shù)進(jìn)行單元測(cè)試比較困難。getNumberOfValues()也有同樣的問(wèn)題,因此這兩個(gè)函數(shù)更適合進(jìn)行集成測(cè)試。

3、以太坊智能合約測(cè)試的Solidity用例

在這一部分,我們學(xué)習(xí)如何為智能合約編寫Solidity單元測(cè)試用例和集成測(cè)試用例。讓我們先從簡(jiǎn)單一點(diǎn)的單元測(cè)試開始。

下面是TestBackground測(cè)試的代碼:

pragma solidity >=0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../../../contracts/Background.sol";

contract TestBackground {

    Background public background;

    // Run before every test function
    function beforeEach() public {
        background = new Background();
    }

    // Test that it stores a value correctly
    function testItStoresAValue() public {
        uint value = 5;
        background.storeValue(value);
        uint result = background.getValue(0);
        Assert.equal(result, value, "It should store the correct value");
    }

    // Test that it gets the correct number of values
    function testItGetsCorrectNumberOfValues() public {
        background.storeValue(99);
        uint newSize = background.getNumberOfValues();
        Assert.equal(newSize, 1, "It should increase the size");
    }

    // Test that it stores multiple values correctly
    function testItStoresMultipleValues() public {
        for (uint8 i = 0; i < 10; i++) {
            uint value = i;
            background.storeValue(value);
            uint result = background.getValue(i);
            Assert.equal(result, value, "It should store the correct value for multiple values");
        }
    }
}

這個(gè)單元測(cè)試的目的是確保Background合約可以:

  • 在values數(shù)組中保存新的值

  • 按索引返回values

  • 在values數(shù)組中保存多個(gè)值

  • 返回values數(shù)組的大小

下面的TestEntryPoint測(cè)試中包含了一個(gè)單元測(cè)試testItHasCorrectBackground() 用于驗(yàn)證EntryPoint合約的功能符合預(yù)期:

pragma solidity >=0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../../../contracts/Background.sol";
import "../../../contracts/EntryPoint.sol";

contract TestEntryPoint {

    // Ensure that dependency injection working correctly
    function testItHasCorrectBackground() public {
        Background backgroundTest = new Background();
        EntryPoint entryPoint = new EntryPoint(address(backgroundTest));
        address expected = address(backgroundTest);
        address target = entryPoint.getBackgroundAddress();
        Assert.equal(target, expected, "It should set the correct background");
    }

}

這個(gè)函數(shù)對(duì)依賴注入進(jìn)行測(cè)試。如前所述,EntryPoint合約中的其他函數(shù)需要與Background合約交互,因此我們沒有辦法單獨(dú)測(cè)試這些函數(shù),需要在集成測(cè)試中進(jìn)行驗(yàn)證。下面是集成測(cè)試的代碼:

pragma solidity >=0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../../../contracts/Background.sol";
import "../../../contracts/EntryPoint.sol";

contract TestIntegrationEntryPoint {

    BackgroundTest public backgroundTest;
    EntryPoint public entryPoint;

    // Run before every test function
    function beforeEach() public {
        backgroundTest = new BackgroundTest();
        entryPoint = new EntryPoint(address(backgroundTest));
    }

    // Check that storeTwoValues() works correctly.
    // EntryPoint contract should call background.storeValue()
    // so we use our mock extension BackgroundTest contract to
    // check that the integration workds
    function testItStoresTwoValues() public {
        uint value1 = 5;
        uint value2 = 20;
        entryPoint.storeTwoValues(value1, value2);
        uint result1 = backgroundTest.values(0);
        uint result2 = backgroundTest.values(1);
        Assert.equal(result1, value1, "Value 1 should be correct");
        Assert.equal(result2, value2, "Value 2 should be correct");
    }

    // Check that entry point calls our mock extension correctly
    // indicating that the integration between contracts is working
    function testItCallsGetNumberOfValuesFromBackground() public {
        uint result = entryPoint.getNumberOfValues();
        Assert.equal(result, 999, "It should call getNumberOfValues");
    }
}

// Extended from Background because values is private in actual Background
// but we're not testing background in this unit test
contract BackgroundTest is Background {
    uint[] public values;

    function storeValue(uint value) public {
        values.push(value);
    }

    function getNumberOfValues() public view returns(uint) {
        return 999;
    }
}

我們可以看到TestIntegrationEntryPoint使用了一個(gè)Background的擴(kuò)展,即定義在第43行的BackgroundTest,以其作為我們的模擬合約,這可以讓我們的測(cè)試用例檢查EntryPoint是否調(diào)用了部署在backgroundAddress地址處的合約的正確的函數(shù)。

4、以太坊智能合約測(cè)試的JavaScript用例

我們用JavaScript編寫集成測(cè)試來(lái)確保合約的外部行為滿足預(yù)期要求,這樣我們就有信息基于這些智能合約開發(fā)DApp了。

下面是我們的JavaScript測(cè)試文件entryPoint.test.js:

const EntryPoint = artifacts.require("./EntryPoint.sol");

require('chai')
    .use(require('chai-as-promised'))
    .should();

contract("EntryPoint", accounts => {
    describe("Storing Values", () => {
        it("Stores correctly", async () => {
            const entryPoint = await EntryPoint.deployed();

            let numberOfValues = await entryPoint.getNumberOfValues();
            numberOfValues.toString().should.equal("0");

            await entryPoint.storeTwoValues(2,4);
            numberOfValues = await entryPoint.getNumberOfValues();
            numberOfValues.toString().should.equal("2");
        });
    });
});

使用EntryPoint合約中的函數(shù),JavaScript測(cè)試可以確保我們可以將區(qū)塊鏈外部的值利用交易傳入智能合約,這是通過(guò)調(diào)用合約的storeTwoValues(uint,uint)函數(shù)(第15行)實(shí)現(xiàn)的。

5、以太坊智能合約測(cè)試教程小節(jié)

當(dāng)談到智能合約的測(cè)試時(shí),可以說(shuō)越多越好,應(yīng)當(dāng)盡可能覆蓋所有可能的執(zhí)行路徑都返回預(yù)期的結(jié)果。Truffle提供了兩種辦法:區(qū)塊鏈層的Solidity單元測(cè)試和集成測(cè)試,以及DApp級(jí)別的JavaScript集成測(cè)試,我們?cè)趯?shí)際的工作中需要根據(jù)智能合約的代碼實(shí)現(xiàn)綜合運(yùn)用這兩種測(cè)試方法來(lái)保證智能合約的運(yùn)行符合預(yù)期。

“solidity測(cè)試用例分析”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

新聞標(biāo)題:solidity測(cè)試用例分析
標(biāo)題路徑:http://bm7419.com/article6/gijiig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名App設(shè)計(jì)、外貿(mào)建站、動(dòng)態(tài)網(wǎng)站、云服務(wù)器、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司