Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 2 (28 posts) 1 2 Next >

Mocking XNA Game object

Last post 9/14/2009 2:07 PM by Gnomic Studios. 27 replies.
  • 5/4/2009 7:49 PM

    Mocking XNA Game object

    I was wandering if there was a good way to mock a Game object so that I could test my drawable game components, in isolation?

    For example stuff like Tile and Sprite.

    I posted this question on stack overflow, because these XNA forums are slow as a turtle (in terms of loading times), but it seems people don't know how to solve this exactly:
    http://stackoverflow.com/questions/804904/xna-mock-the-game-object

    Any help appreciated!
  • 5/4/2009 7:56 PM In reply to

    Re: Mocking XNA Game object

    "Hey XNA Game object, you're so ugly that even your private constuctor won't make an instance of you"....

    I know a couple of people have tried this but I can't find the forum posts right now... I'm pretty sure they came to the conclusion that it was a lot of work to mock the whole game object up enough to get unit tests out of it.
  • 5/4/2009 8:21 PM In reply to

    Re: Mocking XNA Game object

    I see.
    That makes little sense to me, because if I have a "Car" object, for example, I really want to be able to test behavior like car.collide(rect) or:

    car.speed=10
    car.direction = (0, -1)
    car.update(sometime)
    verify car.position

    This is just a silly example, but other more complicated things exist which I cannot test just by playing my game.

    Thanks.
  • 5/4/2009 8:27 PM In reply to

    Re: Mocking XNA Game object

    Hopefully Shawn will pop in, I seem to remember he had an opinion on this - they use Unit Testing on the XNA Framework so they are ware of the issues.

    Its trivial to mock object that sort of car object. But the Game object is what is running the whole game, all your code is called by it. So you are going to have to implement almost all of it and then some just so that the code you are trying to test gets called properly... At least thats what I remember from the other threads... there's plenty of TDD folk round here to correct me though.
  • 5/4/2009 8:36 PM In reply to

    Re: Mocking XNA Game object

    Answer
    Reply Quote
    Successful unit testing is all about minimizing dependencies. If your car object requires a mock Game instance in order to run its unit tests, that strikes me as an overly-close coupling. Why does the car class require a Game at all? Break that dependency, and your problem goes away.

    The XNA Framework does not support mocking types such as Game or GraphicsDevice. We decided it would impose too much runtime overhead if we made everything an interface in order to enable that. You could build your own abstraction layer on top of our types, then mock that abstraction of your own, but:

    a) that's going to be a lot of work
    b) you're going to pay a perf penalty
    c) are you sure you really need this in any case?

    I'm not convinced that for instance testing graphics code with a mock graphics device is particularly useful. If you factor your code right, you can test all your game logic without ever creating a Game or GraphicsDevice. But when it comes to testing your graphics, you really need to draw some stuff and then check that it drew the right image for the test to be valid. For that, you need to create an actual GraphicsDevice, rather than just mocking all the graphics API to noop.
  • 5/4/2009 8:50 PM In reply to

    Re: Mocking XNA Game object

    I was thinking the same thing.
    Currently my car looks like this:

    class Car: DrawableGameComponent{
       public override Draw(..){}
       public override Update(..){..}
    }

    I just went with the ideology that each object should take care of drawing and updating itself.

    What would be a better option?
    To have something like:

    class Car{
      Vector2 position;
      int speed;
      ...
    }
    class GamePlay:DrawableGameComponent{
        Car car;  
        public override Update(time){
            car.position +=  time * car.speed
        }
        public override Draw( ){
           spritebatch.draw(car.texture, car.position, ...)
        }
    }

    But now it is not clear where to handle all key-events for the car, as instead of being handled by Update() method,
    they will now have to be handled by someone else. Yap, I know i am hopeless...
  • 5/4/2009 9:03 PM In reply to

    Re: Mocking XNA Game object

    Your car can still have Update and Draw methods; just don't make it derive from DrawableGameComponent. Then just call those methods from your game or another place and let it still handle it's own logic and drawing.

    Alternatively you could build your own base game component class that doesn't rely on the Game object, but instead just requires an IServiceProvider. Then you can implement your own IServiceProvider to give the component an IGraphicsDeviceService and you'll be all set. Here are a couple of my classes: BasicGameComponent (requires neither Game nor IServiceProvider) and BasicDrawableGameComponent (requires an IServiceProvider instead of a Game). The only note is that the Initialize method in BasicDrawableGameComponent uses an extension method I wrote for IServiceProvider to get a service out using generics; just replace that with the normal GetService method and you'll be fine.
  • 5/4/2009 9:13 PM In reply to

    Re: Mocking XNA Game object

    Shawn Hargreaves:
    Successful unit testing is all about minimizing dependencies. If your car object requires a mock Game instance in order to run its unit tests, that strikes me as an overly-close coupling. Why does the car class require a Game at all? Break that dependency, and your problem goes away.

    To be fair, our GameComponent class has this dependency, and we encourage people to use it. If the car class derives from GameComponent, then the developer was coerced into the overly-close coupling by the XNA Framework!

    While developers can go ahead and implement their own IGameComponent and IUpdateable in a class that doesn't depend on Game, that's a bit of a pain and it's a shame we didn't do it for them in the first place. For that matter, why doesn't IGameComponent.Initialize take an IServiceProvider parameter instead of forcing the class implementing the interface to have an implementation-specific method of connecting to its hosting environment?

    Considering the public methods on Game, what is the chance of a noticeable performance penalty in providing an abstraction of it to game components? The public members of Game don't get called that many times per frame. In the case of the properties, which are mainly there for convenience, the values can easily be cached locally to resolve any issues that might come up.

    For GraphicsDevice, on the other hand, I completely agree with you. :)
  • 5/4/2009 9:18 PM In reply to

    Re: Mocking XNA Game object

    Nick Gravelyn:
    Your car can still have Update and Draw methods; just don't make it derive from DrawableGameComponent. Then just call those methods from your game or another place and let it still handle it's own logic and drawing.

    Alternatively you could build your own base game component class that doesn't rely on the Game object, but instead just requires an IServiceProvider. Then you can implement your own IServiceProvider to give the component an IGraphicsDeviceService and you'll be all set. Here are a couple of my classes: BasicGameComponent (requires neither Game nor IServiceProvider) and BasicDrawableGameComponent (requires an IServiceProvider instead of a Game). The only note is that the Initialize method in BasicDrawableGameComponent uses an extension method I wrote for IServiceProvider to get a service out using generics; just replace that with the normal GetService method and you'll be fine.


    How did you know that you had to implement the IGameComponent, IUpdateable and in particular IDisposable interfaces.

    Also, if this is the case, will I be able to do things like Keyboard.GetState() from this kind of custom-crafted game component? Does it not require a dependency on the Game object?
  • 5/4/2009 9:21 PM In reply to

    Re: Mocking XNA Game object

    Stephen Styrchak:
    Shawn Hargreaves:
    Successful unit testing is all about minimizing dependencies. If your car object requires a mock Game instance in order to run its unit tests, that strikes me as an overly-close coupling. Why does the car class require a Game at all? Break that dependency, and your problem goes away.

    To be fair, our GameComponent class has this dependency, and we encourage people to use it. If the car class derives from GameComponent, then the developer was coerced into the overly-close coupling by the XNA Framework!

    While developers can go ahead and implement their own IGameComponent and IUpdateable in a class that doesn't depend on Game, that's a bit of a pain and it's a shame we didn't do it for them in the first place. For that matter, why doesn't IGameComponent.Initialize take an IServiceProvider parameter instead of forcing the class implementing the interface to have an implementation-specific method of connecting to its hosting environment?

    Considering the public methods on Game, what is the chance of a noticeable performance penalty in providing an abstraction of it to game components? The public members of Game don't get called that many times per frame. In the case of the properties, which are mainly there for convenience, the values can easily be cached locally to resolve any issues that might come up.

    For GraphicsDevice, on the other hand, I completely agree with you. :)


    *pretends he understands and nods in agreement :-)*
  • 5/4/2009 9:28 PM In reply to

    Re: Mocking XNA Game object

    Andriyko:
    How did you know that you had to implement the IGameComponent, IUpdateable and in particular IDisposable interfaces.
    IGameComponent is required to be added to the Components collection and IUpdateable is required for it to have an Update method be automatically called by the game. IDisposable is there because it's on the standard GameComponent/DrawableGameComponent so I wanted to mimic the functionality.

    Also, if this is the case, will I be able to do things like Keyboard.GetState() from this kind of custom-crafted game component? Does it not require a dependency on the Game object?
    No, there is no dependency on the Game class for the Keyboard class to work.
  • 5/4/2009 9:43 PM In reply to

    Re: Mocking XNA Game object

    Nick Gravelyn:
    Andriyko:
    Also, if this is the case, will I be able to do things like Keyboard.GetState() from this kind of custom-crafted game component? Does it not require a dependency on the Game object?
    No, there is no dependency on the Game class for the Keyboard class to work.


    But this is another dependency that might be worth breaking...

    If your Car class directly calls Keyboard.GetState(), then you will not be able to write automated unit tests for any of its functionality that depends on that keyboard input (you'd have to sit at the computer while the test is running to press the right keys at just the right times).

    But if you wrote your Car.Update method to take a KeyboardState as a parameter, and have your main game do the GetState part before it passes this input when it calls car.Update, then you can easily write unit tests that construct their own KeyboardState with whatever value you need for that test, never touching the actual keyboard, as your unit test has total control to pass any fake input data it likes into car.Update.
  • 5/5/2009 10:09 AM In reply to

    Re: Mocking XNA Game object

    For classes that are going to require unit testing, I generally use a subroutine for all the real work.

    I'll try and explain...

    class Tom derives from *** and overrides ***.Update and ***.Draw

    in Tom I use the functions that overide Update and Draw to set up the input variables for a subroutine that actually does the work

    I then create a public method Tom.DebugUpdate and Tom.DebugDraw which set up all the input variables and call the same subroutine.

    You can then call the debug versions should you need to instead of the real versions.

    This works particularly well when debugging shaders that render to textures, I cannot get pixwin to debug shader code while rendering to a texture, it just crashes on my machine, so the debug versions just draw to the screen and I can then debug them at my leisure.

    It's a pretty simple solution, and quite crude, but it does work.


  • 5/5/2009 11:43 AM In reply to

    Re: Mocking XNA Game object

    You could actually instantiate a real Game object for every test couldn't you? It would be horribly slow but it would work? If that is the case would it be possible to cache that Game object and reuse it for each test in the run, 'reseting' it between tests? I haven't done any GameComponent unit testing so I'm just guessing here..
  • 5/5/2009 2:02 PM In reply to

    Re: Mocking XNA Game object

    Craig Martin:
    You could actually instantiate a real Game object for every test couldn't you? It would be horribly slow but it would work? If that is the case would it be possible to cache that Game object and reuse it for each test in the run, 'reseting' it between tests? I haven't done any GameComponent unit testing so I'm just guessing here..

    Oh, but WHY do I need that painstaking way of doing this?

    Stainless:
    For classes that are going to require unit testing, I generally use a subroutine for all the real work.

    I'll try and explain...

    class Tom derives from *** and overrides ***.Update and ***.Draw

    in Tom I use the functions that overide Update and Draw to set up the input variables for a subroutine that actually does the work

    I then create a public method Tom.DebugUpdate and Tom.DebugDraw which set up all the input variables and call the same subroutine.

    You can then call the debug versions should you need to instead of the real versions.

    This works particularly well when debugging shaders that render to textures, I cannot get pixwin to debug shader code while rendering to a texture, it just crashes on my machine, so the debug versions just draw to the screen and I can then debug them at my leisure.

    It's a pretty simple solution, and quite crude, but it does work.

    If I understand you correctly, then all the code that you want to be able to test has a few "special" functions (DebugDraw, DebugUpdate etc...), that setup the testing state for that code?

    Does it not defeat the purpose of testing, in that you should really be testing the functions actually in use by your game and not the ones that are not?
    DebugUpdate may work fine with your custom setup code, but when used on it's own it might fail when passed a null value of some kind, for example. Also when you refactor your code how can you be sure that your custom setup functions reflect the refactored code correctly, and not the "old" code?

    I need a way to test my code without any modifications to it. Also I don't want to add a lot of methods that are really only good for testing, since that puts additional requirements on my design which have nothing to do with the game itself.

    Similarly when people suggest making an IGame interface, I don't see the reason why I need to "hack" my code just to accommodate testing.
    I want to test Game Components and not Components with my custom IGame interface.

    I would like to decouple my game components, but when I do, I just end up rewriting the Update, Draw, Initialize and LoadContent methods, in order to make them not accept the Game parameter. Essentially I am recreating the interface that game components implement.
    So now I have 2 interfaces that do the same thing. Is it just me or is there some complexity issues here (especially in the case of framework updates for example).

    I am but a newbie programmer, so any clarification would be appreciated.
  • 5/5/2009 2:09 PM In reply to

    Re: Mocking XNA Game object

    Shawn Hargreaves:
    Nick Gravelyn:
    Andriyko:
    Also, if this is the case, will I be able to do things like Keyboard.GetState() from this kind of custom-crafted game component? Does it not require a dependency on the Game object?
    No, there is no dependency on the Game class for the Keyboard class to work.


    But this is another dependency that might be worth breaking...

    If your Car class directly calls Keyboard.GetState(), then you will not be able to write automated unit tests for any of its functionality that depends on that keyboard input (you'd have to sit at the computer while the test is running to press the right keys at just the right times).

    But if you wrote your Car.Update method to take a KeyboardState as a parameter, and have your main game do the GetState part before it passes this input when it calls car.Update, then you can easily write unit tests that construct their own KeyboardState with whatever value you need for that test, never touching the actual keyboard, as your unit test has total control to pass any fake input data it likes into car.Update.


    That's a good idea. I should have thought about it myself :-)
  • 5/5/2009 5:12 PM In reply to

    Re: Mocking XNA Game object

    Shawn Hargreaves:
    ... when it comes to testing your graphics, you really need to draw some stuff and then check that it drew the right image for the test to be valid. For that, you need to create an actual GraphicsDevice, rather than just mocking all the graphics API to noop.

    Shameless plug :-P I have a project out on codeplex that aims to help in this specific situation: http://scurvytest.codeplex.com/
  • 5/6/2009 5:17 PM In reply to

    Re: Mocking XNA Game object

    Andriyko:
    If I understand you correctly, then all the code that you want to be able to test has a few "special" functions (DebugDraw, DebugUpdate etc...), that setup the testing state for that code?

    Does it not defeat the purpose of testing, in that you should really be testing the functions actually in use by your game and not the ones that are not?


    No, all you are changing is the input parameters, the keyboard state, the joypad state, everything else is the same.

    You HAVE to do this if you want repeatability.

    My last community game had a feature that the game recorded all the user inputs for a game level.

    If you scored more than the stored value on that level, the demo mode was replaced by your game. I just recorded the user input.

    But what a great debugging tool it was.
  • 5/6/2009 5:45 PM In reply to

    Re: Mocking XNA Game object

    Stainless:

    ...
    If you scored more than the stored value on that level, the demo mode was replaced by your game. I just recorded the user input.

    But what a great debugging tool it was.


    I don't really follow you there :-(
  • 5/6/2009 6:03 PM In reply to

    Re: Mocking XNA Game object

    Every frame I recorded the state of the gamepad, so it was easy to reproduce a bug.
  • 9/14/2009 2:01 AM In reply to

    Re: Mocking XNA Game object

    Sorry for the bump, but I was wandering if there was any talk of providing an IGame interface?

    I've recently decided to re-factor my XNA code, and I have a Game dependancy nightmare... everything needs the Game instance.
  • 9/14/2009 3:50 AM In reply to

    Re: Mocking XNA Game object

    Andriyko:
    Sorry for the bump, but I was wandering if there was any talk of providing an IGame interface?

    I've recently decided to re-factor my XNA code, and I have a Game dependancy nightmare... everything needs the Game instance.


    Create your own IGame interface and have your Game subclass implement it.
  • 9/14/2009 3:57 AM In reply to

    Re: Mocking XNA Game object

    Stephen Styrchak:
    Shawn Hargreaves:
    Successful unit testing is all about minimizing dependencies. If your car object requires a mock Game instance in order to run its unit tests, that strikes me as an overly-close coupling. Why does the car class require a Game at all? Break that dependency, and your problem goes away.

    To be fair, our GameComponent class has this dependency, and we encourage people to use it. If the car class derives from GameComponent, then the developer was coerced into the overly-close coupling by the XNA Framework!

    While developers can go ahead and implement their own IGameComponent and IUpdateable in a class that doesn't depend on Game, that's a bit of a pain and it's a shame we didn't do it for them in the first place. For that matter, why doesn't IGameComponent.Initialize take an IServiceProvider parameter instead of forcing the class implementing the interface to have an implementation-specific method of connecting to its hosting environment?


    Huzzah! Stephen, why didn't they get you to design the framework ;)

    The best solution is to write your own base classes and interfaces to avoid Game dependecies at all costs - use IServiceProvider instead. This also gives you a nice framework for putting your game framework into WinForms for editors etc.
  • 9/14/2009 11:23 AM In reply to

    Re: Mocking XNA Game object

    I am not sure how I can write the "Car" class without the XNA dependencies.

    I mean i need Update, and Draw methods, don't I? No matter how I write it.
    But that means I either have to reuse XNA GameComponenet or create my own...erm.. GameComponent?

    If I create my own I have 2 kinds of GameComponenets in my game + I have to create ComponentManager that essentially does what XNA Comp.Manager does...
    With such luck - why use XNA-GameComponenets at all?

  • 9/14/2009 11:43 AM In reply to

    Re: Mocking XNA Game object

    Andriyko:

    I mean i need Update, and Draw methods, don't I? No matter how I write it.


    Yes.

    Andriyko:
    why use XNA-GameComponenets at all?


    Exactly... Dont. See Nick's post above - it's really quite easy to roll your own. I agree it's a hassle to write your own "GameComponentCollection", but Reflector should help if there's functionality you need but aren't sure how to implement. You get the added bonus that you can customize 'til your heart's content.
Page 1 of 2 (28 posts) 1 2 Next > Previous Discussion Next Discussion