我想用一组不同的输入和预期输出对一个函数进行单元测试。
我的功能无关紧要,因此我会使用一个示例函数来计算英语单词,并使用以下候选实现:
int countEnglishWords( const std::string& text )
{
return 5;
};
以下是测试数据集。数据的结尾由带有单词" END"。
的元素标记struct TestData {
std::string text;
int englishWords;
};
struct TestData data[] = // Mark end with "END"
{
{ "The car is very fast", 5 },
{ "El coche es muy rapido", 0 },
{ "The rain in Spain stays mainly in the plain", 9},
{ "XXXXX OOOOO TTTT", 0},
{ "Yes Si No No", 3},
{ "I have a cheerful live", 5},
{ "END", 0}
};
我可以轻松编写6个测试用例,我会得到我想要的结果。但这是不可维护的,因为添加到测试用例中的任何进一步测试都不会被测试,所以需要编写另一个测试用例,这只是锅炉板。因此,我编写了一个测试用例,循环遍历所有测试数据,如下所示:
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
class cppUnit_test: public CppUnit::TestFixture
{
private:
CPPUNIT_TEST_SUITE (cppUnit_test);
CPPUNIT_TEST(myTest);
CPPUNIT_TEST_SUITE_END();
public:
void myTest();
};
void cppUnit_test::myTest()
{
TestData* p = data;
while ( p->text != "END")
{
std::stringstream ss;
ss << "Text=\"" << p->text << "\" Counted=" <<
countEnglishWords(p->text) << " Expected=" << p->englishWords;
CPPUNIT_ASSERT_MESSAGE( ss.str().c_str(),
countEnglishWords(p->text) == p->englishWords );
++p;
}
}
int main()
{
CPPUNIT_TEST_SUITE_REGISTRATION (cppUnit_test);
CppUnit::Test *suite =
CppUnit::TestFactoryRegistry::getRegistry().makeTest();
CppUnit::TextUi::TestRunner runner;
runner.addTest(suite);
runner.run();
return 0;
}
问题是前面的代码在第一次测试中运行良好并且还在第二次测试中检测到错误但在此之后它停止测试。报告是:
!!! FAILURES !!!
测试结果:
运行:1失败:1错误:0
虽然我想得到的结果是:
!!! FAILURES !!!
测试结果:
运行:6次失败:4次错误:0
答案 0 :(得分:1)
正如我在评论中已经提到的,cppunit 1.14.0可以支持你的用例。
我想引用外部数组,最快的方法是使用CPPUNIT_TEST_PARAMETERIZED。这个宏需要两个参数:首先类似于CPPUNIT_TEST一个测试方法,然后作为第二个参数迭代。
根据您的代码,它看起来像:
CPPUNIT_TEST_PARAMETERIZED(myTest, aData);
现在我们需要调整你的myTest功能。
void cppUnit_test::myTest(const TestData& data)
{
std::stringstream ss;
ss << "Text=\"" << data.text << "\" Counted=" <<
countEnglishWords(data.text) << " Expected=" << data.englishWords;
bool b = countEnglishWords(data.text) == data.englishWords;
std::string a = ss.str();
CPPUNIT_ASSERT_MESSAGE( a,
b);
}
最后,由于框架需要一种方法来报告哪个测试失败,因此它期望它可以打印传递给测试函数的参数。在这种情况下,最简单的方法是添加一个简单的运算符&lt;&lt;过载。
std::ostream& operator<<(std::ostream& strm, const TestData& data)
{
strm << data.text;
return strm;
}
如果您将这些部分组合在一起,您应该快速获得一个通用解决方案,该解决方案允许您根据需要向数据阵列添加尽可能多的数据,而无需调整测试代码。