As our project’s code has grown, and the use cases have become more complex and hard to remember, I have shut out the practice of writing tests as a method to ensure the quality of my code.

Our application runs as a plugin within many different host applications, and so our deployment environment is next to impossible to predict. As such, we are spending most of our time just writing the new code, compiling the entire plugin (500+ source files), and debugging it straight up to get everything to work. basically, we don’t have time for tests.

I know a bunch of you will say “but the time gained by forgetting tests is lost in maintaining the bugs you will create.” Well, there is actually a window created by excessive feature requests and tight time constraints where you just don’t have the time to deal with tests. You get it working, you submit the code, you deal with it later.

But, after hiring a new developer to help handle my load, I have started to have a little more time here and there and I have started to inkle out a few tests here and there. Writing test is a skill that can become second nature with practice. Not only does it help verify your code, but it gives you a chance to massage it’s flexibility by looking at it from a new perspective.

We don’t use a sophisticated testing framework or anything, but one technique that I find very helpful is to slap the tests for a class into a static class right a the bottom of the .cpp file, and put the test code right in the constructor. That way your code is run before your app code (during your runtime’s static initialization phase) muddies up static data.

Here is an example:

class test_UValArgs
{
public:

void test(const UValArgs &args, const char *formats[])
{
for(int i=0; formats[i] != 0; ++i)
{
const char *fmt = formats[i];
try
{
args.checkTypes(fmt);
}
catch(ArgumentError &e)
{
printf("test_UValArgs: FAILED "%s": %sn", fmt, e.what());
}
}
}

test_UValArgs()
{
// UVal e;
// e.exc_setException("ArgumentException", "hey you guys");
// printf("%sn", e.toCString());


UValArgs a0; a0 << (int) 1 << (int) 2;
const char *f0[] = { "ii|i", 0};
test(a0, f0);

UValArgs a0; a0 << (int) 1 << (float) 2 << (double) 3;
const char *f0[] = { "ifd", "if|d", "if", "i", 0 };
// test(a0, f0);

UValArgs a1; a1 << "hey" << (int) 3;
const char *f1[] = { "s", "i", "si|f", 0 };
// test(a1, f1);

UValArgs a2; a2 << "hey" << "you";
const char *f2[] = { "s|s", 0 };
test(a2, f2);
}
};

static test_UValArgs _test_UValArgs;

When you are done with the test you can just use a ‘#if 0 .. #endif’ or a comment block to exclude it from your code.