Unit Testing in XNA


Before going into greater detail about the helper classes for the upcoming projects in this book, this section talks a little bit about unit testing. You already learned about static unit tests in the last chapter. Static unit tests are great for quickly checking visual results, testing physics and the controllers, and building your game in a quick manner. But helper classes and components that do not require user input would require you to think about interfacing with them. That makes no sense because unit testing is all about improving the maintainability of your application and making sure everything runs as errorless as possible. For example, to test if the Log class works you could call the following lines of code:

  FileHelper.DeleteFile(Log.LogFilename); Log.Write("New log entry"); 

Tip 

This code can only be executed inside the Log class because Log.LogFilename is private.

Now you could go into the application directory and check if the log file exists and has an entry with the “New log entry” text in it. But checking this file yourself over and over again is a bit of a hassle. Instead of logging every error here you should only put the less important warning messages (e.g. user is not connected to the internet) into the log and throw exceptions when fatal errors occur (e.g. texture not found, no shaders available, etc.). This is especially true if the problems become bigger and the tests are much more complex and involve a very lengthy check process. You can avoid checking for errors yourself by letting these tests check themselves and let them be executed automatically instead of calling them yourself from the Program class like static unit tests.

NUnit and TestDriven.Net

To do this you can use the popular NUnit Framework, which you can download at http://www.nunit.org/.

Alternatively you can also use TestDriven.NET from http://www.testdriven.net/ if you are using Visual Studio 2005 Professional or better. It supports many cool features and you can start tests directly with hotkeys or the popup menu, which is really cool and simple. TestDriven.Net does not work in VC# Express or XNA Studio Express (it did work a year ago, but the developer had to remove the plugin support for Express because Microsoft wants developers to use the Professional Edition for serious programmers). See Chapter 1 on how to get XNA working in Visual Studio 2005; use a dummy project from XNA Studio Express for processing your content, which is not possible in Visual Studio 2005.

It does not matter which one you install, just add the NUnit.Framework.dll from the installation folder to your project (right-click your project references and add a new reference; use Browse if you can’t find it in the Global Assembly Cache (GAC), which is represented in the first tab). Now you can add the following using directive:

  #if DEBUG using NUnit.Framework; #endif 

I usually add this at the very top of the using directives region and the reason why this is used only in debug mode is the fact that you will only use the unit tests in your debug build; for the final game you don’t want the extra NUnit.Framework.dll and all the testing code, because it is not required for your game.

As an example, take a look at the first unit test in the StringHelper class, which checks if the IsInList helper method works as expected:

  [TestFixture] public class StringHelperTests {   /// <summary>   /// Test IsInList   /// </summary>   [Test]   public void TestIsInList()   {     Assert.IsTrue(IsInList("whats",       new string[] { "hi", "whats", "up?" }, false));     Assert.IsFalse(IsInList("no way",       new string[]       { "omg", "no no", "there is no way!" }, false));   } // TestIsInList() ... 

Assert is a helper class inside the NUnit framework and it contains methods to check if the return values are as expected. If the value is not as expected an exception will be thrown and you can immediately see which line of your test failed. For example, Assert.IsTrue checks if the return value of IsInList is true. If the return value is false, an exception will be thrown. Luckily the string list contains “whats” and the test should pass. The next test checks for “no way” and that string is not in the second string list and therefore the second test line should return false as it does. Note: “there is no way!” contains “no way,” but you were not checking the Contains method, which also exists in the StringHelper class. IsInList only returns true if the exact string was found in the list.

Starting Unit Tests

You can run the test in TestDriven.Net by clicking the right mouse button and selecting “Run Test” (see Figure 3-6) or you can use the NUnit GUI program if you don’t have or cannot use TestDriven.Net. You can also test static unit tests the same way with TestDriven.Net, but the NUnit GUI does not support static unit tests. For this reason I added the unit tests in Program.cs (or the UnitTesting.cs class in later projects) to support all users and XNA Studio Express. TestDriven.Net can be used to start both dynamic and static unit tests, but since version 2.0 you will have to remove the [Test] attribute from static unit tests in order to work properly (you don’t use the [Test] attributes for static unit tests in this book anyway).

image from book
Figure 3-6

The test will execute without any error, but if you were to change the test by changing “whats” to “whats up” the first Assert test would fail and you would see the following results from TestDriven.Net:

  TestCase 'M:XnaBreakout.Helpers.StringHelper.StringHelperTests.TestIsInList' failed:   NUnit.Framework.AssertionException   at NUnit.Framework.Assert.DoAssert(IAsserter asserter)   at NUnit.Framework.Assert.IsTrue(Boolean condition, String message, Object[] args)   at NUnit.Framework.Assert.IsTrue(Boolean condition)   C:\code\XnaRacer\Helpers\StringHelper.cs(1387,0): at     XnaBreakout.Helpers.StringHelper.StringHelperTests.TestIsInList() 0 passed, 1 failed, 0 skipped,  took 0,48 seconds. 

This tells you exactly where to look (you can even double-click the error and jump to the line 1387) and what you should change. The error becomes even more visible if using the NUnit GUI (see Figure 3-7).

image from book
Figure 3-7

The NUnit GUI is a good tool to run many unit tests at once and quickly see which ones did not work properly and then investigate further in the source code. You can use File image from book Load to select your program or just drag and drop any .NET .exe or .dll file onto the NUnit GUI program. Then you see all the tests in that assembly and can test them by clicking Run. The program is nice, but I usually don’t go outside of my programming environment when coding and testing, and therefore I like TestDriven.Net a lot more and use it all the time. To fix the error you just change the “whats up” line back to “whats” and all your tests will pass and you get a green light.

Golden Rules

I did not go much into writing unit tests here because Chapter 2 already discussed the basic rules, which of course also apply for dynamic unit tests. Keep these guidelines in mind when you start writing your first unit tests:

  • Think about your problems and divide them into small manageable parts.

  • Write the tests first and do not think about the implementation, just write them down like you think the final code should look or like you want to have your game code.

  • Try to make sure you test as much as possible. For example, the TestIsInList method tests both a successful call to IsInList and a failure from the IsInList call. Spend time with your unit tests, but never more than 50% - you should not have to write 30 checks for a method that has only two lines of code.

  • Start the test constantly from this point on, even when you think it does not make sense. It will force you to see what has to be done and how far you are in the implementation process. At first the test will not even compile because you haven’t implemented anything. Then after implementing empty methods the test should fail because you are not doing anything yet. Later when everything works you will feel much better.

  • Though you will not test your static unit tests very often, dynamic unit tests can be tested every single time you compile your code (if they all run quick enough). Always try to run all unit tests once a day or once a week to make sure your latest code changes did not add new bugs or errors.




Professional XNA Game Programming
Professional XNA Programming: Building Games for Xbox 360 and Windows with XNA Game Studio 2.0
ISBN: 0470261285
EAN: 2147483647
Year: 2007
Pages: 138

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net