An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
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
- Install ganache with
npm -g ganache-cli
- 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
- Create local client
client = Ethereum::HttpClient.new('http://localhost:8545')
- Create instance of our contract by providing path to a file and instance of a client
Ethereum::Contract.create(file: "greeter.sol", client: client)
- 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.
- Need to start ganache by hand
- 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
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To