Introduction To Unity Unit Testing

Learn all about how Unit Tests in Unity work and how to use them in your projects in this great tutorial. By Anthony Uccello.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Setting Up the Test Assembly and the Test Suite

Select the Tests folder and in the Test Runner window, click the Create Test Script in current folder button. Name the new file “TestSuite”.

unittest create testsuite

In addition to creating the new C# file, Unity also creates another file called Tests.asmdef. This is an assembly definition file and it’s used to point Unity to where the test file dependencies are. This is because your production code is kept separate from your test code.

If you run into a situation where Unity can’t find your test files or tests, double check to make sure there’s an assembly definition file that includes your test suite. The next step is setting this up.

To ensure the test code has access to the game classes, you’ll create an assembly of your class code and set the reference in the Tests assembly. Click the Scripts folder to select it. Right-click this folder and choose Create ▸ Assembly Definition.

Name the file “GameAssembly”.

unittest create assembly file

Click the Tests folder, and then click the Tests assembly definition file. In the Inspector, click the plus button under the Assembly Definition References heading.

You will see a Missing Reference field. Click the dot next to this field to open the selector window. Select the GameAssembly file.

You should now see the GameAssembly assembly file in the references section. Click the Apply button to save these changes.

If you didn’t follow these steps, you wouldn’t have been able to reference the game class files inside the unit test files. With that out of the way, it’s finally time to code. :]

Writing Your First Unit Test

Double-click the TestSuite script to open it in a code editor. Replace all the code with the following:

using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Collections;

public class TestSuite
{


}

What tests should you write? Truth be told, even in this tiny little Crashteroids game, there are a quite a lot of tests you could write to make sure everything works as expected. For this tutorial, you will only concern yourself with a few key areas around hit detection and core game mechanics.

Note: When it comes time for you to write unit tests on a production level product, it’s really worth taking the time to consider all the possible edge cases you need to test for all areas of your code.

For the first test, it would be a good idea to make sure that the asteroids actually move down. It would be really hard for the asteroids to hit the ship if they’re moving away from it! Add the following method and private variable to the TestSuite script and save:

private Game game;

// 1
[UnityTest]
public IEnumerator AsteroidsMoveDown()
{
    // 2
    GameObject gameGameObject = 
        MonoBehaviour.Instantiate(Resources.Load<GameObject>("Prefabs/Game"));
    game = gameGameObject.GetComponent<Game>();
    // 3
    GameObject asteroid = game.GetSpawner().SpawnAsteroid();
    // 4
    float initialYPos = asteroid.transform.position.y;
    // 5
    yield return new WaitForSeconds(0.1f);
    // 6
    Assert.Less(asteroid.transform.position.y, initialYPos);
    // 7
    Object.Destroy(game.gameObject);
}

There’s only a few lines of code here, but there’s a lot going on. So, take a moment and make sure you understand each part:

  1. This is an attribute. Attributes define special compiler behaviors. It tells the Unity compiler that this is a unit test. This will make it appear in the Test Runner when you run your tests.
  2. Creates an instance of the Game. Everything is nested under the game, so when you create this, everything you need to test is here. In a production environment, you will likely not have everything living under a single prefab. So, you’ll need to take care to recreate all the objects needed in the scene.
  3. Here you are creating an asteroid so you can keep track of whether it moves. The SpawnAsteroid method returns an instance of a created asteroid. The Asteroid component has a Move method on it (feel free to look at the Asteroid script under RW / Scripts if you’re curious how the movement works).
  4. Keeping track of the initial position is required for the assertion where you verify if the asteroid has moved down.
  5. All Unity unit tests are coroutines, so you need to add a yield return. You’re also adding a time-step of 0.1 seconds to simulate the passage of time that the asteroid should be moving down. If you don’t need to simulate a time-step, you can return a null.
  6. This is the assertion step where you are asserting that the position of the asteroid is less than the initial position (which means it moved down). Understanding assertions is a key part of unit testing, and NUnit provides different assertion methods. Passing or failing the test is determined by this line.
  7. Your mom might not yell at you for leaving a mess after your unit tests are finished, but your other tests might decide to fail because of it. :[ It’s always critical that you clean up (delete or reset) your code after a unit test so that when the next test runs there are no artifacts that can affect that test. Deleting the game object is all you have left to do, since for each test you’re creating a whole new game instance for the next test.

Passing Tests

Great job! You’ve written your first unit test, but how do you know if it works? The Test Runner of course! In the Test Runner window, expand all the arrows. You should see your AsteroidsMoveDown test in the list with a gray circle:

The gray circle means the test has not yet been run. When a test is run and passes it’ll show a green arrow. If a test fails, it’ll show a red X. Run the test by clicking the RunAll button.

This will create a temporary scene and run the test. When it’s done you should see that the test passed.

You have successfully created your first passing unit test, which asserts that spawned asteroids move down.

Note: Before you write unit tests of your own, you need to understand the implementation you’re testing. If you’re curious how the logic you’re testing works, feel free to look at the code under RW / Scripts.