2011-11-10 66 views
10

是否有可能以任何方式將BOOST_AUTO_TEST_CASEBOOST_AUTO_TEST_CASE_TEMPLATE宏與BOOST_PARAM_TEST_CASE混合?我甚至對這種事情發生的方式非常感興趣。是否可以在boost :: test上使用自動註冊的BOOST_PARAM_TEST_CASE?

必須手動構建所有測試用例似乎非常乏味。但BOOST_PARAM_TEST_CASE機制相當有用,但只有在您有測試初始化​​函數時纔有效,這又會要求您使用手動測試用例構建。

有沒有關於如何自動掛鉤到自動化系統的任何文檔,所以你可以提供自己的測試,自動註冊自己?

我現在使用boost 1.46。

+0

沒有人對'boost :: test'的內部工作有太多瞭解的是StackOverflow? – Omnifarious

回答

1

與升壓版本1.59開始,這被處理由data-driven test cases

#define BOOST_TEST_MODULE MainTest 

#include <boost/test/included/unit_test.hpp> 
#include <boost/test/data/test_case.hpp> 
#include <boost/array.hpp> 

static const boost::array< int, 4 > DATA = { 1, 3, 4, 5 }; 

BOOST_DATA_TEST_CASE(Foo, DATA) 
{ 
    BOOST_TEST(sample % 2); 
} 

此功能需要編譯器和庫提供的C++ 11支持。

3

您可以輕鬆地混合手動和自動化測試單元註冊。實現你自己的初始化函數(如this頁面上的例子20),在init函數內部,你可以爲參數化測試用例執行註冊。 Boost.Test會將它們合併成單個測試樹。

+0

我想到了這一點。但是我有許多獨立的源文件,每個文件都有自己的測試,並且初始化函數有望成爲具有單一名稱的全局函數。我希望能夠使用新的參數化測試添加新文件,而無需查找全局init函數並修改它以添加測試。 – Omnifarious

+0

不幸的是,參數化測試用例必須手動註冊(我正在開發一個新功能以允許基於註冊自動測試用例的數據集進行測試)。您可以通過使用某種ffactory或簡單的extern函數輕鬆分發註冊機制。 –

+0

很高興知道它可以輕鬆分發。但我不知道如何使用工廠或簡單的外部功能來實現這一點。我實際上已經剖析了自動註冊機制,我正在考慮編寫一個幫助類,它被設計爲一個靜態變量,它將爲我執行註冊。有更容易的方法嗎? – Omnifarious

12

我寫了自己的支持,因爲那裏似乎沒有任何好的支持。這需要C++ 11 decltype功能和::std::remove_const::std::remove_reference庫方法工作。

宏定義是BOOST_FIXTURE_TEST_CASEBOOST_AUTO_TEST_CASE宏的修改版本。

你可以通過這樣的聲明功能使用:

BOOST_AUTO_PARAM_TEST_CASE(name, begin, end) 
{ 
    BOOST_CHECK_LT(param, 5); // The function will have an argument named 'param'. 
} 

這裏是定義BOOST_AUTO_PARAM_TEST_CASE微距頭:

#include <boost/test/unit_test_suite.hpp> 
#include <boost/test/parameterized_test.hpp> 
#include <type_traits> 

#define BOOST_FIXTURE_PARAM_TEST_CASE(test_name, F, mbegin, mend)  \ 
struct test_name : public F {           \ 
    typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \ 
    void test_method(const param_t &);         \ 
};                  \ 
                     \ 
void BOOST_AUTO_TC_INVOKER(test_name)(const test_name::param_t &param) \ 
{                  \ 
    test_name t;              \ 
    t.test_method(param);            \ 
}                  \ 
                     \ 
BOOST_AUTO_TU_REGISTRAR(test_name)(         \ 
    boost::unit_test::make_test_case(         \ 
     &BOOST_AUTO_TC_INVOKER(test_name), #test_name,     \ 
     (mbegin), (mend)));            \ 
                     \ 
void test_name::test_method(const param_t &param)      \ 

// ******* 

#define BOOST_AUTO_PARAM_TEST_CASE(test_name, mbegin, mend)   \ 
    BOOST_FIXTURE_PARAM_TEST_CASE(test_name,       \ 
            BOOST_AUTO_TEST_CASE_FIXTURE,   \ 
            mbegin, mend) 
+1

+1,但我需要C++ 03版本。 –

+0

我對這段代碼有問題,抱怨說找不到'make_test_case'的正確重載。我不得不將'(mbegin),(mend)));'改成'(mbegin),(mend)),boost :: unit_test :: decorator :: collector :: instance());'。 –

5

由@Omnifarious提供解決方案的工作工作,但需要C++ 11編譯器。

適應用於C++ 03編譯器溶液:

#include <boost/test/unit_test_suite.hpp> 
#include <boost/test/parameterized_test.hpp> 

#define BOOST_FIXTURE_PARAM_TEST_CASE(test_name, F, P, mbegin, mend) \ 
struct test_name : public F            \ 
{                  \ 
    typedef P param_t;             \ 
    void test_method(const param_t &);         \ 
};                  \ 
                     \ 
void BOOST_AUTO_TC_INVOKER(test_name)(const test_name::param_t &param) \ 
{                  \ 
    test_name t;              \ 
    t.test_method(param);            \ 
}                  \ 
                     \ 
BOOST_AUTO_TU_REGISTRAR(test_name)(         \ 
    boost::unit_test::make_test_case(         \ 
     &BOOST_AUTO_TC_INVOKER(test_name), #test_name,     \ 
     (mbegin), (mend)));            \ 
                     \ 
void test_name::test_method(const param_t &param)      \ 

// ******* 

#define BOOST_AUTO_PARAM_TEST_CASE(test_name, param_type, mbegin, mend)   \ 
    BOOST_FIXTURE_PARAM_TEST_CASE(test_name,       \ 
            BOOST_AUTO_TEST_CASE_FIXTURE,   \ 
            param_type,       \ 
            mbegin, mend) 

這種解決方案略有不同是使用情況。由於C++ 03中沒有declspec,因此無法自動推導參數對象的類型。我們必須把它作爲一個參數BOOST_AUTO_PARAM_TEST_CASE

class FooTestParam       
{  
public:       
    std::string mS;  

    FooTestParam (int n)  
    {    
     std::stringstream ss;  
     ss << n;   
     mS = ss.str();        
    }  
};   

FooTestParam fooParams [] =  
{   
    FooTestParam (42),  
    FooTestParam (314)  
};   

BOOST_AUTO_PARAM_TEST_CASE (TestFoo, FooTestParam, fooParams, fooParams + 2)   
{                     
    const std::string testVal = param.mS;           
}                     

BOOST_AUTO_TEST_CASE (TestAddressField)            
{                     
    const uint32_t raw = 0x0100007f; // 127.0.0.1         
    const uint8_t expected[4] = {127, 0, 0, 1};          
    const Mdi::AddressField& field = *reinterpret_cast <const Mdi::AddressField*> (&raw);  
    for (size_t i = 0; i < 4; ++i)             
     BOOST_CHECK_EQUAL (field[i], expected[i]);         
}                     
+0

Omnifarious在很長一段時間內還沒有被看到,所以我問你:有什麼理由說明基類型'BOOST_AUTO_TEST_CASE_FIXTURE'是通過宏參數傳遞的(你知道的),還是這是一個Omnifarious的副本神器'C++ 11解決方案?這個例子中的TestAddressField測試用例是否有目的? – DevSolar

+0

@DevSolar:我已經看了一段時間了,我不記得所有的技術。我可以推測...看起來它是Boost用於自動註冊測試用例的Boost定義的固定裝置。 –

+0

是的,'BOOST_AUTO_TEST_CASE_FIXTURE'是一個Boost內建函數。我只是想知道爲什麼Omniborous和你通過參數將外部宏('BOOST_AUTO_PARAM_TEST_CASE')的宏名稱傳遞給內部('BOOST_FIXTURE_PARAM_TEST_CASE'),而不是在內部宏中進行硬編碼(比如,'BOOST_FIXTURE_PARAM_TEST_CASE'可能有意義用不同的基類參數調用?)。沒關係。 ;-) – DevSolar

0

我拿着五花八門的頭文件,並修改了它,使得參數傳遞到測試夾具的構造函數,而不是測試方法。這要求測試夾具的構造函數聲明對參數的類型採用單個參數。我發現這是超級方便 - 非常感謝最初的問題和答案!

#include <boost/test/unit_test_suite.hpp> 
#include <boost/test/parameterized_test.hpp> 
#include <type_traits> 

#define BOOST_FIXTURE_PARAM_TEST_CASE(test_name, F, mbegin, mend)  \ 
struct test_name : public F {           \ 
    typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \ 
    test_name(const param_t &param) : F(param) {}      \ 
    void test_method(void);            \ 
};                  \ 
                     \ 
void BOOST_AUTO_TC_INVOKER(test_name)(const test_name::param_t &param)\ 
{                  \ 
    test_name t(param);             \ 
    t.test_method();             \ 
}                  \ 
                     \ 
BOOST_AUTO_TU_REGISTRAR(test_name)(         \ 
    boost::unit_test::make_test_case(         \ 
     &BOOST_AUTO_TC_INVOKER(test_name), #test_name,     \ 
     (mbegin), (mend)));            \ 
                     \ 
void test_name::test_method(void)          \ 

// ******* 

#define BOOST_AUTO_PARAM_TEST_CASE(test_name, mbegin, mend)   \ 
    BOOST_FIXTURE_PARAM_TEST_CASE(test_name,       \ 
            BOOST_AUTO_TEST_CASE_FIXTURE,   \ 
            mbegin, mend) 
+0

您能詳細說明Omnifarious上的解決方案的優點嗎? – kynan

2

由於Boost 1.59實現的內部細節發生了變化,Omnifarious的解決方案無法編譯。

原因加時賽這種情況正在改變簽名boost::unit_test::make_test_case功能:現在需要2組額外的參數:__FILE__, __LINE__

固定解:

#if BOOST_VERSION > 105800 
#define MY_BOOST_TEST_ADD_ARGS __FILE__, __LINE__, 
#define MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR ,boost::unit_test::decorator::collector::instance() 
#else 
#define MY_BOOST_TEST_ADD_ARGS 
#define MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR 
#endif 

#define BOOST_FIXTURE_PARAM_TEST_CASE(test_name, F, mbegin, mend)  \ 
struct test_name : public F {           \ 
    typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \ 
    void test_method(const param_t &);         \ 
};                  \ 
                     \ 
void BOOST_AUTO_TC_INVOKER(test_name)(const test_name::param_t &param) \ 
{                  \ 
    test_name t;              \ 
    t.test_method(param);            \ 
}                  \ 
                     \ 
BOOST_AUTO_TU_REGISTRAR(test_name)(         \ 
    boost::unit_test::make_test_case(         \ 
     &BOOST_AUTO_TC_INVOKER(test_name), #test_name,     \ 
     MY_BOOST_TEST_ADD_ARGS           \ 
     (mbegin), (mend))            \ 
     MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR);       \ 
                     \ 
void test_name::test_method(const param_t &param)      \ 




#define BOOST_AUTO_PARAM_TEST_CASE(test_name, mbegin, mend)   \ 
    BOOST_FIXTURE_PARAM_TEST_CASE(test_name,       \ 
            BOOST_AUTO_TEST_CASE_FIXTURE,   \ 
            mbegin, mend) 
+0

感謝您使用此解決方案。你救了我無盡的痛苦。 – Drew

相關問題