Reputation: 41840
I was wondering if something as unit testing template was a thing. Let me explain my needs.
I have a highly templated library. I have a lot of sfinae type traits, and some static_assert.
What I want to test is the validity of sfinae type traits, and test if my static_assert are throwing the right thing. Knowing what is my coverage would be awesome.
Here's an example of what my code look like:
template<typename T>
using false_v = !std::is_same<T, T>::value;
// Here are my types traits
template<typename T, typename... Args>
struct SomeCondition1 { /* ... */ };
template<typename T, typename... Args>
struct SomeCondition2 { /* ... */ };
// This is a master type trait, that test every others
template<typename T, typename... Args>
using Conditions = std::integral_constant<bool,
SomeCondition1<T, Args...>::value && SomeCondition2<T, Args...>::value
>;
// This is the function that is call when everything is okay.
template<typename T, typename... Args,
std::enable_if_t<Conditions<T, Args...>::value, int> = 0>
void doThing(Args...) {}
// These function are called only to trigger
// static asserts to give the user a diagnostic to explain what's wrong.
template<typename T, typename... Args,
std::enable_if_t<SomeCondition1<T, Args...>::value && !SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, SomeCondition2 not met");
}
template<typename T, typename... Args,
std::enable_if_t<!SomeCondition1<T, Args...>::value && SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, SomeCondition1 not met");
}
template<typename T, typename... Args,
std::enable_if_t<!SomeCondition1<T, Args...>::value && !SomeCondition2<T, Args...>::value, int> = 0>
void doThing(Args...) {
static_assert(false_v<T>, "Error, both conditions not met");
}
I was thinking about testing if the traits were ok, and if the right static assert is thrown for my cases. If the wrong static assert is triggered, that's a bug, and I would like to be able to test it. Trying to cover all cases for all compilers and check every message by hand is really time consuming and error prone.
Upvotes: 2
Views: 377
Reputation: 61610
The problem of unit-testing template code for ranges of argument types is
fairly well addressed by googletest
with its TYPED TESTS
feature
and Type-Parameterized Tests
feature.
A limitation of these features is that they are only immediately applicable to testing templates with just one parameter. But it's not difficult to work around this limitation: see this question and the accepted answer.
None of that helps, however, with the further problem of testing the correctness static_assert
s in
template code. The special obstacle for that kind of testing, of course, is that
a static_assert
fires by compilation failure; so if it fires, correctly or otherwise,
there is nothing you can execute to show that it does.
This bothered me too several years ago. I posted How to write runnable tests of static_assert? and also wrote the only answer so far received (lately updated for C++14 and current compilers).
Combining these resources and techniques should yield the solution you're looking for.
Upvotes: 5