2013-08-26 19 views
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) 

感谢, 伊迪。

回答

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

如果不工作,宏实际上是很好,你可以用基于表格的方法去那里。再次(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);