Testing Your Solidity Smart Contracts
A good practice in the software industry is writing tests for code. The tests needs to cover the features of your code and assert that everything is working as predicted. As we are writing smart contracts that can deal with money, writing tests is a really important task for us. The Embark Framework offers a pretty rich environment for testing our smart contracts.
We will write our tests in Javascript using the Mocha. To install it just type npm install -g mocha in your terminal.
Let’s start writing test for our MDBService contract that we deployed in our previous tutorial. We want to test the functionalities of our contract:
- It’s empty when initialized
- When a user registers, it creates a contract
- We can retrieve a contract made by a user
- A user can’t register more than one time
We will create a new file in the test directory test/MDBService_spec.js . We will import the libraries and tools we need to test our code:
var assert = require('assert');
var Embark = require('embark');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
Following the Mocha syntax we will describe our tests and deploy all of the contracts in our project:
describe("MDBService", function() {
before(function(done) {
this.timeout(0);
EmbarkSpec.deployAll({}, done);
});
//Write your tests here
})
Our first test will check if when the MDBService , it is really empty:
it("Should be empty after deployment", function(done) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 0);
done();
});
});
Then we will check if an account is really created after we call the register function:
it("A user can register an account", function(done) {
MDBService.register({gas:900000}, function(err, result) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 1);
done();
});
});
});
Then we test if the contract has a correct address and our method to access the contracts works:
it("Retrieving the account address should be the same and different from 0x0", function(done) {
web3.eth.getAccounts(function(err, accounts) {
MDBService.getAccount(accounts[0], function(err, accountaddress) {
MDBService.getAccountId(0, function(err, accountaddressid) {
assert.equal(accountaddress, accountaddressid);
assert.notEqual(accountaddress, '0x0000000000000000000000000000000000000000');
done();
});
});
});
});
And finally we’ll unsure one user can’t create multiple accounts:
it("A user can't register more than one account", function(done) {
MDBService.register({gas:900000}, function(err, result) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 1);
done();
});
});
});
Even if smart contracts code are by nature pretty short, writing tests is really important to help you identify errors while building an application. It is also important as in smart contracts development, we often re use existing contracts code and it is important to know that your bricks are sane and safe.
To run your tests using Embark Framework, in a terminal type:
embark test
Here is our complete test file:
var assert = require('assert');
var Embark = require('embark');
var EmbarkSpec = Embark.initTests();
var web3 = EmbarkSpec.web3;
describe("MDBService", function() {
before(function(done) {
this.timeout(0);
EmbarkSpec.deployAll({}, done);
});
it("Should be empty after deployment", function(done) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 0);
done();
});
});
it("A user can register an account", function(done) {
MDBService.register({gas:900000}, function(err, result) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 1);
done();
});
});
});
it("Retrieving the account address should be the same and different from 0x0", function(done) {
web3.eth.getAccounts(function(err, accounts) {
MDBService.getAccount(accounts[0], function(err, accountaddress) {
MDBService.getAccountId(0, function(err, accountaddressid) {
assert.equal(accountaddress, accountaddressid);
assert.notEqual(accountaddress, '0x0000000000000000000000000000000000000000');
done();
});
});
});
});
it("A user can't register more than one account", function(done) {
MDBService.register({gas:900000}, function(err, result) {
MDBService.getNbAccounts(function(err, result) {
assert.equal(result.toNumber(), 1);
done();
});
});
});
});