前面講了在 Boost Test 怎麼去根據資料來自動建立 test case,這邊來講一下 C++ 程式很可能碰到的問題:要怎麼針對 template 的型別自動產生 test case?
在 Boost Test 中,有提供 BOOST_AUTO_TEST_CASE_TEMPLATE
這個巨集(官方文件),可以搭配 Boost MPL(官網)的型別列表、或是用 std::tuple
(參考)來自動建立出不同型別的 test case。
下面是一個使用 Boost MPL 的例子:
#define BOOST_TEST_MODULE example #include <boost/test/included/unit_test.hpp> #include <boost/mpl/list.hpp> typedef boost::mpl::list<int, long, unsigned char> test_types; BOOST_AUTO_TEST_CASE_TEMPLATE(TypedTest, T, test_types) { BOOST_TEST(sizeof(T) == (unsigned)4); }
這邊先定義了一個 Boost MPL 的型別清單 test_types
,裡面有 int
、long
、unsigned char
三種型別。
之後,則是透過 BOOST_AUTO_TEST_CASE_TEMPLATE
這個巨集,來針對 test_types
中的型別、建立出三個 test case;而在 test case 中,則可以使用 T
來做為要測試的型別。
這樣的測試程式所產生的測試會如下:
>.\Test.exe --list_content
TypedTest<int>*
TypedTest<long>*
TypedTest<unsigned char>*
這邊可以看的出來,他產生的 test case 名稱裡面就直接包含了型別名稱,所以在辨別度上算是相當高的~
而如果不想用 Boost MPL 的話,也可以直接把 boost::mpl::list
換成 std::tuple
,這樣就可以做到同樣的事了~下面就是修改過的樣子:
#define BOOST_TEST_MODULE example #include <boost/test/included/unit_test.hpp> #include <tuple> typedef std::tuple<int, long, unsigned char> test_types; BOOST_AUTO_TEST_CASE_TEMPLATE(TypedTest, T, test_types) { BOOST_TEST(sizeof(T) == (unsigned)4); }
而如果不想用 #typedef
額外定義 test_types
的話,則需要搭配 BOOST_IDENTITY_TYPE
來使用;下面是一個例子:
#define BOOST_TEST_MODULE example #include <boost/test/included/unit_test.hpp> #include <boost/utility/identity_type.hpp> #include <tuple> BOOST_AUTO_TEST_CASE_TEMPLATE(TypedTest, T, BOOST_IDENTITY_TYPE((std::tuple<int, long, unsigned char>))) { BOOST_TEST(sizeof(T) == (unsigned)4); }
比較特別的,是這邊需要兩個小括號,否則編譯的時候會出錯。
至於有沒有比較方便?恩,不好說。
相較於資料導向的測試來說,Boost Test 在 template test case 提供的功能算是相對少的,似乎也沒辦法針對多組型別來展開,算是滿可惜的;而以官方提供的巨集來說,應該也是沒辦法和 Boost Test 提供的 dataset 混用。
所以如果要做到更進階的 test case 產生,可能就需要自己用 C++ API 來建立 test case 了~