Write a Solidity Test Case

The course is part of this learning path

Start course
1h 2m

In this lecture, we run through testing in Solidity and carry out a variety of tests on the game that we have been creating in previous courses in this learning path.


Now that we have written our JavaScript tests in the previous lectures, I want to go a little bit more bare metal, a little bit more down to the actual solidity level and write a test in solidity. And I will write a very, very simple test just to see how things are working in solidity test cases. There are a couple of things that are different to how you write tests in JavaScript. I'm here in the truffle documentation which you can find on and then you just basically go down to testing and writing tests in solidity and it should bring up a page which looks like this or very similar. So, what is the first thing that is the difference to a JavaScript test? Our tests in JavaScript have the ending Js and our tests in solidity, our solidity files they have the ending sol. If you run the truffle test with truffle test, then you should have a separate test suite protest contract. And if these are run then they have the same feature which is a clean room environment protest suite. So, you don't have to think about any state that youre smart contracts are currently in. They will be redeployed from scratch. Alright, the second thing is which is not so much mentioned in these docs here, your test files, the solidity files have to have the same name as the contract inside of them. So, you cannot just write for_testMetacoin, you have to write the file, testMetacoin and then have the contract inside testMetacoin or else truffle will not pick it up. Let's write our first test. Very simple one in truffle into our game. Alright, I'm back here in our game. And inside the test folder I'm creating a new file and I call this file TestGamemanager.sol. And what we're going to test is that our Highscore list is empty at the beginning. So, it should show you two things. The first one is if you call the Gettop10 from the Gamemanager not from the Highscoremanager, but it's the same return value. Then you get back a list of two arrays. So, I want to show you how you get back this list of two arrays. And then we're going to assert that at the  beginning when the Highscoremanager has deployed this list will be totally empty. There will be nothing inside. So, our first position will have the zero address, and our first position will have no wins at all. Okay, let's test this. The first line in our solidity file is a pragma line; doesn't change anything, ^0.5.0 for now. And then we have a couple of import statements. The first one is we are importing from "truffle/Assert.sol." We are importing from "truffle/DeployedAddresses.sol" and we are going to import our actual Gamemanager; /contracts/GameManager.sol file. These are the files that we are importing here and then we have our contract TestGameManager. And inside our testGamemanager contract, we have the actual tests and tests they start with the keyword test. So, we have a function testInitialHighscoreIsZero() for example, It's going to be public. So, you have to roll with the latest solidity semantics here. And what we can do next is we want to have the instance of the gameManager that is already deployed. How do we get this? Inside the deployed addresses, smart contract, we have for each of the smart contracts that truffle is deploying, a function which returns as the address. Let me show you this here. What is this in a more theory version? If you go to the truffle documentation and scroll to the point deployed addresses, then you find this code snippet which has DeployedAddresses name>(). So, the function for the actual contract name will give you the address under which the contract can be found. And we can use this to get the instance  or to initialize an instance with an address where and contract is already running. How do we do this? GameManager, GameManager = GameManager(...) and then it should give an address here. If you want to create a new instance, then you write new. If you have an instance already running somewhere, then you need the address and the address here is under (DeployedAddresses.GameManager()). Alright, now we can access all the functions, all the suite functions from our game manager as if we are just working with object-oriented objects and in our case we would want to get the getTop10 list, and if you go back to the GameManager and see the getTop10 then you see it returns a list of an address 10 array and an unsigned integer 10 array. And we can use this and I just basically copy this now and I say, our address 10 memory is going to be our top10Addresses and our unsigned integer 10 Memory is top10Wins for example. And then we can use this to assert something. And assertions works with this assert library, so we can do Assert.equal(top10Wins[0], 0, "Initially there should no wins at all"). And then we're going to run this. So, let's just run this truffle test  .\test\testGamemanager.sol. Obviously, you have to have your ganache started in the background. So, if you don't have your ganache started yet, then start ganache before you are starting this test. Okay, it takes a while, and then it should output. Okay, the test is done. Now we have also run unused local variable which is an address10, top10Addresses, and here you come in which is the challenge for this part extend this test so that we also know our first place at the beginning should have the address zero. It's probably very easy. Give it a couple of minutes to write this test and pause the video now and then I will show you how to do it. Okay, probably you already got this from the beginning on Assert.equal(top10Addresses[0], address(0), "Initially there should be nobody on our top10 list"). Okay, I'm going to execute this one more time and then I also want to show you what it is if the assertion fails. It's also interesting, right? Alright, this assertion goes through. There is no warning, no nothing whatsoever. So, let's say our assertion fails here. What happens then? And we have an error. Initially, there should be nobody in our top10 list. So, it just outputs us the error here. It says failing. So, it all is very nice and sweet. If we have tests for all functions, for everything that is within our smart contracts, and we work in teams then this one is really the way to go. Once you clone a project, you start the tests, you start writing your own code, you restart the test, and see if all the tests are still passing. If they're not, then you broke something. And obviously if you do test driven development, you write your tests first before you are actually writing your code. So, they are failing at the beginning and you write your code until the test cases are not failing anymore. This means you should write test cases for everything. Now in this course, obviously, we are not writing test cases for everything because this course would be much longer and probably extremely boring if we start writing tests for all different situations we're in. But if you write a real world products, then tests are very important mostly underrated. Take time to write your tests. It is important to have every aspect of your smart contracts tested. Alright, with this, we are going into the next part of our app which is the actual frontend. Right now, so far, we've worked in truffle here, but that's pretty boring. We need some how a way to click around on the field, an actual field. We need to have this highScore list at the beginning and we need to have a nice way to interact with our smart contract without writing any code for a command line interface and that is the part of our next section, the game in HTML and JavaScript. So, that one is the most meaty section where everything comes together that we've learned. I'll see you in the next lecture.


About the Author

Tom is a CTO, senior back-end developer, and systems architect with over twenty years of hands-on development experience in a variety of languages and systems. He has a CS master's degree and has been working with Ethereum and blockchain technologies since 2016.

Covered Topics