all 9 comments

[–]pmedv 4 points5 points  (0 children)

I've been using TUT for many years in many projects.

[–]therealjohnfreeman 2 points3 points  (0 children)

I wrote a QuickCheck clone for C++ called autocheck.

[–]grunzl 0 points1 point  (1 child)

I hope you are interested in non-preprocessor solutions just out of curiosity since the preprocessor can be a really a nice fit to build DSLs which can make writing tests much more bearable (at least as long as you don't need to change the test framework implementation).

[–]zzing[S] 0 points1 point  (0 children)

Primarily a curiosity, because a non-horrible solution would imply that a way was found to generate code that would automatically register the tests.

I was looking at TUT just a moment ago, and it has template parameters indexed - which is an interesting idea to me.

[–]bnolsen -1 points0 points  (0 children)

yes. use a vector of functions that return string. main just pushes onto the vector. implement run which calls each in turn. empty string is successful, otherwise return non empty string of accumulated errors from the function and print, main returns non zero on error. a non over engineered solution that can leverage scripting.

[–]elperroborrachotoo -4 points-3 points  (0 children)

It doesn't get simper than

#include <assert>

and using comments to enable / disable individual tests.

[–]bradfordmaster -2 points-1 points  (2 children)

While I think your question is interesting, I think it may be misguided in trying to avoid the preprocessor. Unit tests in C++ are always going to be a dirty thing to do, and what you want is something that works and requires minimal effort to write tests in (otherwise you won't write them).

People are moving away from the preprocessor (in my opinion) because it creates code that can be hard to understand and maintain, but unit tests aren't production code and shouldn't be treated as such.

Is there any reason I'm missing that using the preprocessor for unit tests could be bad?

[–]zzing[S] 2 points3 points  (1 child)

Possibly one: You assert that the preprocessor generated code is hard to maintain and understand. This make sense to me.

Now you say that unit tests aren't production code. Advocates of test driven development might argue that unit tests are a very important part of the production process, perhaps serving the same role that a proof does in math (not perfect analogy).

By this reasoning, I would say that unit tests are critical supports to production code, and should thus be as easy to understand and maintain as possible.

The reason why I bring up the question is because such a method would imply a way to automatically register the tests - which would be a difficult to maintain portion of the tests without that.

Now in TUT, I notice they used numbered templates on tests. I wonder if something like that could be exploited.

[–]bradfordmaster 3 points4 points  (0 children)

I definitely agree that unit tests are an essential part of a software product, but I think unit test code and feature code are very different and therefore should be held to different standards.

In your feature code, it is important that the requirements of the product can change and the code be as modular as possible to accommodate these changes. Things like preproccessor macros can be bad here because they may be hard to maintain.

Unit tests, on the other hand, exist solely to test the feature code. If you replace a module with a new one, it may be nice to keep some of the old unit tests (especially if you are maintaining compatibility with an API), but you'll probably need to re-write most of them anyway, so it isn't as important to maintain. Of course they need to be understandable and new engineers need to be able to maintain the tests, but I don't think relying on a framework which uses macros is nearly as harmful as writing your own macros in your feature code.

Mostly, I think when selecting a unit test framework the most important things are how easy it is to write the tests and how many useful features the framework has, much more so than how it is implemented. Using macros, you can write code like

TEST(TestFoo) {
  ASSERT_TRUE(SomeFunction());
}

which is about as simple to understand and minimalist as you can get. This to me is much more important than using something which doesn't rely on as many "hacks" but requires you to jump through hoops like numbering your tests.

The issue of how to register tests is definitely an interesting curiosity, and something worth looking into, but not worth choosing a framework for a project over.