Wednesday, September 14, 2011

Recently I've written about the possibility to test the features by writing code, that test them. As I've started doing some refactoring in our code, I immediately wanted to use that feature. Let's see how it worked out...

Gathering, once again

As we already mentioned, we are changing (again) the way resources will be gathered. This of course required yet-another-refactor of that part of code. Last time I was doing this, it was rather boring task: refactor script of one facility, start server, login, spawn some of those facilities, spawn myself needed item, use it, check. Rinse and repeat (sometimes you may hot-reload the script, but you need to still test it manually).

This time I decided to write set of test cases for every 'use event' that results in resource being acquired. And then, those tests will check the stuff for me, so that I do not even need to fire up the client. Nifty!

This is an excerpt from a class that represents plant facility that we may cut with knife to use the needed resources. It's represented in-game as an item, and we are initializing it in item script in following way:

Testing stuff

First thing we would probably like to test is, whether critter really receives the items if using proper tool on that facility.Let's first prepare a helper that's gonna greatly reduce the amount of repeated code:

The most important part is the mock for Critter::AddItem, which just stores the expectation named in following manner: CritterAddItem_PID_COUNT. In above test function, we're preparing a context consisting of:

critter

knife

item representing the plant

We invoke the event that would be normally invoked when player or npc would use a knife on the plant (EventUseOnMe). The call process normal behavior, but when it encounters call to Critter:AddItem it calls our mock instead. So we expect that our function is gonna call this function with PID_FIBER and 2 as parameters. Looking into the code of Plant::UseItem, we see that indeed it should work. Plant::batch is equal to 2, so it's gonna execute exactly what we wanted. Running the test confirms that. Yay!

Code is already bugged

Oh great:( I'm writing some code snippets that already contain bugs. So what? Let's fix them, but first let's write a test that confirms them, check if it fails, and then fix the bug and re-check the test:

Since there are gonna be no timeouts on characters, the facilities itself should somehow limit the amount of resources that we can obtain (and they will be regenerated over time). We've already had implemented some Amount property in our Plant class, but the code didn't care about it. And this test proves that - we expect that AddItem is not gonna be called with PID_FIBER (and whatever count) at all, but it is, because we do not check for amount left in UseItem method. Let's fix it:

And let's run the test again. It succeeds! We've fixed a bug, we tested it. Without doing manual labor.

The method I'm describing here, really makes me happy developer, as I do not need to spend time on manual testing, and also I am preparing more and more tests that's gonna test whether existing features are still working in the future (you know, some change in other area of code can really break the other part of code, in an unexpected way, better catch at least some of such bugs).

There is still one bug left in the code (probably much more, I wrote this post without compiler). I'm leaving it for readers to find out and write test code that proves it!

Donate!

We are working in our free time on FOnline, we don't get paid and FOnline will never become pay-to-play. But running the server costs money. So, if you like the game and would like to support us, we would be very happy if you could donate some money to keep the server running.

Amount:

Currency in:

Powered by Online Quest.

About

"FOnline: 2238" is a Fallout game based on the FOnline engine. Currently, it is only available in English.

The game is set in 2238, 3 years before Fallout 2. The world has been expanded and includes both the Fallout and Fallout 2 game areas.