Implementing Unit Testing in Unity — The Basics
A basic overview of creating Unit Test in Unity.
Imagine in the ideal world that your code always works as intended. No compile errors, no runtime errors, and the game magically works in one try! It will be a very happy world for programmers to live in.
However, that’s always not the case. In reality, there will be some defects in your code. Sometimes, it will be as easy as your code not compiling. A lot of times, though, you will encounter errors after you play and test the game.
This is why we need to test our game. The most typical form of testing game is manual testing, You have to build the game, give it to some testers, and provide lists of steps to reproduce the feature you’re implementing. This is very time-consuming and expensive, and may result in a longer development cycle.
Unit Test
Enter Unit Testing. It’s a kind of automated testing, where a “unit” of your code is tested and validated with a set of determined output. A “unit” of code is not strictly defined, but it can be a function, class, or a library, etc. Unit testing means that we will perform a set of tests to validate whether the unit is functioning as intended — for example, if an “enemy” really “destroyed” when it dies.
In this series of article, I will share on how to build a simple project in Unity while using Unit Test. We are going to reproduce a super-simplified version of the famous Slay the Spire. We will recreate its basic mechanics, and use Unity Test Runner to validate whether the game is working as intended. We will call the game, um, Slay the Dragon 😄
Health
First, we will begin by creating one of the most basic implementation in Slay the Spire: Health Points. In the game, this is the basic rule of Health Points :
- Health cannot go below zero, and cannot go above maximum health.
After we understand the rules, we will go and create Health
class on our project, and implement two methods, SetHp()
and Damage()
. Health
also have two properties, MaxHp
and CurrentHp
.
This is the basic implementation of Health.cs
:
Simple.
Next, we will create a Unit Test to test the functionality. But before we can write the tests, we will need to set up the Unity Test Framework to use it. Let’s go!
Setting Up
Importing Unity Test Framework
Performing Unit Testing in Unity requires you to import Test Framework package from Unity’s Package Manager window. Navigate to your Package Manager window, and find Test Framework package, and import it to your project.
Assembly Definition
Afterwards, in order to use Unity Test Runner, you must put your script in an Assembly Definition. Assembly Definitions enforces your script to be packaged into an assembly, and enables you to slice your game into separate assemblies and refers them as necessary. For more details, please refer to this link.
Put the Health.cs
script in the Scripts
folder and create and Assembly Definition file (I will use Prototype.SlayTheDragon as the filename).
EditMode Test Assembly Folder
We will create our Unit Test as an Edit Mode test, meaning that we will not use Unity’s loop (Update, etc.) to test our game.
Create a folder called Tests
, then open the Test Runner window (Window > General Test Runner). Then, click your Tests
folder in the inspector, and click the Create EditMode Test Assembly Folder. Fill the folder name with EditMode.
You should notice that another assembly definition file called EditMode will appear on the folder. Then, in order for this assembly able to access our Prototype.SlayTheDragon assembly, we need to add it in the Assembly Definition References. Click on the EditMode assembly, and Prototype.SlayTheDragon assembly to the references, as such :
Now, we are ready to create our first test 😎
Testing the Health
Now, we will create our Unit Testing for Health
class. Under EditMode folder we just created, create a new empty C# scripts called HealthTests.cs
. Because Unity uses NUnit Framework for the base of Unity Test Runner, add both of these using statement in the script :
using NUnit.Framework;
using Prototype.SlayTheStarship;
Let’s refresh our mind that the aim for Unit Testing is to have the “unit” of your code is tested and validated with a set of determined output. The next question is: what to test?
We know already that Health in Slay the Spire has the following condition :
- Health cannot go below zero, and cannot go above maximum health
Therefore, we will create tests that validates these conditions. Let’s do it!
Test 1 : Current health cannot go above maximum health
One “Unit Test” in NUnit is defined by a method with void
return type, and marked with [Test]
attribute. As for the function name, it will be different from naming a normal function. I will use the following name for this function :
[Test]
public void SetHp_Must_Not_Exceed_MaxHp()
{}
We will create a test based on Arrange-Act-Assert pattern.
In Arrange, we will set-up the Health instance with 100 maxHp
:
// ARRANGE
Health health = new Health(100);
In Act, we will try to set the health to exceed its maxHp
(let's say 1000).
// ACT
health.SetHp(1000);
Lastly, in Assert, we will validate the currentHp value with the expected value. Based on our rule, Health cannot go above maximum health, so we will use the maxHp
value to Assert it.
// ASSERT
Assert.AreEqual(100, health.CurrentHp);
Therefore, the complete Unit Test is the following:
That’s it. Our first test is done 🙂
Before we run the test, let’s create another test to check that the health cannot go below zero.
Test 2 : Current health cannot go below zero.
Based on Arrange-Act-Assert pattern again, we’ll try to SetHp
to negative value and assert the currentHp
. We will Assert that the currentHp
should be valued at zero.
This is the Unit Test :
Running The Test
We’ve completed writing the test, now it’s time to test it. Go to Test Runner Window, and Click the Edit Mode tab. Here, you’ll see the list of Unit Test you’ve written and its status. By default, it’ll look something like this :
Now, click the Run All button, and Unity will run the tests for you 🙂
The green “check” icon represent that your test have passed. Congratulations!
Wrapping It Up
In this post, I have shared some basic understanding about Unit Test and create a simple test for Unity. Having Unit Testing suites in your project will benefit the quality of your game, because it can automatically checks for wrong behaviour in your implementation.
In the next article, I will dig deeper into creating more implementation of Slay the Spire’s game using Unit Test. I will also share about some common practices in implementing Unit Test, so that it will be easier to create and maintain. Stay tuned!