Block Chain Development

이더리움 기반 Dapp 개발 연습 #4 (단위 테스트)

PON_Z 2022. 1. 27. 16:09

- 이번엔 truffle을 사용하여 단위 테스트를 해볼 것이다.

  자바스크립트 또는 솔리디티로 테스트 스크립트를 작성하여 단위 테스트를 수행할 것이다.

  자바스크립트 테스트 프레임워크 mocah를 기반으로 contract 함수를 사용할 것이다.

  단위 테스트 묶음 contract()에서는 각 단위 테스트 케이스의 결과를 공유하므로 순서를 고려해야 한다.

  대부분의 메소드들은 비동기적으로 동작하므로 결과도 비동기적으로 작성해야 한다(Promise, aysnc/await).

 

 

- 아래코드를 test 디렉토리에 test_hello.js 파일을 만들어 작성하자.

var  hello = artifacts.require("HelloWorld");

contract("HelloWorld", function() {
    // say 메소드 테스트
    it("should be same as constructor argument", async() => {
        let instance = await hello.deployed();
        let greeting = await instance.say.call();
        assert.equal(greeting, "Hello, World!");
    });
    // setGreeting 메소드 테스트
    it("should change the greeting value by setGreeting", async() => {
        let instance = await hello.deployed();
        await instance.setGreeting("Hello, Blockchain!", {from: web3.eth.accounts[0]});

        let greeting = await instance.say.call();
        assert.equal(greeting, "Hello, Blockchain!");
    });

    // 아래 방법과 동일하지만 async를 통해 더 직관적으로 작성 가능
    /*
    // say 메소드 테스트
    it("should be same as constructor argument", function() {
        // hello가 배포되고나면 리턴값을 instance 변수로 전달, instance가 contract를 나타내게 됨
        return hello.deployed().then(function(instance) {
            // say가 실행되고 나면 리턴값을 greeting 변수로 전달
            return instance.say().then(function(greeting) {
                assert.equal(greeting, "Hello, World!");
            })
        })
    });
    // setGreeting 메소드 테스트
    it("should change the greeting value by setGreeting", function() {
        return hello.deployed().then(function(instance) {
            // 상태변수를 업데이트, 비용을 계정할 계정을 accounts[0]으로 설정
            instance.setGreeting("Hello, Blockchain!", {from: web3.eth.accounts[0]});
            return instance.say().then(function(greeting) {
                assert.equal(greeting, "Hello, Blockchain!");
            })
        })
    });
    */
});

 

 

- 파워쉘에서 테스트를 실행해보았더니 하나는 성공 하나는 실패했다. 이것도 버전 이슈인 것 같다...

  열심히 구글링을 하여 해결방법을 찾아 다시 코드를 작성하였다.

 

 

var  hello = artifacts.require("HelloWorld");

contract("HelloWorld", function() {
    // say 메소드 테스트
    it("should be same as constructor argument", async() => {
        let instance = await hello.deployed();
        let greeting = await instance.say.call();
        assert.equal(greeting, "Hello, World!");
    });
    // setGreeting 메소드 테스트
    it("should change the greeting value by setGreeting", async() => {
        let instance = await hello.deployed();
        let accounts = await web3.eth.getAccounts();
        web3.eth.defaultAccount = accounts[0];
        await instance.setGreeting("Hello, Blockchain!", {from: web3.eth.defaultAccount});
        let greeting = await instance.say.call();
        assert.equal(greeting, "Hello, Blockchain!");
    });

    // 아래 방법과 동일하지만 async를 통해 더 직관적으로 작성 가능
    /*
    // say 메소드 테스트
    it("should be same as constructor argument", function() {
        // hello가 배포되고나면 리턴값을 instance 변수로 전달, instance가 contract를 나타내게 됨
        return hello.deployed().then(function(instance) {
            // say가 실행되고 나면 리턴값을 greeting 변수로 전달
            return instance.say().then(function(greeting) {
                assert.equal(greeting, "Hello, World!");
            })
        })
    });
    // setGreeting 메소드 테스트
    it("should change the greeting value by setGreeting", function() {
        return hello.deployed().then(function(instance) {
            // 상태변수를 업데이트, 비용을 계정할 계정을 accounts[0]으로 설정
            instance.setGreeting("Hello, Blockchain!", {from: web3.eth.accounts[0]});
            return instance.say().then(function(greeting) {
                assert.equal(greeting, "Hello, Blockchain!");
            })
        })
    });
    */
});

 

 

- 두 가지 테스트 모두 성공하였다! 만약 테스트 파일이 여러개일 경우 truffle test를 하면 모든 유닛 테스트를 한 번에

  수행할 수 있다.

 

-  아래는 지금까지의 프로세스를 그림으로 표현한 것이니 참고하길 바란다.

 

 

 

- 추가로 자바스크립트 비동기 처리시(Promise, async/await) 유의 사항에 대해 살펴볼 것이다.

  우선 가나슈의 Setting/Server 에 들어간다.

 

 

- 위 그림처럼 AUTOMINE이 켜져있으면 블럭이 즉시(instantaneously) 생성된다. 하지만 현실적으로 이더리움 블록이

  생성 되는 데에는 몇 초정도 시간이 걸린다.

 

- AUTOMINE을 끄면 MINING BLOCK TIME을 설정 할 수 있는데 실제와 비슷하게 5초정도로 설정을 한다고 가정해보자.

  만약 테스트 케이스가 비동기적인 결과를 반환 할 경우 promise를 사용하지 않으면 테스트 케이스에 실패 할 수 있으

  므로 유의하자.

 

  

 

 

 

 

 

 

ref) https://www.inflearn.com/course/dapp/dashboard

728x90