Using TDD and MVP Design Pattern

I am in the very early stages of implementing a very simple game which i hope to develop using TDD (Test Driven Development), I am using Nunit for the TDD framework.

To test as much of the logic as possible I plan to use the MVP (Model View Presenter) design pattern to separate the testable logic from the graphics side. Its the MVP that I am a bit stuck on and how best to split my game objects.

At the moment I’m thinking I might have a ViewEngine which is pretty much the entry point on my game and instantiates all the other Views, which in turn instantiates their presenters and so on. Each game object (player, tiles, power ups, etc) will have their own view, presenter and model. I believe in good MVP the presenter should really be the main driving force of the game/application. Therefore I assume the presenters should be called using the ‘Update’ loop and the views should be called using the ‘Draw’ event. But I’m still unsure how to structure this.

Has anyone else done this or able to share some thoughts/ideas on what would be a good way to do this?

I’m fairly certain MVP won’t work in game design. It works well in things like web servers and UI clients as the M/V/P bits are fairly obvious, but this does not extend to games.

Hey :slight_smile:

I don’t follow a strict TDD approach myself, simply because I find that it really gets in the way of my problem solving ability. Instead, when I’m writing new classes, I tend to just blast them out and then revisit them with a unit test pass. Then, for classes that exist and I generally know what I’m doing, I follow TDD. I think TDD is great, I just find that I need to prototype/iterate to figure something out and I haven’t really figured out how to do that with TDD yet.

With that out of the way, I’m just about to release my first game, which is fully unit tested. I tried following a fairly relaxed MVC approach. I did some googling and MVP is pretty similar, so you shouldn’t have too much trouble. I used MSTEST and NSubstitute for my unit testing and mocking.

The way I structured things was to have my objects implement an entity interface, which had Update and Draw. The entities generally handled their own Draw calls but the actual logic of the entities I’d offload to a controller that I would just inject via the constructor, then update during the entity’s Update method. This separation worked really well because I could just write the tests for each piece independently and it all worked out really well.

It’s worth noting that I also wrote tests for all my views. It took me very little effort overall to create, simply making interfaces for the functionality I wanted, then implementing those interfaces as wrappers for the existing MonoGame classes. I posted a topic about this seeing if anybody was interested in this approach. Nobody was :stuck_out_tongue: You can find it here though:

The last thing I’ll say is, regarding the struggle you mentioned, I really wouldn’t worry about finding the perfect solution to MVP. As long as you’re following that general practice, each of your components will be testable and you can achieve your general goal. You can always refactor later and, if you’re sticking to SOLID practices, that should be relatively easy to achieve. Additionally, since you will have written a bunch of unit tests already, that refactor will be extra smooth since you’ll know if you broke something as you go along.

Anyway, to sum this all up, you should definitely be able to achieve your goals here. Just know that not a lot of people actually seem to do this, and that you don’t really need to get hung up on the perfect approach. Your code will evolve and that’s ok. From experience, trying to do everything perfectly the first go around is a great way to get yourself blocked :slight_smile:

Good luck!

Just my two cents — I think a lot of people use Entity Component Systems for game design here, which could arguably be similar to MVC. The components are your models, while update systems are your controllers and draw systems are your views/presenters. They’re not exactly the same, but it does help split the responsibility of data and operations in a similar way.

@Trinith many thanks for your input… it’s very encouraging to see that someone else is doing this and seeing the benefit. I followed most of what you said but still a little unclear on your separation between the view object and controller, how are these related? I don’t suppose you could put together a simple example of a single object (player for example) which draws a graphic on screen but also has some logic, like maybe reacting to a single key press? I just want to see how you do your separation.
I was having the same idea of creating interface wrappers for all the mono game calls I use… shame mono game wasn’t developed with this in mind.
Sorry for the long post but how are you doing your game object instantiation to maintain loose coupling? I have been looking at depandancy injection containers but don’t yet know enough about them to know if this is overkill.

@jnoyola thanks also for your input, I didn’t know about Ecs and from this have seen that this sort of pattern is covered by NEZ and Monogame.extention. So I will check those out too.

@Trinith however you are correct I shouldn’t get bogged down in getting a ‘perfect system’, but as I am quite new to monogame I want to know the options are before I go too far in one direction.

Thanks again.

You kinda caught me at a bad time. I’m trying to release my game and, let’s be real, WoW just dropped a new expansion :stuck_out_tongue: I think an example would be a good idea though, and I could probably roll this into some kind of tutorial video. I’ve got some ideas of how I might want to approach this, but maybe give me a bit to let some of the dust settle. I’ll see what I can do.

Unfortunately, unit testing isn’t something that seems to have penetrated very far into the game development world. At least, this seems to be the case from the research I’ve done. I kind of get it, it really does add a lot of additional effort to your development. I usually budget for at least 3 times what I think it’s going to take me to do without following testing practices. Personally, I find the benefits worth it… not only do you have high confidence in the code you write, the very act of trying to test your code just forces you into better coding practices. I accept that it’s not for everyone though, and given that, it doesn’t make a lot of sense for the MonoGame devs to spend time on it when they could focus on other things.

Fortunately, if you just focus on the functionality you need and wrap that, creating your own wrapper framework is fairly straight forward. When I get to the example, I’ll cover this as well :slight_smile:

Constructor injection is your best bet. Not only is there less of a performance cost (no dictionary lookup in your dependency container), but it’s also much easier to test as you can pass your mocks directly into the class without having to worry about staging your dependency container. Having said that, you’ll still probably want some kind of dependency container anyway, where you can put objects you find you’ll need but don’t want to pass along everywhere.

Honestly, there’s no real best way, just the way that makes sense to you. Just be mindful of dependency container use… the best place to use them is to resolve dependencies that you pass into a constructor. The next best place is in a constructor itself. The worst place is in your Update or Draw methods, as the lookup will get called over and over.

Anyway, at this point I think your best bet is to just dive in and play around. You’ll know something isn’t quite right when you go to test it and it’s hard. When you bump into that, it’s time to refactor. That’s the nice thing about writing testable code. If you’re finding it hard to test, you probably need to take a different approach :slight_smile:

Oh! One last note… there are definitely things you will not write tests for. For example, you don’t need to write tests for your wrapped MonoGame objects that implement your interfaces. You also don’t need to write tests for your MonoGame Game class. This is simply your entry point, direct it to some kind of IMainGame (or IViewEngine as you noted above) and then leave it alone. We generally trust that the API we are using works, but want to stage our code so we can test the interactions with it.

@Trinith thanks for all the input, much appreciated. Depending on how it goes I might update this post on what I find and add my own tips etc.

Id be interested in seeing you game once released so please keep me posted.

I agree with what others have already stated. I tried multiple approaches like you suggested and found ECS (Entity Component System) is the way to go. One component works with one system (generally) and keeps things decoupled really well. When you make changes to one system, you only have to test the new system, the others are not impacted. There are A LOT of opinions online about the correct way to do ECS. Read up on all the approaches and pick one you feel fits your style.

I’ll restate what @Trinith said, “your code will evolve”. That is the honest truth. That said, IMO if you spend too much time making unit tests, you’ll be recreating tests and more tests because the system will keep evolving (and wasting time). I’ve found using an agile style approach works well especially in the ECS design. Develop a system (no test cases), put it through its paces by using it, develop another system, use it and use the previous system, continue…

And honestly in the end… game testers. Your friends or even people online will probably love to test your game for free (even more so if you say their names will be in the credits). I’ve had so many people ask me if they could test my game and they want to payment.

I posted a release announcement here:

It’s paid only for now though. A free version is coming, but I want to work on some other things for a bit… I need a break :stuck_out_tongue:

One such thing? That example I was talking about. I’ve started fleshing it out and so it seems like it should come together. Like I said, I’ll probably make this some kind of video, but I’ll have to see how long it is. I’ll post a thread for this, but I’ll link it here as well so you can find it.

Hey!

Sorry for the delay here. I had an issue on release with my game and then… well, new WoW expansion :wink:

I’ve created an example, you can find it here::

You should be able to build and run this, as well as run the tests, but if you have trouble maybe build the main project first (without the test project), then build the whole solution. Also, note that the test project uses NuGet to get both MonoGame and NSubstitute, so you’ll need to have an internet connection on whatever computer you build with.

The sample contains two implementations of moving a ball around the screen, stopping it when space bar is held. The first, MainGame, just implements it directly and doesn’t make any considerations for MVC or testable code. The second, MainGame_Part2, uses an MVC implementation following SOLID principles (more or less) and provides tests for objects that don’t interact with MonoGame objects directly.

If there’s interest, I’ll create a second part of this example that wraps up the MonoGame objects and allows for all the code to be tested :slight_smile:

Finally, my original plan here was to use this example in a tutorial video that I was going to upload to my YouTube channel. After about an hour of recording, at which point I was only just finishing the GameEngine class and tests, I realized that this was going to be too much. I highly doubt you (or anyone) wants to watch three hours of tutorial on this. Instead, I’ll just provide the example code as-is. I did go through and write comments at the top of all the files to explain things and to point out various concepts. Hopefully you still find this useful. Much respect to those people who manage to make coding tutorial videos and keep them in the 10-20 minute range :wink:

Anyway, when going through the code, start at Program.cs. The comments should guide you through the rest. I hope it helps, and if you have any questions, feel free to post them here and I’ll try to help you out.

Good luck!

@Trinith Thanks for this… its being very useful and have started to use elements of this.

I see the reasons for the MVC separation (and is part of the reason I started this post) but i wonder in a game where you would probably have 10’s or 100’s or even more game entities, would having this separation slow the game down? For example for each game entity you split it into the different MVC objects. Obviously the view of each object will not do anything with the update, and the model and control will do nothing with the draw. So this is resulting in 3 times more game objects that are being created and called for functions that do nothing.

Is this a consideration?

Actually the moment I posted the above I guess you could just separate out the Draw and Update into separate interfaces to get around this.

Certainly :slight_smile:

This was a simplified example so I took the easiest approach. As you pointed out, you can definitely make specialized Controller and View interfaces and store them in different structures for processing. This would be more in line with the Interface Segregation Principle (which I think I commented on somewhere in there).

It’s also worth noting though that, depending on the complexity of your game’s logic, computers these days can handle a lot. I mean if you’re doing intensive physics calculations for each object, maybe you want to take some steps to mitigate how much processing you do… but for a lot of applications, it’s probably fine. Really though, what I’m getting at is that it’s generally not a good idea to get too hung up on performance until you find out that performance is actually going to be an issue. Otherwise you’ll spend a ton of time getting everything perfect to give you phenomenal performance that you probably didn’t need anyway.

If you design with SOLID in mind, refactors are generally less painful and you can implement changes as needed. Also, it’s a good idea to tackle the “low hanging fruit” first… make those easier refactors first, then, if needed, tackle the harder stuff.

I dunno, hopefully that makes sense :slight_smile: