带模板的 CppUnitTestingFramework TEST_CLASSes
CppUnitTestingFramework with templated TEST_CLASSes
首先,这里有一个目标相似的问题:C++ unit test testing, using template test class。
这个问题是关于我试图解决同样的问题。
使用 Microsoft CppUnitTestFramework,我们可以使用如下内容创建单元测试:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace MyUnitTests {
TEST_CLASS(NameOfMyTestClass) {
public:
TEST_METHOD(MyMethod1) {
Assert::IsTrue(false);
}
};
}
我想测试一组类似的测试(不使用 For 循环将所有断言放在一个 TEST_METHOD
中),所以我查看了 TEST_CLASS
宏:
#define TEST_CLASS(className) \
ONLY_USED_AT_NAMESPACE_SCOPE class className : public ::Microsoft::VisualStudio::CppUnitTestFramework::TestClass<className>
这不能直接与模板一起使用 - 据我所知,没有办法指定一个 className
值,该值将包含具有正确编译语法的模板参数。
因此,我尝试了以下操作:
namespace MyUnitTests {
ONLY_USED_AT_NAMESPACE_SCOPE
template<MyEnumClass MeasurementType, char ExpectedShift>
class templatedScaleTestClass : public TestClass<templatedScaleTestClass<MeasurementType,ExpectedShift>>
{
public:
TEST_METHOD(Test_ExpectedShift) {
Assert::AreEqual(ExpectedShift, Calculations::getShiftAmount(MeasurementType));
}
};
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::FIRST,3>;
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::THIRD,1>;
}
这会编译,在我看来它应该允许我在模板 class 中定义 TEST_METHOD
的集合,然后实例化必要的枚举集合和常量值以设置他们起来(也许在未来对其他参数使用某种构造函数,虽然看着 CppUnitTest.h 让我想知道这是否可能是另一个问题......)
但是,class 从未出现在测试资源管理器中,尝试右键单击测试(在模板代码中)并单击 "Run Test(s)" 会产生以下输出:
[datetime Informational] Executing test method 'MyUnitTests.templatedScaleTestClass<MeasurementType, ExpectedShift>.Test_ExpectedShift'
[datetime Informational] No tests found to run.
编辑:不确定最后一部分 ("No tests found to run") 的相关性如何 - 对正常测试(无用户端模板)执行相同的操作会产生相同的输出。单击远离特定测试会运行 .cpp 文件中的所有测试。可能是我右键菜单用错了
尽管已多次尝试让它显示,并检查如下函数的输出:
template<typename T>
void debugMethod(TestClass<T> *tc) {
const TestClassInfo* classInfo = tc->__GetTestClassInfo();
std::stringstream msg;
msg << "Tag: " << classInfo->metadata->tag << std::endl;
msg << "helpMethodName: " << classInfo->metadata->helpMethodName << std::endl;
msg << "helpMethodDecoratedName: " << classInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "New method address: " << &(classInfo->pNewMethod) << std::endl;
const MemberMethodInfo* methodInfo = T::__GetTestMethodInfo_Debug();
msg << "methodInfo - Tag: " << methodInfo->metadata->tag << std::endl;
msg << "methodInfo - methodName: " << methodInfo->metadata->methodName << std::endl;
msg << "methodInfo - helpMethodName: " << methodInfo->metadata->helpMethodName << std::endl;
msg << "methodInfo - helpMethodDecoratedName: " << methodInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "methodInfo - lineNo: " << methodInfo->metadata->lineNo << std::endl;
Logger::WriteMessage(msg.str().c_str());
}
... (namespace, test class etc)
TEST_METHOD(Debug) { debugMethod(this); }
并在标准 TEST_CLASS 和我的模板 class 中观察到相似的结果,我无法获得模板 classes 以显示在测试资源管理器中。
可以模板化 class 然后从非模板化的 class 调用测试函数:
template <MyEnum val>
class myClass : public TestClass<myClass<val>>
{
public:
TEST_METHOD(MyTest) {
Assert::AreEqual(val, MyEnum::exampleValue);
}
}
TEST_CLASS(DummyTests) {
TEST_METHOD(Test_across) {
auto a = myClass<MyEnum::MyEnumValue>();
a.MyTest();
}
}
但这在测试资源管理器中提供的反馈仍然不够理想。
另一种选择(虽然丑陋...)是定义一个宏函数,该函数采用您要模板化的参数,然后在宏中定义整个 class:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#define SCALING_TEST(TYPE_TO_TEST, EXPECTED_SHIFT)\
TEST_CLASS(CATNAME(ScalingTest_, TYPE_TO_TEST)) {\
private:\
MyEnum type = MyEnum::TYPE_TO_TEST;\
public:\
TEST_METHOD(HasExpectedShift) {\
Assert::AreEqual((char)EXPECTED_SHIFT, Calculations::getShiftAmount(type));\
}\
}
namespace ScalingTests {
SCALING_TEST(SPEED, 3);
}
首先,这里有一个目标相似的问题:C++ unit test testing, using template test class。
这个问题是关于我试图解决同样的问题。
使用 Microsoft CppUnitTestFramework,我们可以使用如下内容创建单元测试:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace MyUnitTests {
TEST_CLASS(NameOfMyTestClass) {
public:
TEST_METHOD(MyMethod1) {
Assert::IsTrue(false);
}
};
}
我想测试一组类似的测试(不使用 For 循环将所有断言放在一个 TEST_METHOD
中),所以我查看了 TEST_CLASS
宏:
#define TEST_CLASS(className) \
ONLY_USED_AT_NAMESPACE_SCOPE class className : public ::Microsoft::VisualStudio::CppUnitTestFramework::TestClass<className>
这不能直接与模板一起使用 - 据我所知,没有办法指定一个 className
值,该值将包含具有正确编译语法的模板参数。
因此,我尝试了以下操作:
namespace MyUnitTests {
ONLY_USED_AT_NAMESPACE_SCOPE
template<MyEnumClass MeasurementType, char ExpectedShift>
class templatedScaleTestClass : public TestClass<templatedScaleTestClass<MeasurementType,ExpectedShift>>
{
public:
TEST_METHOD(Test_ExpectedShift) {
Assert::AreEqual(ExpectedShift, Calculations::getShiftAmount(MeasurementType));
}
};
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::FIRST,3>;
ONLY_USED_AT_NAMESPACE_SCOPE template class templatedScaleTestClass<MyEnumClass::THIRD,1>;
}
这会编译,在我看来它应该允许我在模板 class 中定义 TEST_METHOD
的集合,然后实例化必要的枚举集合和常量值以设置他们起来(也许在未来对其他参数使用某种构造函数,虽然看着 CppUnitTest.h 让我想知道这是否可能是另一个问题......)
但是,class 从未出现在测试资源管理器中,尝试右键单击测试(在模板代码中)并单击 "Run Test(s)" 会产生以下输出:
[datetime Informational] Executing test method 'MyUnitTests.templatedScaleTestClass<MeasurementType, ExpectedShift>.Test_ExpectedShift'
[datetime Informational] No tests found to run.
编辑:不确定最后一部分 ("No tests found to run") 的相关性如何 - 对正常测试(无用户端模板)执行相同的操作会产生相同的输出。单击远离特定测试会运行 .cpp 文件中的所有测试。可能是我右键菜单用错了
尽管已多次尝试让它显示,并检查如下函数的输出:
template<typename T>
void debugMethod(TestClass<T> *tc) {
const TestClassInfo* classInfo = tc->__GetTestClassInfo();
std::stringstream msg;
msg << "Tag: " << classInfo->metadata->tag << std::endl;
msg << "helpMethodName: " << classInfo->metadata->helpMethodName << std::endl;
msg << "helpMethodDecoratedName: " << classInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "New method address: " << &(classInfo->pNewMethod) << std::endl;
const MemberMethodInfo* methodInfo = T::__GetTestMethodInfo_Debug();
msg << "methodInfo - Tag: " << methodInfo->metadata->tag << std::endl;
msg << "methodInfo - methodName: " << methodInfo->metadata->methodName << std::endl;
msg << "methodInfo - helpMethodName: " << methodInfo->metadata->helpMethodName << std::endl;
msg << "methodInfo - helpMethodDecoratedName: " << methodInfo->metadata->helpMethodDecoratedName << std::endl;
msg << "methodInfo - lineNo: " << methodInfo->metadata->lineNo << std::endl;
Logger::WriteMessage(msg.str().c_str());
}
... (namespace, test class etc)
TEST_METHOD(Debug) { debugMethod(this); }
并在标准 TEST_CLASS 和我的模板 class 中观察到相似的结果,我无法获得模板 classes 以显示在测试资源管理器中。
可以模板化 class 然后从非模板化的 class 调用测试函数:
template <MyEnum val>
class myClass : public TestClass<myClass<val>>
{
public:
TEST_METHOD(MyTest) {
Assert::AreEqual(val, MyEnum::exampleValue);
}
}
TEST_CLASS(DummyTests) {
TEST_METHOD(Test_across) {
auto a = myClass<MyEnum::MyEnumValue>();
a.MyTest();
}
}
但这在测试资源管理器中提供的反馈仍然不够理想。
另一种选择(虽然丑陋...)是定义一个宏函数,该函数采用您要模板化的参数,然后在宏中定义整个 class:
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
#define SCALING_TEST(TYPE_TO_TEST, EXPECTED_SHIFT)\
TEST_CLASS(CATNAME(ScalingTest_, TYPE_TO_TEST)) {\
private:\
MyEnum type = MyEnum::TYPE_TO_TEST;\
public:\
TEST_METHOD(HasExpectedShift) {\
Assert::AreEqual((char)EXPECTED_SHIFT, Calculations::getShiftAmount(type));\
}\
}
namespace ScalingTests {
SCALING_TEST(SPEED, 3);
}