A very basic TRUFFLE js testing story
Like many getting their feet wet with Ethereum development and testing of Ethereum contracts I went through many late night hours trying to figure out how to get things done.
Documentation, online posts and news articles would give some information and in many cases just looking at the issues of others gave inspiration.
This article is how I got a VERY basic Ethereum contract to work with Truffle. I am writing this after the aha moment and want to share the experience, help others to persevere and move onward with development in Ethereum.
Firstly I wrote a contract that simply gets and sets a value. The contract text is below:
pragma solidity ^0.4.18;
contract basicsum {
uint x;
function set (uint y) public {
x = y;
}
function get () constant public returns(uint) {
return x;
}
}
Function set() will change variable x. Function get will return the value of x.
Copy and paste the code above into https://remix.ethereum.org to prove that the code works and has no syntax issues.
Now the complex part…and I am jumping some steps here as there are already great articles on this part. I then installed TRUFFLE on my laptop and made sure that I could run a couple of example tutorials. http://truffleframework.com/
Once installed I setup a Truffle project that I could compile. The end result was that I had a directory with a working Truffle project that would compile and deploy. …..ok back on track now.
The directory structure and files for the project prior to writing the Truffle js test script is below:
Write a file called basic.js and PUT THIS INTO THE test directory. I got the location wrong and spent hours trying to figure out what went wrong.
The text for the file above can be found below so easy copy paste for your own learning.
// Specifically request an abstraction for basicsum
var basicsum = artifacts.require(“basicsum”);contract(‘basicsum’, function() {
//Tells you the name if the test we want to perform
it(“Check that the contract starts at 0”, function() {
//Deploy the contract and reference it through and variable called bs
return basicsum.deployed().then(function(bs) {
//Call function get, we expect to get a value back here
return bs.get.call();
//Take the result of the function call into a variable called bsoutput
}).then(function(bsoutput) {
//Take the value found in bsoutput and compare with assert equal to the values expected
assert.equal(bsoutput.toNumber(), 0, “Get did not return 0”);
});
});//Check contract value from get starts at 0
it(“Check that the contract value can change and hold value”, function() {
return basicsum.deployed().then(function(bs) {
bs.set(4);
return bs.get.call();
}).then(function(bsoutput) {
var expected = 4;
assert.equal(bsoutput.toNumber(), expected, “Get did not return 4”);
});
});
})
So what does this code do? The online tutorials and docs did not help me understand in clear plain English. I hope the examples below (which do indeed work!) should help you follow the same steps and find out how to get basic testing working.
var basicsum = artifacts.require(“basicsum”);
This line tells Truffle to add the contract basicsum that we built at the commencement of this article. The lines that follow are all dependent on this first line.
The construct that follows in lines 5 to 31 contains a reference to the basicsum contract and two tests.
contract(‘basicsum’, function() {
})
Is the definition that Truffle needs to reference the basicsum contract. Tests that follow will reference this contract. At this stage you could run the command truffle test and it should run without issue.
Next add a test.
//Tells you the name if the test we want to perform
it(“Check that the contract starts at 0”, function() {
//Deploy the contract and reference it through and variable called bs
return basicsum.deployed().then(function(bs) {
//Call function get, we expect to get a value back here
return bs.get.call();
//Take the result of the function call into a variable called bsoutput
}).then(function(bsoutput) {
//Take the value found in bsoutput and compare with assert equal to the values expected
assert.equal(bsoutput.toNumber(), 0, “Get did not return 0”);
});
});
The most basic format and template I worked from was the format below. The code.
it(“NAME OF THE TEST”, function() {
//DO SOMETHING HERE AND THE RETURN GOES INTO THE NEXT SECTION
}).then(function(RETURN_VALUE) {
//LOOK AT THE VALUE IN RETURN_VALUE AND TEST ITS VALUE
});
});
The learning experience here was that I had to first deploy the contract and use the keyword return to pass this contract to the receiving variable. Line 10 deploys the contract and passes a reference to the deployed contract to a variable called bs. Line 12 then uses bs to fire the get function call in basicsum. The output of the function call is then passed (line 14) into another variable called bsoutput.
This for me was a HUGE jump in logic from other languages and development. The final check is the call on line 16 to check the value of the return variable. As my return value in the basicsum contract is integer I have to convert this value to a numeric value. This is what the bsoutput.toNumber() does.
Now for the final test.
From the terminal goto the directory where your truffle project resides and run truffle test ./test/basic.js you can also just use truffle test, but I prefer to be specific.
To get this far from scratch and trial and error took nearly 12 hours.
So be patient, be logical and persevere. The feeling of accomplishment when you get this working is great.