0

首先,这里描述了一个具有类似目标的问题: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 循环将所有 Asserts 放在一个中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>;
}

这可以编译,在我看来它应该允许我TEST_METHOD在模板类中定义 s 的集合,然后只需实例化必要的枚举和常量值集合来设置它们(也许对其他参数使用某种构造函数)未来,虽然看着 CppUnitTest.h 让我想知道这是否可能是另一个问题......)

但是,该类永远不会出现在测试资源管理器中,并且尝试右键单击测试(在模板代码中)并单击“运行测试”会产生以下输出:

[datetime Informational] Executing test method 'MyUnitTests.templatedScaleTestClass<MeasurementType, ExpectedShift>.Test_ExpectedShift'
[datetime Informational] No tests found to run.

编辑:不确定最后一部分(“未找到要运行的测试”)的相关性 - 对普通测试(无用户端模板)执行相同操作会产生相同的输出。在特定测试之外单击会运行 .cpp 文件中的所有测试。也许我错误地使用了右键菜单。

4

1 回答 1

0

尽管已经尝试了几次尝试让它显示,并检查如下函数的输出:

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 和我的模板类中观察到类似的结果,我无法让模板类显示在测试资源管理器中。

可以对一个类进行模板化,然后从非模板化类调用测试函数:

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();
        }
}

但这仍然在测试资源管理器中提供了不太理想的反馈。

另一种选择(丑陋,因为它是......)是定义一个宏函数,它接受你想要模板化的参数,然后在宏中定义你的整个类:

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);
}
于 2019-11-25T03:03:30.590 回答