Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
March 30, 2022 05:15 pm GMT

How to test solidity smart contracts with ruby with RSpec and Etherium.rb

I recently tried testing solidity contracts with rspec and wanted to share results since I haven't really found anyone documenting the process.

Why?

Initially, I just wanted to test whether it's possible because I like ruby and try to stick it anywhere I can. Result turned out to be pretty good, though. I haven't found any big differences with truffle suite.

Without further ado. Naive implementation

Prerequisites

  1. Install ganache with npm -g ganache-cli
  2. Install solidity compiler. If you're on mac you can just use brew install solidity. If not here is a link to documentation

Our smart contract

For this tutorial. We'll use a simple hello world contract. located in 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;  }}

As you can see it allows to read from block and write from a blockchain. Simple but good enough for our tests.

Our test

Spec setup

First, we'd need to start ganache with just

> ganache-cli

Then following etherium.rb documentation all we need to do is

  1. Create local client
client = Ethereum::HttpClient.new('http://localhost:8545')
  1. Create instance of our contract by providing path to a file and instance of a client
Ethereum::Contract.create(file: "greeter.sol", client: client)
  1. Deploy contract
contract.deploy_and_wait

Our initial setup will look like this

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 }

Asserts

First, let's test our greet method. To read from a blockchain with etherium.rb we'll need to use call like so contract.call.method_name. Our test case will look like this

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

To change state of the blockchain we need to use transaction like so contract.transact_and_wait.method_name.

Here is an example of our next assertion

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

Our whole spec will look like this

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")  endend

Running

> bundle exec rspec2 examples, 0 failures

As you can see it's super easy only a couple drawbacks.

  1. Need to start ganache by hand
  2. No easy access to accounts

Next Iteration

To overcome the above drawbacks I've created a simple gem. It'll start ganache before the tests and provide access to accounts

Require gem

Let's add our gem to a Gemfile

gem 'rspec-eth'

and require it in spec_helper.rb with

require 'rspec/eth'

Change spec

All you need to do now to make code work is add type: :smart_contract. RSpec::Eth provides a few methods that'll make our specs even simple. We now can remove client and contract. As the gem will guess contract location by spec location.

Updated version

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")  endend

Now stop ganache if it's still running and try running specs again

> bundle exec rspec2 examples, 0 failures

Conclusion

It's still a work in progress and the process can be improved by adding extra configuration options and contract-specific matchers. However, if you like me love using ruby whenever you can, I believe truffle isn't the only toolset you can use for testing smart contracts


Original Link: https://dev.to/thesmartnik/how-to-test-solidity-smart-contracts-with-ruby-with-rspec-and-etheriumrb-156

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To