Можно ли использовать BOOST_PARAM_TEST_CASE с автоматической регистрацией на boost :: test? - PullRequest
11 голосов
/ 10 ноября 2011

Можно ли каким-либо образом смешать макросы BOOST_AUTO_TEST_CASE и BOOST_AUTO_TEST_CASE_TEMPLATE с BOOST_PARAM_TEST_CASE?Я даже заинтересован в действительно грязных способах заставить это случиться.

Необходимость сборки всех ваших тестовых примеров вручную кажется действительно утомительной.Но механизм BOOST_PARAM_TEST_CASE чертовски полезен, но работает, только если у вас есть функция инициализации теста, которая, в свою очередь, требует, чтобы вы использовали конструкцию тестового набора вручную.

Есть ли документация о том, как перехватитьсами в автоматизированную систему, чтобы вы могли предоставить свои собственные тесты, которые автоматически регистрируются?

Я сейчас использую Boost 1.46.

Ответы [ 6 ]

12 голосов
/ 13 ноября 2011

Я написал свою поддержку для этого, так как действительно не было никакой хорошей поддержки. Для этого требуется функция C ++ 11 decltype и методы библиотеки ::std::remove_const и ::std::remove_reference.

Определения макросов являются модифицированными версиями макросов BOOST_FIXTURE_TEST_CASE и BOOST_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)
5 голосов
/ 27 июля 2013

Решение, предоставляемое @Omnifarious works, работает, но требует компилятора 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]);                                  
}                                                                                   
3 голосов
/ 11 ноября 2011

Вы можете легко смешать ручную и автоматическую регистрацию тестового блока. Реализуйте свою собственную функцию init (как в примере 20 на странице this ), и внутри функции init вы можете выполнить регистрацию для параметризованных тестовых случаев. Boost.Test объединит их в одно тестовое дерево.

2 голосов
/ 24 марта 2017

Начиная с Boost версии 1.59, это обрабатывается управляемыми данными тестами :

#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 от компилятора и библиотеки.

2 голосов
/ 28 июля 2016

Начиная с 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 голосов
/ 15 ноября 2014

Я взял заголовочный файл Omnifarious и изменил его так, чтобы параметр передавался конструктору тестового прибора, а не методу теста.Для этого требуется, чтобы объявление конструктора тестового устройства принимало один аргумент с типом параметра.Я обнаружил, что это очень удобно - большое спасибо за первоначальный вопрос и ответ!

#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)
...