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 4 of 4 of this article. Click here to view the first page.

Ensuring Lasers Destroy Asteroids

Next, you are going to make sure that a laser will destroy an asteroid if it hits it. Open the editor and add the following test at the bottom of TestSuite and save:

[UnityTest]
public IEnumerator LaserDestroysAsteroid()
{
    // 1
    GameObject asteroid = game.GetSpawner().SpawnAsteroid();
    asteroid.transform.position = Vector3.zero;
    GameObject laser = game.GetShip().SpawnLaser();
    laser.transform.position = Vector3.zero;
    yield return new WaitForSeconds(0.1f);
    // 2
    UnityEngine.Assertions.Assert.IsNull(asteroid);
}

Here’s how this works:

  1. You are creating an asteroid and a laser, and making sure they have the same position so as to trigger a collision.
  2. A special test with an important distinction. Notice how you are explicitly using UnityEngine.Assertions for this test? That’s because Unity has a special Null class which is different from a “normal” Null class. The NUnit framework assertion Assert.IsNull() will not work for Unity null checks. When checking for nulls in Unity, you must explicitly use the UnityEngine.Assertions.Assert, not the NUnit Assert.

Return to the Test Runner and run this new test. You’ll see that satisfying green check mark. :]

To Test or Not To Test

Deciding to commit to unit tests is a big commitment, and should not be taken lightly. However the payoffs can certainly be worth it. There is even a methodology of development known as Test Driven Development (TDD).

With TDD, you actually write tests before you write your application logic. You make tests first, ensure they fail, and then only write code designed to get the test to pass. This can be a very different approach to coding, but it also ensures you’ve written your code in a testable way.

Keep this in mind if you decide to take the plunge on your next project. For now, it’s time to write your own unit tests, but to do that you need a game — which is all provided for you.

Note: Deciding whether to test only public methods or also private methods is something you need to consider. Some people believe that private methods should only be tested through the public methods that use them. This can make the “unit” of code you need to test quite large, and might not be desirable. On the flip side, testing private methods can be problematic and requires special frameworks or using reflection tools to check things. Each scenario has its pros and cons, which are beyond the scope of this tutorial. This tutorial will set all methods to be tested to public to make things easier to follow — so don’t use this tutorial as a best practices reference when it comes to production code.

Testing can be a big commitment, so it would be worth taking a look at the pros and cons of adding unit testing to your project:

Unit Testing Pros

There are a lot of important upsides to unit testing, which include the following:

  • Provides confidence that a method behaves as expected.
  • Serves as documentation for new people learning the code base (unit tests make for great teaching).
  • Forces you to write code in a testable way.
  • Helps you isolate bugs faster and fix them quicker.
  • Prevents future updates from adding new bugs to old working code (known as regression bugs).

Unit Testing Cons

However, you might not have the time or budget to take on unit testing. These are the downsides you should consider:

  • Writing tests can take longer than writing the code itself.
  • Bad or inaccurate tests create false confidence.
  • Requires more knowledge to implement correctly.
  • Important parts of the code base might not be easily testable.
  • Some frameworks don’t easily allow private method testing, which can make unit testing harder.
  • If tests are too fragile (fail too easily for the wrong reasons), maintenance can take a lot of time.
  • Unit tests don’t catch integration errors.
  • UI is hard to test.
  • Inexperienced developers might waste time testing the wrong things.
  • Sometimes, testing things with external or runtime dependencies can be very hard.

Testing that Destroying Asteroids Raises the Score

Time to write the last test. With the code editor open, add the following to the bottom of the TestSuite file and save:

[UnityTest]
public IEnumerator DestroyedAsteroidRaisesScore()
{
    // 1
    GameObject asteroid = game.GetSpawner().SpawnAsteroid();
    asteroid.transform.position = Vector3.zero;
    GameObject laser = game.GetShip().SpawnLaser();
    laser.transform.position = Vector3.zero;
    yield return new WaitForSeconds(0.1f);
    // 2
    Assert.AreEqual(game.score, 1);
}

This is an important test that makes sure that when the player destroys an asteroid that the score goes up. Here’s how it breaks down:

  1. You’re spawning an asteroid and a laser, and making sure they’re in the same position. This ensures a collision occurs, which will trigger a score increase.
  2. This asserts that the game.score int is now 1 (instead of the 0 that it starts at).

Save your code and go back to the Test Runner to run this last test and see that it passes:

Amazing work! All the tests are passing.

Where to Go From Here?

You covered a lot of ground here. If you want to compare your work with the final project, you can find the Download Materials at the top or bottom of this tutorial.

In this tutorial, you’ve learned what unit tests are and how to write them in Unity. You also wrote six unit tests that all passed successfully and learned some of the pros and cons of unit testing.

Feeling confident? There are plenty more tests you could write. Try looking at all the game class files and writing unit tests for other parts of the code. Consider adding tests for the following scenarios:

  • Each asteroid type triggers game over when it crashes into the ship.
  • Starting a new game sets the score to 0.
  • Moving left and right works correctly for the ship.

If you’re interested in taking your unit testing to the next level, you should look into dependency injection and mocking frameworks. This can make it a lot easier to configure your tests.

Also read through the NUnit documentation to learn more about the NUnit framework.

And don’t be shy, share your thoughts and ask your questions in our forums.

Happy Testing!