일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 컨트렉트 배포 자동화
- 스마트 컨트렉트 함수이름 중복
- SBT표준
- 오블완
- chainlink 설명
- 스마트컨트렉트테스트
- Vue
- 계정추상화
- erc4337
- 러스트 기초 학습
- vue기초
- rust 기초
- 러스트기초
- 티스토리챌린지
- git rebase
- 컨트렉트 동일한 함수이름 호출
- ethers websocket
- erc4337 contract
- ethers v6
- 러스트 기초
- 머신러닝기초
- Vue.js
- ethers type
- multicall
- ambiguous function description
- 스마트컨트렉트 함수이름 중복 호출
- ethers
- 체인의정석
- 스마트컨트렉트 예약어 함수이름 중복
- ethers typescript
- Today
- Total
체인의정석
hardhat 사용법 정리 03- 테스트코드 작성하기 본문
이제 배포를 했으니 테스트코드를 작성하고 돌려봐야 한다.
테스트 코드는 딱히 가나슈랑 다른 점은 없어보여서 그대로 가져와서 사용해보기로하였다.
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("Greeter", function () {
it("Should return the new greeting once it's changed", async function () {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, world!");
await greeter.deployed();
expect(await greeter.greet()).to.equal("Hello, world!");
const setGreetingTx = await greeter.setGreeting("Hola, mundo!");
// wait until the transaction is mined
await setGreetingTx.wait();
expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});
chai 모듈과 ethers를 사용하여 테스트를 하는것인데 나도 이대로 하려고 한다.
expect를 걸어두는 부분이나 함수를 변수화하여 비동기화 시키는 작업이 필요한것 같다.
https://docs.openzeppelin.com/test-helpers/0.5/
오픈제플린의 공식 ERC 코드를 살펴보다가 test helper라는 모듈을 사용하고 있음을 발견하였다.
https://docs.openzeppelin.com/test-environment/0.1/
또한 테스트 환경에 대한 모듈도 사용이 가능하다.
그러나 트러플과 하드햇의 환경이 혼동되어서 문서를 찾아보니 깔끔하게 정리된 페이지가 있었다.
위 3개의 페이지를 참고하여 테스트코드를 작성할 예정이다.
https://docs.openzeppelin.com/learn/writing-automated-tests?pref=hardhat
먼저 chai를 테스트 모듈로 사용한다.
npm install --save-dev chai
test 디렉토리에 테스트 코드를 관리하게 되는데 contracts 디렉토리에 있는 것을 미러링 하여 테스트 디렉토리에 그대로 넣어 주어야 한다. test 디렉토리는 루트 경로에 있어야 하며 .js 파일 형태로 만든다.
// test/Box.test.js
// Load dependencies
const { expect } = require('chai');
// Start test block
describe('Box', function () {
before(async function () {
this.Box = await ethers.getContractFactory('Box');
});
beforeEach(async function () {
this.box = await this.Box.deploy();
await this.box.deployed();
});
// Test case
it('retrieve returns a value previously stored', async function () {
// Store a value
await this.box.store(42);
// Test if the returned value is the same one
// Note that we need to use strings to compare the 256 bit integers
expect((await this.box.retrieve()).toString()).to.equal('42');
});
});
이런 식으로 테스트 코드를 작성하면 되는데, 아래 링크를 공부해보라고 나와있었다.
여기 글을 보면 반복되는 부분에 대해서 EVM snapshot과 revert를 사용하여 테스트를 빠르게 하며 반복을 줄인다고 한다.
beforeEach(async () => {
snapshotId = await snapshot()
proposal1 = {
applicant: applicant1,
tokenTribute: 100,
sharesRequested: 1,
details: 'all hail moloch'
}
token.transfer(summoner, initSummonerBalance, { from: creator })
})
afterEach(async () => {
await restore(snapshotId)
})
테스트 코드에 자꾸 beforeEach가 나와 있는데 이러한 부분은 각 유닛테스트시 작동하게 된다. afterEach는 유닛테스트 이후에 작동하게 된다. 위의 코드에서 beforeEach를 사용하여 글로벌 변수들을 예측 가능한기본선으로 세팅해주게 된다. 이러한 each 구문은 describe의 블록 범위 앞뒤에서 트리거가 되게 된다. 또한 더 높은 스코프에서의 Each는 해당 범위를 모두 포괄하여 작동하게 된다.
foreEach_1 -> beforeEach_2 -> { test } -> afterEach
describe('submitProposal', () => {
beforeEach(async () => {
await token.transfer(proposal1.applicant, proposal1.tokenTribute, {
from: creator
})
await token.approve(moloch.address, 10, { from: summoner })
await token.approve(moloch.address, proposal1.tokenTribute, {
from: proposal1.applicant
})
})
beforeEach는 submitProposal의 단위 테스트를 위하여 토큰을 보내고 어프루브를 받아서 디파짓이 매번 가능하도록 만들어 준다.
이렇게 반복되는 기능은 매 테스트마다 계속해서 사용하게 된다.
it('happy case', async () => {
await moloch.submitProposal(
proposal1.applicant,
proposal1.tokenTribute,
proposal1.sharesRequested,
proposal1.details,
{ from: summoner }
)
await verifySubmitProposal(proposal1, 0, summoner, {
initialTotalShares: 1,
initialApplicantBalance: proposal1.tokenTribute,
initialProposerBalance: initSummonerBalance
})
})
위의 테스트가 있다고 쳐보고
it('require fail - uint overflow', async () => {
proposal1.sharesRequested = _1e18
await moloch
.submitProposal(
proposal1.applicant,
proposal1.tokenTribute,
proposal1.sharesRequested,
proposal1.details,
{ from: summoner }
)
.should.be.rejectedWith('too many shares requested')
})
아래의 테스트가 반복되는 경우 단 하나만 바뀌게 된다. 오버 플로우를 테스트하기 위해 이처럼 반복되는 코드가 많이 나오게 된다.
이런 부분을 해결하기 위해 before Each를 달아서 중복되는 부분을 한번에 처리할 수 있다.
이번 부분은 중요하기 때문에 다음 글에서 이어서 정리하도록 하겠다.
'블록체인 > Ethers & web3' 카테고리의 다른 글
ethers.js에서 keccak256 사용하기 (0) | 2022.02.13 |
---|---|
ether.js에서 HexPad 하기 (0) | 2022.02.11 |
hardhat 오류 해결) bytes32 형태의 값 넣는 방법 (0) | 2022.01.27 |
hardhat 사용법 정리 04- 테스트코드 작성하기 2 (0) | 2022.01.19 |
hardhat 사용법 정리 01- 하드햇 설치 및 기본세팅 진행 (0) | 2022.01.17 |