[Solidity] Truffle 공부 - 7(Contract Module Test)

in mini.topia4 months ago

Solidity 메모7!

유튜브 영상 자료(Dapp Campus)를 따라해보면서 배우고 있는 중입니다. 한번 따라해보면 처음에 익숙해지는데 꽤나 좋을 것 같습니다.

여기서는 로또비스무리한 컨트랙트를 만들고 있군요. 그래서 Lottery Contract로 만들어 보고 있습니다.


이번에는 Lottery 관련 테스트 모듈 개발입니다.

assertRevert 소스

  • promise 함수를 변수로 받고 실행을 한다.
  • promise에서 에러 시 catch에서 error message에서 revert 존재 여부를 확인
module.exports = async (promise) => {
    try {
        await promise;
        assert.fail("Expected revert not received");
    } catch (error) {
        console.log(`catch error`);
        const revertFound = error.message.search("revert") > -1;
        assert(revertFound, `Expected "revert", got ${error} instead`);
    }
};

expectEvent 소스

  • chai 라이브러리 참조
  • contract 내에 eventName으로 선언된 event가 있는 지 확인 하는 테스트 소스
const assert = require("chai").assert;

const inLogs = async (logs, eventName) => {
    const event = logs.find((e) => e.event === eventName);
    assert.exists(event);
};

module.exports = {
    inLogs,
};

Lottery Test 소스

  • 테스트는 mocha 테스트 모듈이 내장되어 있고, 그 형식을 따른다.(https://mochajs.org/)
  • it.only 또는 describe.only 처럼 only를 입력하는 경우 해당 테스트만 실행한다.
  • describe는 비슷한 모듈 단위로 묶는 역할을 한다.
  • it는 테스트 단위
  • 기본적으로 컨트랙트의 함수는 비동기 함수이므로 async/await 로 설정한다.
  • 실행명령어 : truffle test <테스트 파일 경로>
const Lottery = artifacts.require("Lottery");
const expectEvent = require("./expectEvent");
const assertRevert = require("./assertRevert");

contract("Lottery", function ([deployer, user1, user2]) {
    let lottery;
    let betAmount = 5 * 10 ** 15;
    let BET_BLOCK_INTERVAE = 3;

    // 테스트 전에 미리 실행 하는 함수
    beforeEach(async () => {
        lottery = await Lottery.new(); // 스마트 컨트랙트 배포
    });

    // only 입력시 요것만 테스트를 해본다.
    it("Getpot should return current pot", async () => {
        console.log("Getpot should return current pot");
        let pot = await lottery.getPot();

        assert.equal(pot, 0);
    });

    describe.only("Bet", function () {
        it("should fail when the bet money is not 0.005 ETH", async () => {
            // fail transaction
            await assertRevert(
                lottery.bet("0xab", { from: user1, value: betAmount })
            );
            // await lottery.bet('0xab', {from:user1, value:betAmount})

            // ethereum transaction object {chainId, value, to, from, gas(limit), gasPrice}
        });

        it("should put the bet to the bet queue with 1 bet", async () => {
            // bet
            const receipt = await lottery.bet("0xab", {
                from: user1,
                value: betAmount,
            });
            console.log(receipt);
            console.log(
                `receipt logs.args : ${JSON.stringify(receipt.logs[0].args)}`
            );

            let pot = await lottery.getPot();
            assert.equal(pot, 0);
            // check contract Balance == 0.005 ETH
            let contractBalance = await web3.eth.getBalance(lottery.address);
            assert.equal(contractBalance, betAmount);

            // check bet info
            let currentBlockNumber = await web3.eth.getBlockNumber();
            let bet = await lottery.getBetInfo(0);
            assert.equal(
                bet.answerBlockNumber,
                currentBlockNumber + BET_BLOCK_INTERVAE
            );
            assert.equal(bet.bettor, user1);
            assert.equal(bet.challenges, "0xab");

            // check log
            await expectEvent.inLogs(receipt.logs, "BET");
        });
    });
});