2013-08-26 47 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);