0

Catch を使用してテンプレート化されたクラスをテストする良い方法を探しています。私はほとんど動作するものを持っています:

#define RUN_ALL(fn, params)  \
fn<uint8_t, bool>(params);  \
fn<uint8_t, char>(params);  \
fn<uint16_t, bool>(params); \
fn<uint16_t, char>(params); \
fn<uint32_t, bool>(params); \
fn<uint32_t, char>(params); \
fn<uint64_t, bool>(params); \
fn<uint64_t, char>(params);

template<typename A, typename B>
void test_number_one() {
   REQUIRE(...)
} 

TEST_CASE("Foo::Foo() works nicely", "[SmallGraph]") {
  RUN_ALL(test_number_one)
}

このセットアップは、最初の失敗までのみ実行されます。これは、8 つのケースすべてが同じように失敗する可能性が高いため、問題ありません。ただし、障害が発生したときにどのテンプレート引数のセットが使用されているかを知っておくと便利です。私の考えはこれを行うことです:

#define RUN_ALL_P(fn, params)  \
INFO("Testing <uint8_t, bool>"); \
fn<uint8_t, bool>(params);  \
INFO("Testing <uint8_t, char>"); \
fn<uint8_t, char>(params);  \
INFO("Testing <uint16_t, bool>"); \
fn<uint16_t, bool>(params); \
...

ただし、RUN_ALL で複数の INFO を使用することはできません。これを行うと、重複した識別子を持つコードが生成されるためです。

FOO.cpp:270:3: error: redefinition of 'scopedMessage270'
  RUN_ALL(test_number_one);

(RUN_ALL(test_number_one)は 270 行目に表示されます。)

すべてのテスト関数を同じ署名にする必要がない回避策のアイデアはありますか?

(また、CATCH を使用したテンプレート コードのテストに関する記事へのポインタ、および一般的な例外処理 (つまり、try/catch) に関する多くの結果を取得せずにそのような記事を検索する方法に関する提案も歓迎します。)

4

2 に答える 2

1

マクロの問題は、マクロを展開すると、1 行に展開されることです。テスト フレームワークが使用されているかどうかはわかりませんが、マクロがこれに匹敵することを行うことは明らかです。

struct M { M(char* msg) { puts(msg); } }; // just an example class...
#define INFO(m) M scopedMessage##__line__(msg)

したがって、270 行目でマクロ RUN_ALL を使用すると、複数の scopedMessage270 インスタンスが取得されます...

マクロをテンプレートに置き換えることで、この問題を回避できます。残念ながら、これをテンプレート関数で使用することはできないため、テスト ケースのテンプレート クラスも作成する必要があります。

template <template <typename T, typename TT > class Test >
struct All
{
    template <typename ... Parameters>
    static void run(Parameters ... parameters)
    {
        Test<uint8_t, bool>::run(parameters ...);
        Test<uint8_t, char>::run(parameters ...);
        Test<uint16_t, bool>::run(parameters ...);
        Test<uint16_t, char>::run(parameters ...);
        Test<uint32_t, bool>::run(parameters ...);
        Test<uint32_t, char>::run(parameters ...);
        Test<uint64_t, bool>::run(parameters ...);
        Test<uint64_t, char>::run(parameters ...);
    }
};

template<typename A, typename B>
struct test_number_one
{
    static void run()
    {
        // log test name
        // run the test
    }
};
template<typename A, typename B>
struct test_number_two
{
    static void run(int n)
    {
        // log test name and parameter value
        // run the test
    }
};

int main(int argc, char* argv[])
{
    All<test_number_one>::run();
    All<test_number_two>::run(12);
    All<test_number_two>::run(10);
}

現在、テンプレート内では、すべてのコード行が別々の行に残っているため、好きなようにログの間に配置できます。

template <typename ... Parameters>
static void run(Parameters ... parameters)
{
    INFO("uint8_t, bool");
    Test<uint8_t, bool>::run(parameters ...);
    INFO("uint8_t, char");
    Test<uint8_t, char>::run(parameters ...);
// ...
于 2016-07-22T05:36:55.420 に答える