Unit testing best practices

Hi Everyone,

I was wondering what everyone does with regards to unit testing for MonoGame applications.
Specifically what does everyone do with game code that take graphics related classes as parameters.

I have tried (albeit not for very long) to create a GraphicsDevice in my unit test assembly and was hoping to use that to initialise things like Texture2D etc. but haven’t had much luck getting this to work so far.

The other option is to hide everything behind interfaces which would allow me to not have to worry about the graphics related classes at all. I didn’t really want to do this as it seems a bit excessive to do this to every MonoGame class that my game may use.

Before making a decision one way or another I was wondering what approaches other people have taken.

Hi SirNanoCat,

what problems did you experience when trying to create the GraphicsDevice?

I believe it should work without problems using the DX / Windows monogame assembly. If you want to use the Windows GL version, check out this hack.

Hi Jonas,

I got as far as setting up the presentation parameters and then realised I needed a window handle to initialise everything correctly. I didn’t really want to create an actual window to get everything up and running so gave up at that point.

Ultimately I wanted to be able to run as much of the unit test code in a headless environment and wasn’t sure whether creating windows would get in the way of this.

Best Wishes

SirNanoCat

Hi again,

I like having a separate test project for functional tests that depend on the GraphicsDevice. The GraphicsDevice itself is created using the handle of a hidden form.

public class GraphicsDeviceServiceMock : IGraphicsDeviceService
{
    GraphicsDevice _GraphicsDevice;
    Form HiddenForm;

    public GraphicsDeviceServiceMock()
    {
        HiddenForm = new Form()
        {
            Visible = false,
            ShowInTaskbar = false
        };

        var Parameters = new PresentationParameters()
        {
            BackBufferWidth = 1280,
            BackBufferHeight = 720,
            DeviceWindowHandle = HiddenForm.Handle,
            PresentationInterval = PresentInterval.Immediate,
            IsFullScreen = false
        };

        _GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, GraphicsProfile.Reach, Parameters);
    }

    public GraphicsDevice GraphicsDevice
    {
        get { return _GraphicsDevice; }
    }

    public event EventHandler<EventArgs> DeviceCreated;
    public event EventHandler<EventArgs> DeviceDisposing;
    public event EventHandler<EventArgs> DeviceReset;
    public event EventHandler<EventArgs> DeviceResetting;

    public void Release()
    {            
        _GraphicsDevice.Dispose();
        _GraphicsDevice = null;

        HiddenForm.Close();            
        HiddenForm.Dispose();
        HiddenForm = null;
    }
} 

Since it takes a small amount of time to setup the GraphicsDevice, I just do it once and not in every test:

    public static GraphicsDeviceServiceMock GraphicsDevice;        

    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        GraphicsDevice = new GraphicsDeviceServiceMock();
    }

    [AssemblyCleanup]
    public static void AssemblyCleanup()
    {
        GraphicsDevice.Release();
    }

HTH, Jonas

1 Like

Thanks for this Jonas.

Ill give this a try. I’m primarily working on Mac at the moment so hopefully the Forms stuff won’t give me too much trouble.