Transcripted Summary

In this chapter, you're going to code some tests for the Voting contracts that we have created in the previous chapter.


# Start with Importing Necessary Files

First, we create our “TestVoting.sol” file in the test/ folder, then type pragma and then the solidity version.


pragma solidity >=0.4.22 <0.8.0;


import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Voting.sol";

These first two imports are referring to global Truffle files, not a Truffle directory.

Assert.sol gives us various assertions to using in our tests, so below type truffle/Assert.sol

Then type truffle/DeployedAddresses.sol. This one will deploy a fresh instance of the contract being tested to the blockchain. In our case, it is Voting.sol only for now.

Then import "../contracts/Voting.sol", which is the smart contract we want you to test.


# Set Up the Contract Tests

Then type contract TestVoting, and then you type the path of the voting contract to be tested.

Now we need to instantiate the Voting contract to the deployed contract — Voting voting = Voting(DeployedAddresses.Voting()). This will be used to call the functions inside of Voting contracts.

Then type uint256 expectedLocationId = 8. This is the expected voted location for these tests.

Then you type address expectedVotedLocation = address(this). This will return the address of the voted location.

So, notice that before we were setting the ID of the location that we are going to test. And now we are just setting what is the address of this location in the blockchain.


contract TestVoting {
    Voting voting = Voting(DeployedAddresses.Voting());

    uint256 expectedLocationId = 8;

    address expectedVotedLocation = address(this); 

# Test Function #1

Now we are going to test if the user can really vote the location with ID 8 and if the returned ID matched. So basically, we are testing the vote function here.

Type function testUserCanVoteLocation(). It is public.

Then uint256 returnedId = voting.vote(), calling the function vote from the voting contract. And then we set the expectedLocationId that we are going to use for this test.

Now we need to type Assert.equal then returnedId and then expectedLocationId.

And then the last parameter is going to be the message that we are going to display.


   function testUserCanVoteLocation() public {
       uint256 returnedId = voting.vote(expectedLocationId);


       Assert.equal(
           returnedId,
           expectedLocationId,
           "User was able to vote for the expected location and expectedVotedLocation should match what is returned."
       );
   }

Here we are just comparing the returnedId from this function with the expectedLocationId that is used for the test.


# Test Function #2

We can also test the retrieval of a single location's vote.

Now we are going to write function testGetVotedLocationAddressByLocationId() and it is public again.

In this test, we are going to compare the address in the blockchain of the location that was voted with the one that we are expecting.

Type address location = voting.locations() and then expectedLocationId.

So, the location function is going to return the address in the blockchain for this location ID.

Now we are going to write the assert, Assert.equal() which will be location.

Then expectedVotedLocation that we set in the beginning of the class,

And then the message that we're going to display.



There is an error on this function, but we are going to figure it out when compiling the contract.


# Test Function #3

Now we need to write the function to test the location address by location ID in the array.

So, write the function testGetVotedLocationAddressByLocationIdInArray(). This function is public as well.

Now type address[16] (which is the number of the bytes) followed by memory locations = voting.getLocations() (which is going to return the array of the locations).

We need to assert the location address, so Assert.equal() then ‘locations[]with theexpectedLocationId` in these array locations.

And then expectedVotedLocation which again is the address that we set in the beginning of the task.

Finally, add the message that we are going to display for these tests.


    function testGetVotedLocationAddressByLocationIdInArray() public {
        address[16] memory locations = voting.getLocations();

        Assert.equal(
            locations[expectedLocationId],
            expectedVotedLocation,
            "Voted location of the expected location should be this contract"
        );
    }

In this last test we are getting the location in memory rather than in contract storage since the memory attribute means Solidity will temporarily store the value in memory.


# Running Our Tests

Make sure you have Ganache running, go to your terminal and type truffle test on the root of the project.

When you run the test, Truffle compiles the contracts again, and also the tests.

I mentioned earlier that there was an error in the code within the tutorial video. Truffle shows a compilation error so you can go back and fix things. In this case, it was missing a bracket when closing the function.



Once I fix that, we can go back and run through a full test again, and then it's going to compile again.

And we are going to see another issue, which is the name of the function locations on the second test.

It was a typo, using “location” instead of “locations”.




# Example Code – Test #2 with Errors


// Code intentionally has 2 errors – missing function closing bracket and typo in the address location line
    function testGetVotedLocationAddressByLocationId() public {
        address location = voting.location(expectedLocationId);

        Assert.equal(
            location,
            expectedVotedLocation,
            "Voted Location of the expected location should be this contract"
        );



Now I will go back to the terminal and run truffle test again.

Here’s the complete test code without any errors for you to see it altogether.


pragma solidity >=0.4.22 <0.8.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Voting.sol";

contract TestVoting {
    Voting voting = Voting(DeployedAddresses.Voting());

    uint256 expectedLocationId = 8;

    address expectedVotedLocation = address(this);

    function testUserCanVoteLocation() public {
        uint256 returnedId = voting.vote(expectedLocationId);

        Assert.equal(
            returnedId,
            expectedLocationId,
            "User was able to vote for the expected location and expectedVotedLocation should match what is returned."
        );
    }

    function testGetVotedLocationAddressByLocationId() public {
        address location = voting.locations(expectedLocationId);

        Assert.equal(
            location,
            expectedVotedLocation,
            "Voted Location of the expected location should be this contract"
        );
    }

    function testGetVotedLocationAddressByLocationIdInArray() public {
        address[16] memory locations = voting.getLocations();

        Assert.equal(
            locations[expectedLocationId],
            expectedVotedLocation,
            "Voted location of the expected location should be this contract"
        );
    }
}

Hopefully, this time you see the contracts compiled and also the tests.

And then you see the tests that are running.



You also see the name of the test, how long they took to run, and if they passed or not.

Check Ganache and you can see the balance of the account was reduced as we did a transaction.



So here are my contacts. Feel free to drop me a message if you have any feedback or questions.



Thank you, and I hope you enjoyed the course.



Resources



© 2024 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR