1

我目前正在尝试为模块生成一些后编码 UT。该模块将输入数据分类到数据库,如果找到匹配项,则返回正确的值。

在构建了一个包含所有可能的输入场景及其预期结果的表格后,我发现我需要创建 50 多个测试。由于所有测试基本相同,除了测试名称和输入,某种模板似乎适合这里,减少代码混乱。

我最初的设想,要么是创建这样一个模板并使用输入数据和预期结果扩展到测试的宏,要么是在宏的帮助下使用表示场景表的结构来包装它。(我想 C++ 模板在这里也足够了)。

但是,我不确定这是一条正确的道路,并且想知道是否有人可以就如何解决它提出一些建议。还有一个问题是它如何适合 TDD 方法。

这是使用 CppUTest 的想法:

#define GEN_TEST_MOD_CLASSIFIER(GROUP_NAME, TEST_NAME, PRIORITY, isCOMPRESS, isX, EXPECTING) \
TEST(GROUP_NAME, TEST_NAME) \
{ \
   int hit; \
   setupDB(PRIORITY, isCOMPRESS, isX); \
   hit = func(PRIORITY, isCOMPRESS, isX); \
   CHECK_EQUAL(EXPECTING, hit); \
}

使用示例:

GEN_TEST_MOD_CLASSIFIER(Classifier_Tests, LowPriority_NoCompress_NoX__HIT, PRIO_LOW, NOT_COMPRESS, NO_X, HIT_DB)
4

1 回答 1

1

好吧,没有外部工具,你能做的最好的事情很可能是使用宏。那是因为你需要TEST(GROUP_NAME, TEST_NAME)为每个测试用例。

情况可能并非如此。您可以不用为每个场景设置单独的测试用例,或者 CppUTest 可能支持以编程方式添加测试用例。在这种情况下,您可以创建一个采用 input-output-testcasename 元组向量的方法。并将在每个元组上添加测试用例/运行测试。不需要宏。

类似的东西(伪代码):

typedef std::tuple<std::string, std::string, PriorityType, CompressType, ExpectedValueType> TestInfo;

void RunTest(const TestInfo& testInfo)
{
// Assuming here you're OK with this kind of test cases separation
    std::cout << "Running test" << std::get<0>(testInfo) << ", " << std::get<1>(testInfo) << std::endl;

   int hit;
   setupDB(std::get<2>(testInfo), std::get<3>(testInfo), isX);
   hit = func(std::get<2>(testInfo), std::get<3>(testInfo), isX);
   CHECK_EQUAL(std::get<4>, hit);
}

void RunTests(const TestInfo& testInfo)
{
    std::for_each(testInfo.begin(), testInfo.end(), RunTest);
}

std::vector<TestInfo> tests = { test1, test2 };
RunTests(tests);

如果这不起作用,宏实际上很好,您也可以在那里使用基于表格的方法。看看boost预处理器(http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/index.html

再次伪代码:

#include <boost\preprocessor\seq.hpp>

#define GENERATE_TEST_CASE(_ignore1_, _ignore2_, _testCaseInfoSequence_) \
    TEST(BOOST_PP_SEQ_ELEM(0, testCaseInfoSequence), BOOST_PP_SEQ_ELEM(1, testCaseInfoSequence)) \
    { \
        int hit; \
        setupDB(BOOST_PP_SEQ_ELEM(2, testCaseInfoSequence), BOOST_PP_SEQ_ELEM(3, testCaseInfoSequence), BOOST_PP_SEQ_ELEM(4, testCaseInfoSequence)); \
        hit = func(BOOST_PP_SEQ_ELEM(2, testCaseInfoSequence), BOOST_PP_SEQ_ELEM(3, testCaseInfoSequence), BOOST_PP_SEQ_ELEM(4, testCaseInfoSequence)); \
        CHECK_EQUAL(BOOST_PP_SEQ_ELEM(5, testCaseInfoSequence), hit); \
    }

#define TESTCASES \
    ( \
        (Group1)(Test1)(prio1)(isCompress1)(isX1)(expectedVal1) \
        (Group1)(Test2)(prio2)(isCompress2)(isX2)(expectedVal2) \
    ) 

// This statement will generate all tests cases in defined in TESTCASES sequnce.
BOOST_PP_SEQ_FOREACH(GENERATE_TEST_CASE, _ignore_, TESTCASES);
于 2013-08-27T22:16:36.240 回答