Write some damn tests so you have proof your code does what you think it does!
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?
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:
taskCounter
to keep track of all the Tasks needing completed β
Task
struct which will encapsulate the information needed inside each of the Tasks for usmapping
to, well, map the Tasksafter 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!
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 ):
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 ...
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π¦
ππππππ¦π¦ππππππ¦π¦ππππππ¦π¦ππππππ¦
Looking for the code? π github.com/frankTurtle
Photo by Braden Collum on Unsplash
Photo by Johan GodΓnez on Unsplash
Photo by Erwan Hesry on Unsplash