PlanetX – Unit Testing an XNA game with Resharper and NUnit

I decided to setup some unit testing on my XNA 4 game before it’s too late.

I’m a huge fan of ReSharper (http://bit.ly/ekRH5g ), and I really cannot work without it and a few other plugins installed.

StyleCop for ReSharper (http://bit.ly/f0AKep) is one of them, VSCommands 2010 is another one http://bit.ly/dJPuFA, but this is not time to describe what my ideal setup is.

Back to the Unit Testing, Resharper supports OOTB nunit (http://bit.ly/eVqGrT) and as mocking framework Moq(http://bit.ly/fXXbhT) is my choice.

So, how do you start to test your XNA game?

Well follow these steps:

  • Add a new XNA Windows Game on your solution
  • Remove the Content Project that was created with this Game
  • Select Content References and add the Content Project used in your game
  • [OPTIONAL] Download Moq (http://bit.ly/fXXbhT) and add a reference to Moq.dll or add it using NuGet (http://bit.ly/gu5yxB)
    image
  • Download nunit (http://bit.ly/eVqGrT) and add a reference to nunit.framework.ddl and nunit.core.dll
  • Add a reference to System.Windows.Forms and System.Drawing
  • Create a folder called Helpers
  • Download MockedGraphicsDeviceService.cs and DeviceType.cs from (http://bit.ly/gqWHpP) and place them in the Helpers folder.
  • Create a new class in Helpers called AssemblyUtilities.cs, the class must be like
  • /// <summary>    /// The assembly utilities.    /// </summary>    internal class AssemblyUtilities    {        #region Public Methods
    
            public static void Copycontent()        {            var buildLocation = typeof(AssemblyUtilities).Assembly.CodeBase.Remove(0, 8).Replace((typeof(AssemblyUtilities).Assembly.ManifestModule).Name, string.Empty).Replace("/", @"\") + @"\Content";            var deployLocation = typeof(AssemblyUtilities).Assembly.Location.Replace((typeof(AssemblyUtilities).Assembly.ManifestModule).Name, string.Empty) + @"\Content";            Directory.CreateDirectory(deployLocation);
    
                //Now Create all of the directories            foreach (string dirPath in Directory.GetDirectories(buildLocation, "*", SearchOption.AllDirectories))                Directory.CreateDirectory(dirPath.Replace(buildLocation, deployLocation));
    
                //Copy all the files            foreach (string newPath in Directory.GetFiles(buildLocation, "*.*", SearchOption.AllDirectories))                File.Copy(newPath, newPath.Replace(buildLocation, deployLocation), true);
    
            }
    
            /// <summary>        /// Use as first line in ad hoc tests (needed by XNA specifically)        /// </summary>        public static void SetEntryAssembly()        {            SetEntryAssembly(typeof(AssemblyUtilities).Assembly);        }
    
            /// <summary>        /// Allows setting the Entry Assembly when needed.         /// Use AssemblyUtilities.SetEntryAssembly() as first line in XNA ad hoc tests        /// </summary>        /// <param name="assembly">        /// Assembly to set as entry assembly        /// </param>        public static void SetEntryAssembly(Assembly assembly)        {            var manager = new AppDomainManager();            FieldInfo entryAssemblyfield = manager.GetType().GetField(                "m_entryAssembly", BindingFlags.Instance | BindingFlags.NonPublic);            entryAssemblyfield.SetValue(manager, assembly);
    
                AppDomain domain = AppDomain.CurrentDomain;            FieldInfo domainManagerField = domain.GetType().GetField(                "_domainManager", BindingFlags.Instance | BindingFlags.NonPublic);            domainManagerField.SetValue(domain, manager);        }
    
            #endregion    }

You’ll need this class to fix a problem with the execution context of the tests with ReSharper, and to copy the Content folder from the build folder to the folder where the test is executed

  • Create a new class where you want to place your tests (Tests.cs
  • Add this code to your class
  •  [TestFixtureSetUp]        public void SetUpTest()        {            AssemblyUtilities.Copycontent();        }
    
            [SetUp]        public void SetUp()        {            AssemblyUtilities.SetEntryAssembly();        }

That will call the AssemblyUtilities methods as required

  • Add your test method
  • [Test]        public void Test()        {            var gd = new MockedGraphicsDeviceService(DeviceType.Hardware, GraphicsProfile.HiDef);            gd.CreateDevice();            var contentManager = new ContentManager(gd.ServiceProvider) { RootDirectory = "Content" };            var resource = contentManager.Load<Texture2D>("Sprites/blank");        }

In this method we are using MockedGraphicsDeviceService to semi mock the GraphicsDevice so we can work with around it to test the other components of our game

Two important points:

  1. You have to set your TestGame to run on the full .NET 4 framework in order to make Moq work
  2. image

 

There you have your Unit Test Library ready to use:

image

P.S: you need to have a Sprites/blank.png file on your content project in order for this test to pass

Download the code sample from http://bit.ly/eVxZmr

Enjoy your unit testing Smile

Advertisements

One thought on “PlanetX – Unit Testing an XNA game with Resharper and NUnit

  1. This approach may result in very slow build times for your game.

    Having multiple projects (your original game project, and the unit test project) both reference the game’s content project may cause visual studio to rebuild all of your game’s content every time you make a small change to the code. This is the issue I ran into with my project, and I pinned this down as the cause after reading this forum post:

    http://forums.create.msdn.com/forums/p/58671/359790.aspx#359790

    Instead of adding a reference to the content project, what I ended up doing is setting my original game project as a dependency of the unit test project (right click on the solution in the solution explorer, choose “Project Dependencies”, select the unit test project from the dropdown, and under “Depends on”, I checked the original game project).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s