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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Introduction To Unity Unit Testing
30 mins
- What Is a Unit Test?
- Looking at Example Unit Tests
- Starting Up the Game
- Getting Started with the Unity Test Runner
- Setting Up NUnit and Test Folders
- What’s in a Test Suite?
- Setting Up the Test Assembly and the Test Suite
- Writing Your First Unit Test
- Passing Tests
- Using Integration Tests
- Adding Tests to the Test Suite
- Setting Up and Tearing Down Phases
- Testing Game Over and Laser Fire
- Asserting Laser Movement
- Ensuring Lasers Destroy Asteroids
- To Test or Not To Test
- Unit Testing Pros
- Unit Testing Cons
- Testing that Destroying Asteroids Raises the Score
- Where to Go From Here?
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:
- You are creating an asteroid and a laser, and making sure they have the same position so as to trigger a collision.
- 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.
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:
- 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.
- 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!