Testing a Solidity smart contract using Truffle framework

In the last tutorial, we have created a smart contract which performs some basic CRUD (create, read, update, delete) operation, let’s test that smart contract using Truffle.

Truffle — Truffle is the most popular development and testing framework for developing ethereum smart contracts.

Installing Truffle

Prerequisites

Installation

  1. First, we need to install the Truffle package
sudo npm install -g truffle
  1. Verify that it has been downloaded successfully by running
truffle

Choose a directory and run

truffle init

It will create a directory structure and create few files.

Let’s go to these directories one by one an will understand what they are.

  • **contracts/**: Directory for Solidity contracts
  • **migrations/**: Directory for scriptable deployment files
  • **test/**: Directory for test files for testing your application and contracts
  • **truffle.js**: Truffle configuration file

We will use truffle develop to test our smart contract. Truffle gives us inbuilt development blockchain with ethereum accounts.

Let’s create a file with CrudApp.sol (Notice, same name as our contract name) under contracts directory and paste our smart contract code.

Let’s compile our smart contract using,

 truffle compile

It may show some warnings but let’s ignore them for now. Open our development console using,

truffle develop

It will show an output something like below:

Truffle Develop started at http://127.0.0.1:9545/
Accounts:(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57(1) 0xf17f52151ebef6c7334fad080c5704d77216b732(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de
Private Keys:(0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3(1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f(2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1(3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c(4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418(5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63(6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8(7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7(8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4(9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5
Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat
⚠️  Important ⚠️  : This mnemonic was created for you by Truffle. It is not secure.Ensure you do not use it on production blockchains, or else you risk losing funds.
truffle(develop)>

Your accounts and private keys will be different than mine.

Now we have accounts ready and our development blockchain spun up, we can test our smart contract.

Before that, let’s run few commands and test the balance of our accounts. Replace my account number with your account in the command below.

web3.eth.getBalance(“0x627306090abab3a6e1400e9345bc60c78a8bef57”)
Result - BigNumber { s: 1, e: 20, c: [ 1000000 ] }

As you can see, above command gives result in BigNumber. You need to convert that into number format using .toNumber() function.

web3.eth.getBalance("0x627306090abab3a6e1400e9345bc60c78a8bef57").toNumber()
Result -  100000000000000000000

This shows balance in WEI (smallest ethereum unit / 1 ethereum = 1⁰¹⁸ wei). To convert this into the ether, you need to use web3.fromWei() function.

web3.fromWei(web3.eth.getBalance(“0x627306090abab3a6e1400e9345bc60c78a8bef57”).toNumber())
Result - '100' <<< Number of ethereum on the test account
Image source
Image source

Now, we need to deploy our smart contract.

You can use either deploy command or migrate command. You don’t need to prefix truffle with commands on truffle CLI.

deploy or migrate

You can use reset flag ( — reset) while redeploying your contracts to get the initial state of the blockchain.

Test Cases-

Now let’s write some test cases to test our smart contract.

Create a file CrudApp.js (name should be same as smart contract file) under test directory and copy below code.

const CrudApp = artifacts.require('./CrudApp.sol')const assert = require('assert')
let crudInstance;
contract('CrudApp' , (accounts)  => {beforeEach(async () => {crudInstance = await CrudApp.deployed()})
it('should insert new user' , async() => {await crudInstance.insert("USA" , "Trump", 30000000);
const country = await crudInstance.getCountry("USA");assert.equal(country[0] , "USA");assert.equal(country[1] , "Trump");assert.equal(country[2].toNumber() , 30000000);
await crudInstance.updateLeader("USA" , "Hillary");
const country1 = await crudInstance.getCountry("USA");assert.equal(country1[0] , "USA");assert.equal(country1[1] , "Hillary");assert.equal(country1[2].toNumber() , 30000000);
await crudInstance.deleteCountry("USA");
const total = await crudInstance.getTotalCountries();assert.equal(total , 0);})
})

Let’s walk through our code and understand it.

We imported our contract and assert library, which created an instance of our contract after deploying it (CrudApp.deployed()). Then we simply wrote three test case in which we are testing all four operations.

First, we are inserting a record and then updating and deleting it, respectively.

You can write test cases in Solidity too, but we choose Javascript, as Truffle makes it easy to test our contract.

You can also run few commands directly on Truffle console and also interact with our smart contract using Truffle CLI (Command Line Interface).

truffle(develop)>
Above is what we calling Truffle CLI. Running commands on truffle.

Let’s get an instance of our smart contract using this command.

CrudApp.deployed().then(function(instance) { crud = instance;})

This will give us an instance (**crud**) of our smart contract, let’s play with it. This instance is simple ABI (Application Binary Unterface) you can check it just printing **crud**.

ABI is the interface between two program modules, one of which is often at the level of machine code. The interface is the de facto method for encoding/decoding data into/out of the machine code.

Let’s check the total number of countries by running this command.

crud.getTotalCountries().then(function(num){var str= num.toString(); console.log(str)});

Let insert a new country

crud.insert("USA","Trump",30000000);

The result should be something like this.

{ tx: '0x6502bd013b41f246e31f071690ffb1c8f41d21c4cddbad8bb99bf53d9ac6c982',receipt:{ transactionHash: '0x6502bd013b41f246e31f071690ffb1c8f41d21c4cddbad8bb99bf53d9ac6c982',transactionIndex: 0,blockHash: '0x297ed89cf22d78956e019100fd15ece49882124ba6d23476c4e48914d3da35f3',blockNumber: 42,gasUsed: 129230,cumulativeGasUsed: 129230,contractAddress: null,logs: [ [Object] ],status: '0x01',logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000008000000000000000000000002000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000' },logs:[ { logIndex: 0,transactionIndex: 0,transactionHash: '0x6502bd013b41f246e31f071690ffb1c8f41d21c4cddbad8bb99bf53d9ac6c982',blockHash: '0x297ed89cf22d78956e019100fd15ece49882124ba6d23476c4e48914d3da35f3',blockNumber: 42,address: '0x8f0483125fcb9aaaefa9209d8e9d7b9c8b9fb90f',type: 'mined',event: 'CountryEvent',args: [Object] } ] }

This is transaction receipt you can see that our country event gets fired too. Whenever you change blockchain state, it has to be a transaction and transactions consume gas.

Now let’s check our entry by running this command

crud.getCountry("USA");

You should see a result something like this.

[ 'USA', 'Trump', BigNumber { s: 1, e: 7, c: [ 30000000 ] } ]

You’ve now learned how to interact with smart contract, and how to test it!

Show me what you’ve built in the comment section.

Conclusion

We have learned how to do basic CRUD operations using solidity and test our smart contract. We cut down on details which can be overwhelming for the sake of brevity. Solidity and Truffle have extensive documentation and you should read them. Also, we used web3.js which comes with Truffle bundle.

There are multiple ways to optimize our CRUD operations (Hint : you can use an external array). Optimize it and let us know.

It’s time for some 👏.

                                                     .    .    .