Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write a unit test when the class to test is complicated?

I am trying to employ TDD in writing a backgammon game in C++ using VS 2010.

I have set up CxxTest to write the test cases.

The first class to test is

class Position
{
public:
...
...
bool IsSingleMoveValid(.....)
...
...
}

I 'd like to write a test for the function IsSingleMoveValid(), and I guess the test should prove that the function works correctly. Unfortunately there are so many cases to test and even if I test several cases, some might escape.

What do you suggest ? How does TDD handle these problems ?

like image 313
Wartin Avatar asked Dec 12 '22 02:12

Wartin


2 Answers

A few guidelines:

  1. Test regular cases. In your problem: test legal moves that you KNOW are valid. You can either take the easy way and have only a handful of test cases, or you can write a loop generating all possible legal moves that can occur in your application and test them all.
  2. Test boundary cases. This is not really applicable to your problem, but for testing simple numerical functions of the form f(x) where you know that x has to lie in a range [x_min, x_max), you would typically also test f(x_min-1), f(x_min), f(x_max-1), f(x_max). (It could be relevant for board games if you have an internal board representation with an overflow edge around it)
  3. Test known bugs. If you ever come across a legal move that is not recognized by your IsSingleMoveValid(), you add this as a testcase and then fix your code. It's useful to keep such test cases to guard against future regressions (some future code additions/modifications could re-introduce this bug, and the test will catch it).

The test coverage (percentage of code lines covered by tests) is a target that can be calculated by tools such as gcov You should do your own cost-benefit analysis how thorough you want to test your code. But for something as essential as legal move detection in a game program, I'd suggest you be vigilant here.

Others have already commented on breaking up the tests in smaller subtests. The nomenclature for that is that such isolated functions are tested with unit testing, whereas the collabaration between such functions in higher-level code is tested with integration testing.

like image 178
TemplateRex Avatar answered Jan 13 '23 15:01

TemplateRex


Generally, by breaking complex classes into multiple simpler classes, each doing a well-defined task that is easy to test.

like image 27
Oliver Charlesworth Avatar answered Jan 13 '23 15:01

Oliver Charlesworth