Writing some Solidity unit tests withΒ Truffle
Writing some Solidity unit tests with Truffle
Writing some Solidity unit tests with Truffle

You are unit testing, right πŸ‘€πŸ‘€?!

Table of contents

TL;DR

Write some damn tests so you have proof your code does what you think it does!

Unit what now?

I'm going to pretend you did not ask that question πŸ˜†. Unit testing is one of the best skills you should be practicing as you continue your growth as an engineer. But this entry isn't really going to get into the why. I'll save that one for later πŸ˜‰

This isn't going to be too crazy, merely a little tiny baby introduction to unit testing your Solidity smart contract.

Savvy?

braden-collum-9HI8UJMSdZA-unsplash.jpg
braden-collum-9HI8UJMSdZA-unsplash.jpg

Tiny baby Solidity smart contract

Let's start with a real basic smart contract. A typical ToDo list tends to be a good jumping off point with these things.

pragma solidity ^0.8.0;

contract TodoList {
    uint256 public taskCount = 0;

    struct Task {
        uint256 id;
        string content;
        bool completed;
    }

    mapping(uint256 => Task) public tasks;

    function createTask(string memory _content) public {
        taskCount++;

        tasks[taskCount] = Task(taskCount, _content, false);
    }
}

You can see the following:

  • a taskCounter to keep track of all the Tasks needing completed βœ…
  • a Task struct which will encapsulate the information needed inside each of the Tasks for us
  • a simple mapping to, well, map the Tasks

after writing the word Task so many times just now, I am suffering from Semantic Satiation -- I caught myself re-reading that bullet list several times because it was not making sense to me anymore 🀣

Super, let's move on to writing our sweet test!! GOOD JOB!

johan-godinez-dDYRYivNzbI-unsplash.jpg
johan-godinez-dDYRYivNzbI-unsplash.jpg

✍ those Tests

The emoji is a bit of a lie, you are not actually going to handwrite your tests. Although, if you wanted to, you absolutely could! Actually, when I started out programming, I would handwrite all my Java code πŸ€·β€β™€οΈπŸ€·β€β™€οΈ

AAAAAAAAAAanyway

βͺ I guess we missed a few steps, let's backtrack slightly. βͺ

You're going to need to setup Truffle! Hit up your terminal, at the root of your project and type πŸ‘‡

$ truffle init
contracts already exists in this directory...
? Overwrite contracts? (y/N)
Starting init...
================
? Overwrite contracts? No

> Copying project files to C:\Users\frank🐒\Documents\Solidity-Unit-Testing

Init successful, sweet!

Try our scaffold commands to get started:
  $ truffle create contract YourContractName # scaffold a contract
  $ truffle create test YourTestName         # scaffold a test

http://trufflesuite.com/docs

Take note that you will need to hit N to avoid overwriting your amazingly cool ToDoList.sol contract we just wrote!

SCHWEET, now we're back in business πŸ€™πŸ€™

OK, so now your folder structure should look something like this ( note, it's not going to be exact b/c I had created a readme, .gitignore, npm project ):

BeautyShot-67708.png
BeautyShot-67708.png

Let's go ahead and create a new test file in our /test folder and name it ToDoList.test.js

const TodoList = artifacts.require("./TodoList.sol");

contract("TodoList", accounts => {
  const creatorAddress = accounts[0];
  const firstOwnerAddress = accounts[1];
  const secondOwnerAddress = accounts[2];
  const externalAddress = accounts[3];
  const unprivilegedAddress = accounts[4]
  /* create named accounts for contract roles */

  before(async () => {
    this.todoList = await TodoList.deployed();
  });

  it('should deploy successfully', async () => {
    assert.notEqual(creatorAddress, 0x0);
    assert.notEqual(creatorAddress, '');
    assert.notEqual(creatorAddress, null);
    assert.notEqual(creatorAddress, undefined);
  });

  it('should revert if ...', async () => {
    try {
      const result = this.todoList.publicOrExternalContractMethod(argument1, argument2, { from: externalAddress });
      assert.fail();
    } catch (error) {
      assert.notEqual(error.message, "assert.fail()", "Reason ...");
    }
  });

  it('should lists tasks', async () => {
    const taskCount = await this.todoList.taskCount();
    const task = await this.todoList.tasks(taskCount);

    assert.equal(task.id.toNumber(), taskCount.toNumber());
    assert.equal(task.completed, false);
    assert.equal(taskCount.toNumber(), 0);
  });

});

Save the file and ...

LETS RUN THOSE TESTS πŸš€πŸš€

Type in the command truffle test

and you should see something similar to this:

$ truffle test
Using network 'test'.


Compiling your contracts...
===========================
> Compiling .\contracts\ToDoList.sol
> Compilation warnings encountered:

    Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.
--> project:/contracts/ToDoList.sol


> Artifacts written to C:\Users\frank🐒\AppData\Local\Temp\test--3584-6JQ8tVvSUA5L
> Compiled successfully using:
   - solc: 0.8.10+commit.fc410830.Emscripten.clang



  Contract: TodoList
    √ should deploy successfully
    √ should revert if ...
    √ should lists tasks (206ms)


  3 passing (329ms)

πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„

πŸ¦„BOOM YOU ARE BASICALLY A FULL BLOWN BLOCKCHAIN ENGINEER NOWπŸ¦„

πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„πŸ¦„πŸŽŠπŸŽ‰πŸŽ‰πŸš€πŸš€πŸ¦„

erwan-hesry-WPTHZkA-M4I-unsplash.jpg
erwan-hesry-WPTHZkA-M4I-unsplash.jpg

Recap

  1. Testing is important
  2. All jokes aside, it really is. You should absolutely test your smart contracts before deploying them into production. There is a reason all those test networks exist!
  3. This is by no means even remotely comprehensive and, tbh, it barely even scratches the surface of what's needed and involved for good testing

Looking for the code? πŸ‘‰ github.com/frankTurtle

Picture Credits

Photo by Braden Collum on Unsplash

Photo by Johan GodΓ­nez on Unsplash

Photo by Erwan Hesry on Unsplash

Subscribe to Frank 🐒
Receive the latest updates directly to yourΒ inbox.
Verification
This entry has been permanently stored onchain and signed by its creator.