A very basic TRUFFLE Solidity setup
Reading http://truffleframework.com/docs/getting_started/solidity-tests I wanted to setup my own example of testing Ethereum contracts with solidity code. This setup leads on from my earlier article on how to build a and test a contract in Truffle using Javascript https://medium.com/@paulmarriott/a-very-basic-truffle-js-testing-story-6dfb7a504fe8
The docs give an example using an example Metacoin contract. My goal was to use an VERY simple basic contract and recreate the same example.
The working folder structure and code is shown below. I also cover some common pitfalls on the way that were both frustrating and hugely time consuming.
My goal is to boost your productivity, if you something out of the article then my job is done.
Firstly the setup of files looks like this:
The contract used was basic, only a set and a get function were used. This was intentional, the idea was to build and understand test automation in truffle.
pragma solidity ^0.4.18;
contract MetaCoin {
uint x;
function set (uint y) public {
x = y;
}
function get () constant public returns(uint) {
return x;
}
}contract basicsum {
uint x;
function set (uint y) public {
x = y;
}
function get () constant public returns(uint) {
return x;
}
}
Next step was to ensure that the Truffle commands worked, these are shown below.
Executing the command migrate should successfully execute with now errors.
Getting to this point should be possible with the standard truffle docs and online tutorials.
Now we are ready to build a solidity test script.
Goto the test directory in the truffle project and create a new file called ‘TestBasicsum.sol’. Add the code below to this file.
pragma solidity ^0.4.18;
import “truffle/Assert.sol”;
import “truffle/DeployedAddresses.sol”;
import “../contracts/basicsum.sol”;// The name of the contract and the actual name of the file MUST be the same!
contract TestBasicsum {function testbasicsumget() public {
basicsum meta = new basicsum();
uint expected = 0;Assert.equal(meta.get(), expected, “Value expected should be zero”);
}
}
The pragma command is not essential but good practice. The two import statements that follow link to contract files that should have already been installed by truffle. A search of the operating system should reveal that they exist on the workstation. I found that these two commands worked as expected. I thought I had to manually create these files and put them in the contracts directory. This was an error and resulted in out of gas errors each time I tried.
The import statement import “../contracts/basicsum.sol” is a link to the contract file we wish to test. This file must exist and must be in the contracts directory. This was my first mistake.
The contract name TestBasicsum on the line that follows and the name of the file TestBasicsum.sol MUST match. If they do not then when truffle runs the test errors like the screen shot below will show. This was the biggest lesson learnt and only learnt through trial and error. I found the answer when I took the truffle example on the website and kept trying different code and filename combinations to replicate the same issue.
Only one contract in this file will be executed, each function within the contract will be executed in the order in which they are listed. This is an important distinction from other Solidity contracts and something worth knowing before truffle test development is started.
The function testbasicsumget() is like other examples, very simple. It first creates a new instance of the basicsum contract and executes the get method of the contract.
The very last line is an Assert.equal statement that compares the result of the call to the expected value. This statement is possible ONLY with the Assert library, there is a standard assert function in regular Solidity but this is lower case and does not support the same methods as the Assert (first letter uppercase) library.
To execute the test first re-run truffle compile, truffle develop and migrate. From the truffle window now run truffle ./test/TestBasicsum.sol
If all went well the output should be displayed as follows.
NOTE: Another issue found during testing was that the name of the contract file needed to match the name of at least one contract in the file. For example my contract basicsum has a filename of basicsum.sol. If I where to change the name of the contract file to mycontract.sol BUT did not have a contract in the file with the same name then the solidity test would fail. The error returned would state.
Could not find nnn.sol from any sources; imported from….nnn.sol