使用Catch框架测试C++模板类
Test C++ template class using Catch framework
我正在寻找一种使用Catch测试模板化类的好方法。我有一个几乎有效的东西:
#define RUN_ALL(fn, params)
fn<uint8_t, bool>(params);
fn<uint8_t, char>(params);
fn<uint16_t, bool>(params);
fn<uint16_t, char>(params);
fn<uint32_t, bool>(params);
fn<uint32_t, char>(params);
fn<uint64_t, bool>(params);
fn<uint64_t, char>(params);
template<typename A, typename B>
void test_number_one() {
REQUIRE(...)
}
TEST_CASE("Foo::Foo() works nicely", "[SmallGraph]") {
RUN_ALL(test_number_one)
}
此设置将只运行到第一次失败,这很好,因为很可能所有8种情况都会以相同的方式失败。但是,最好知道在发生故障时使用的是哪一组模板参数。我的想法是这样做:
#define RUN_ALL_P(fn, params)
INFO("Testing <uint8_t, bool>");
fn<uint8_t, bool>(params);
INFO("Testing <uint8_t, char>");
fn<uint8_t, char>(params);
INFO("Testing <uint16_t, bool>");
fn<uint16_t, bool>(params);
...
但是,我不能在RUN_ALL中使用多个INFO,因为这样做会生成具有重复标识符的代码。
FOO.cpp:270:3: error: redefinition of 'scopedMessage270'
RUN_ALL(test_number_one);
(RUN_ALL(test_number_one)
出现在第270行。)
对于不需要所有测试函数都具有相同签名的变通方法,有什么想法吗?
(我也欢迎使用CATCH测试模板代码的文章,以及如何在不得到一堆关于一般异常处理(即try/CATCH)的结果的情况下搜索此类文章的建议。)
宏的问题在于,当它被展开时,它被展开为一行。虽然我不知道你的测试框架在使用中,但很明显,这个宏做了一些类似的事情:
struct M { M(char* msg) { puts(msg); } }; // just an example class...
#define INFO(m) M scopedMessage##__line__(msg)
因此,如果您在第270行使用宏RUN_ALL…,您将获得多个scopedMessage270实例
您可以通过用模板替换宏来解决这个问题。不幸的是,您不能将其与模板函数一起使用,因此您也必须将测试用例作为模板类:
template <template <typename T, typename TT > class Test >
struct All
{
template <typename ... Parameters>
static void run(Parameters ... parameters)
{
Test<uint8_t, bool>::run(parameters ...);
Test<uint8_t, char>::run(parameters ...);
Test<uint16_t, bool>::run(parameters ...);
Test<uint16_t, char>::run(parameters ...);
Test<uint32_t, bool>::run(parameters ...);
Test<uint32_t, char>::run(parameters ...);
Test<uint64_t, bool>::run(parameters ...);
Test<uint64_t, char>::run(parameters ...);
}
};
template<typename A, typename B>
struct test_number_one
{
static void run()
{
// log test name
// run the test
}
};
template<typename A, typename B>
struct test_number_two
{
static void run(int n)
{
// log test name and parameter value
// run the test
}
};
int main(int argc, char* argv[])
{
All<test_number_one>::run();
All<test_number_two>::run(12);
All<test_number_two>::run(10);
}
现在,在模板中,所有代码行都保留在单独的行上,您可以随心所欲地在任何日志记录之间放置:
template <typename ... Parameters>
static void run(Parameters ... parameters)
{
INFO("uint8_t, bool");
Test<uint8_t, bool>::run(parameters ...);
INFO("uint8_t, char");
Test<uint8_t, char>::run(parameters ...);
// ...
@Aconcagua是绝对正确的。我的解决方案是类似的,但使用了函子(正如@R Sahu所建议的——C++所有模板实例的单个函数指针)
template<template<typename, typename> class TestFunctor, typename... Parameters>
void testAllTypes(Parameters... parameters) {
INFO("Testing <uint8_t, bool>");
TestFunctor<uint8_t, bool>()(parameters...);
INFO("Testing <uint8_t, char>");
TestFunctor<uint8_t, char>()(parameters...);
// ...
}
template<typename A, typename B>
struct testDefaultConstructor {
void operator()() {
mallGraph<A, B> sg;
REQUIRE(sg.numVertices() == 0);
REQUIRE_FALSE(sg.edgecountIsValid());
REQUIRE_FALSE(sg.adjacencyMatrixIsValid());
}
};
TEST_CASE("SmallGraph::SmallGraph() initializes instance data as expected", "[SmallGraph]") {
testAllTypes<testDefaultConstructor>();
}
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 尽管测试成功,CppUnit测试核心仍被丢弃.为什么
- 数据成员SFINAE的C++17测试:gcc vs clang
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么二进制搜索在我的测试中不起作用
- 从父数组测试用例构造二叉树失败
- 试图对缓存进行跨步测试,但程序并没有结束
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- OpenGL在启用深度测试时不会丢弃我的碎片
- 为测试目标创建具有不同源文件夹的文件
- 在子目录中使用target_sources()命令时用于单元测试(qtest)的项目结构
- VC++本机单元测试,找不到调试符号
- 换位表导致测试失败(但在游戏中运行良好)
- 用于交叉编译和CMake的预处理器宏的单元测试
- 谷歌测试中的期望值存储在哪里
- 如何在for循环中包含两个索引值的测试条件
- 在cygwin中测试新的boost安装时出现cpp错误
- 使用rdtsc进行基准测试的缺点是什么
- 更正 CMakeList.txt 用于谷歌测试的文件?