Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm writing unit tests for a steering system for a video game. The system has several behaviours (avoid this area because of reason A, avoid this area because of reason B, each adding a bit of context to a map of the region. A separate function then parses the map and produces a desired movement.

I'm having trouble deciding how to write the unit tests for the behaviours. As TDD suggests, I'm interested only in how the behaviours affect the desired movement. For instance, avoid-because-of-reason-A should result in a movement away from the suggest bad position. I don't care actually how or why the behaviour adds context to the map, only that the desired movement is away from the position.

So my tests for each behaviour set up the behaviour, make it write to the map, then executes the map-parsing function to work out the desired movement. If that movement satisfies my specifications then I'm happy.

However now my tests depend on both the behaviours working correctly, and the map parsing function working correctly. If the parsing function fails, then I would get hundreds of failed tests rather than a couple. Many test-writing guides suggest this is a bad idea.

However if I test directly against the output of the behaviours by mocking out the map, then surely I'm coupling too tightly to the implementation? If I can get the same desired movement from the map by using a slightly different behaviour, then the tests should still pass.

So now I'm suffering cognitive dissonance. What's the best way to structure these tests?

share|improve this question
    
...not sure there's a magic answer. Basically you test things that can break. So ideally you'd somehow magically be able to tell which low level tests were already going to be covered sufficiently by high level tests that they didn't need their own lower-level unit tests. Another way to look at it is: from the time a test fails to the time a developer fixes the problem, how much time will elapse? You want this time to be low. If you did no units, but only perfect functional tests (full high-level coverage), that time would still be too high. Try to use that as a heuristic guide. –  Joe Rounceville Oct 13 at 18:59

3 Answers 3

up vote 10 down vote accepted

In the ideal world, you would indeed have a set of perfectly orthogonal unit tests, all on the same level of abstraction.

In the real world, you usually have tests on many different levels of the app, so often the higher level tests exercise functionality which has already been tested by dedicated lower level tests too. (Many people prefer calling such higher level tests subsystem/integration tests rather than unit tests; nevertheless they can still run on the same unit testing framework, so from the technical point of view there is not much difference.)

I don't think this is a bad thing. The point is to have your code tested the best way which fits your project and your situation, not to adhere to "the ideal way".

share|improve this answer
    
I guess the main point of the author was whether you should use stubs/mocks or real implementations for these higher-level tests –  Idsa Sep 9 '11 at 7:10

This kind of testing is why mocks were invented. The main idea: You write a mock for your object (map, behavior, character, ...), then write tests using that mock instead of the actual object. People sometimes call mocks stubs, and I believe there are other words for both.

In your case, you would write a mock for the map whenever you need to test the behaviors, and other mocks for behaviors whenever you want to test the map. Your mocks would ideally be much simpler than the actual behaviors you are mocking, only incorporating methods or variables you actually need for that test. You may have to write a different mock for each and every test, or you may be able to reuse some mocks. Regardless, they should be suited for the test, and shouldn't try to be as much like the actual behavior as possible.

If you included some examples of maps or behaviors, perhaps someone could provide examples of the mocks you could write. Not me, as I have never programmed a more advanced video game than Pong, and even then I was following a book, but perhaps someone well-versed in both unit testing and game development.

share|improve this answer

I think you try to test stuff that is much higher level than a unit.

Most behavioral tests would require some intelligence behind it, to tell if it behaved correctly. This can't be easily done using automated testing.

share|improve this answer
    
this is why I mentioned concision. I can very easily write small unit tests to test individual lines of code within a behaviour, and have done, but it depends on reading the output of the map parsing function. None of my behaviour tests are large, each of them tests only one piece of functionality of the behaviour. –  tenpn Aug 10 '11 at 11:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.