Smart contracts are a powerful tool for creating decentralized apps and custom cryptocurrencies. Unlike traditional software, once deployed, they are hard to roll back or patch. And with a market cap of over $200 billion for cryptocurrencies, there’s a lot of value at stake! Unit testing can help us ensure our smart contracts do what we expect.
So how do we write unit tests? It’s now possible to write tests in both Solidity and JavaScript, though the two are not entirely interchangeable. Let’s walk through an example of testing a simple token. (Simple as in less complex, not necessarily easy!) I put my work in a github repo if you’d like to follow along. You’ll need to install truffle and ganache-cli first. I’m using Truffle v4.1.11, Solidity v0.4.24, Ganache v6.1.6 and running on Mac OS X High Sierra 10.13.6.
My initial token had a constructor like this
And migrations/2_deploy_contracts.js looks like this:
Now we can fire up ganache command line interface:
In a separate terminal, let’s deploy this to a test blockchain with
Cool, let’s write our first unit test in Solidity in test/TestMikancoin.sol:
We can use DeployedAddresses to look up where the Mikancoin was deployed, and cast that address to a Mikancoin. Then we can use our asserts to see if our coin is doing the right thing. Running truffle test shows us that we’ve successfully deployed a coin with 100 Mikan and we have a balance of zero.
Here we reach our first problem. It’s not going to be very interesting -- or thorough -- to write tests if we have no tokens to send. Who got the initial mikans? Consider that the migration script made the initial deploy, so it’s probably some internal truffle address that got the fruit. Let’s confirm that by using the tool truffle console:

We can see who called the Mikancoin constructor, and how much gas was spent. We can also see that it matches the first eth address created by ganache-cli. Now we could configure ganache-cli to always generate the same ten addresses, but we still won’t easily be able to control it in solidity. Let’s modify our contract slightly so we can decide who gets the coins on deploy.
We can also write a helper contract to easily manage our Mikancoin.
Next, update the migration script:
And finally, a test where we control the Mikans!
Now, say we want to test the require statements of transfer and ensure we can’t do something bad like send tokens to the zero address. In solidity, this is difficult, as there is no try-catch. We end up with a really awful stack trace when sending to 0x0:
Adding this test and running truffle test generates the following:

There used to be ways of testing throws, but since the switch to require & revert, these techniques no longer work. Let’s switch over to javascript to demo testing failure cases. Note you’ll have to run npm install in the root directory before running this test to get the chai dependency.
After testing in solidity, javascript feels like a cakewalk. Now run everything with truffle test. Truffle picks up both JavaScript and Solidity test files to give you the best of both worlds:

TO BE CONTINUED...