RSpec 및 Etherium.rb를 사용하여 Ruby로 견고성 스마트 계약을 테스트하는 방법

나는 최근에 rspec으로 솔리디티 컨트랙트 테스트를 시도했고 프로세스를 문서화한 사람을 실제로 찾지 못했기 때문에 결과를 공유하고 싶었습니다.

왜요?



처음에는 그냥 제가 루비를 좋아해서 가능한지 시험해보고 싶었고, 제가 할 수 있는 모든 곳에 붙여보려고 했습니다. 그래도 결과는 꽤 괜찮았습니다. 트러플 스위트와 큰 차이점을 찾지 못했습니다.

더 이상 고민하지 않고. 순진한 구현



전제 조건


  • npm -g ganache-cli로 가나슈 설치
  • 견고성 컴파일러를 설치합니다. Mac을 사용하는 경우 brew install solidity 를 사용할 수 있습니다. 그렇지 않은 경우 여기에 link to documentation

  • 우리의 스마트 계약



    이 튜토리얼의 경우. 우리는 간단한 Hello World 계약을 사용할 것입니다. contracts/greeter.sol에 위치

    pragma solidity >= 0.8.11;
    
    contract Greeter {
      string private _greeting = "Hello, World!";
      address public owner;
    
      constructor() {
        owner = msg.sender;
      }
    
      function greet() external view returns(string memory) {
        return _greeting;
      }
    
      function setSuperGreeting(string calldata greeting) external {
        require(msg.sender == owner, "Only owner");
        _greeting = greeting;
      }
    }
    


    보시다시피 블록에서 읽고 블록체인에서 쓸 수 있습니다. 간단하지만 테스트에 충분합니다.

    우리의 테스트



    사양 설정



    먼저 가나슈를 시작해야 합니다.

    > ganache-cli
    


    그런 다음 etherium.rb 문서를 따라야 합니다.
  • 로컬 클라이언트 생성

  • client = Ethereum::HttpClient.new('http://localhost:8545')
    


  • 파일 경로와 클라이언트 인스턴스를 제공하여 계약 인스턴스를 생성합니다.

  • Ethereum::Contract.create(file: "greeter.sol", client: client)
    


  • 계약 배포

  • contract.deploy_and_wait
    


    초기 설정은 다음과 같습니다.

    require 'spec_helper.rb'
    
    RSpec.describe 'Greeter' do
      let(:client) { Ethereum::HttpClient.new('http://localhost:8545') }
      let(:contract) { Ethereum::Contract.create(file: "contracts/greeter.sol", client: client) }
    
      before { contract.deploy_and_wait }
    


    주장



    먼저 우리의 welcome 메서드를 테스트해 봅시다. etherium.rb로 블록체인에서 읽으려면 call와 같이 contract.call.method_name를 사용해야 합니다. 테스트 케이스는 다음과 같습니다.

    it 'reads greeting' do
      expect(contract.call.greet).to eq("Hello, World!")
    end
    


    블록체인의 상태를 변경하려면 다음과 같은 트랜잭션을 사용해야 합니다contract.transact_and_wait.method_name.

    다음은 다음 어설션의 예입니다.

    it 'changes message' do
      contract.transact_and_wait.set_super_greeting("Yo")
    
      expect(contract.call.greet).to eq("Yo")
    end
    


    전체 사양은 다음과 같습니다.

    require 'spec_helper'
    
    RSpec.describe 'Greeter' do
      let(:client) { Ethereum::HttpClient.new('http://localhost:8545') }
      let(:contract) { Ethereum::Contract.create(file: "contracts/greeter.sol", client: client) }
    
      before { contract.deploy_and_wait }
    
      it 'sets greeting' do
        expect(contract.call.greet).to eq("Hello, World!")
      end
    
      it 'changes message' do
        contract.transact_and_wait.set_super_greeting("Yo")
    
        expect(contract.call.greet).to eq("Yo")
      end
    end
    
    


    달리기

    > bundle exec rspec
    
    2 examples, 0 failures
    


    보시다시피 몇 가지 단점 만 매우 쉽습니다.
  • 손으로 가나슈를 시작해야 함
  • 계정에 쉽게 액세스할 수 없음

  • 다음 반복



    위의 단점을 극복하기 위해 simple gem 을 만들었습니다. 테스트 전에 ganache를 시작하고 계정에 대한 액세스를 제공합니다.

    보석 필요



    보석을 Gemfile에 추가해 보겠습니다.

    gem 'rspec-eth'
    

    spec_helper.rb에서 요구합니다.

    require 'rspec/eth'
    


    사양 변경



    코드를 작동시키기 위해 지금 해야 할 일은 추가type: :smart_contract 입니다. RSpec::Eth는 사양을 더욱 단순하게 만드는 몇 가지 방법을 제공합니다. 이제 clientcontract 를 제거할 수 있습니다. 보석은 사양 위치로 계약 위치를 추측합니다.

    업데이트된 버전




    require 'spec_helper'
    
    RSpec.describe 'Greeter', type: :smart_contract do
      before { contract.deploy_and_wait }
    
      it 'sets greeting' do
        expect(contract.call.greet).to eq("Hello, World!")
      end
    
      it 'changes message' do
        contract.transact_and_wait.set_super_greeting("Yo")
    
        expect(contract.call.greet).to eq("Yo")
      end
    end
    


    이제 ganache가 계속 실행 중이면 중지하고 사양을 다시 실행해 보십시오.

    > bundle exec rspec
    
    2 examples, 0 failures
    


    결론



    아직 진행 중인 작업이며 추가 구성 옵션과 계약별 매처를 ​​추가하여 프로세스를 개선할 수 있습니다. 그러나 가능할 때마다 루비를 사용하는 것을 좋아한다면 트러플이 스마트 계약을 테스트하는 데 사용할 수 있는 유일한 도구 세트는 아니라고 생각합니다.

    좋은 웹페이지 즐겨찾기