Login/Register
C++ Multiple parameters with GTest TYPED_TEST
Asked Answered
A

1

5

I have fallowing sets of tests:

TEST_F(FactoryShould, createAFromAModule)
{
    const auto stateMachine = createStateMachine(EModule_A);
    const auto* typedStateMachine =
        dynamic_cast<const BackEnd<transitiontable::A, Guard>*>(stateMachine.get());
    ASSERT_TRUE(typedStateMachine);
}

TEST_F(FactoryShould, createBFromBModule)
{
    const auto stateMachine = createStateMachine(EModule_B);
    const auto* typedStateMachine =
        dynamic_cast<const BackEnd<transitiontable::B, Guard>*>(stateMachine.get());
    ASSERT_TRUE(typedStateMachine);
}

Is there any way to turn them into Typed Tests? All I seen is solution for only one changing parameter, there I have 2 changing parameters, EModule can be used for multiple transitiontables, so something like map looks good, but it is doable?

Abstemious answered 10/9, 2018 at 11:36 Comment(3)
In your case the two types are connected - you would always change them together. You could create a wrapper type in the test code that inside it contains typedefs to the 2 types you need to instantiate.Dermatologist
bu this do You mean something like this: struct Type { using EModule = ::testing::Types<EModule_A, EModule_B>; using transition = ::testing::Types<transitiontable::A, transitiontable::B>; } in TC it looks good (if it will work that way) but it looks hard to maintenance TEST_F(FactoryShould, createFromModule) { const auto stateMachine = createStateMachine(Type.EModule); const auto* typedStateMachine = dynamic_cast<const BackEnd<Type.transition, Guard>*>(stateMachine.get()); ASSERT_TRUE(typedStateMachine); }Abstemious
I think so, but as you can see, comments don't work for formatting code. I'm not sure which maintenence issue you have: creating a new variant, or adding a third helper class. For the former you might be able to create a class template with the two classes as arguments, and create that class on the fly. For the latter, updating the template may be acceptable. You could look at template tuples.Dermatologist
H
11

With std::pair you can make one type out of any other two. (And with std::tuple you can make one type out of any other N).

You can write googletest TYPED_TESTs in which TypeParam assumes values from a list of std::pair<X,Y>, for paired parameter-types X and Y, so that each instantiation of such a TYPED_TEST has X defined as TypeParam::first_type and Y defined as TypeParam::second_type. E.g:

gtester.cpp

#include <gtest/gtest.h>
#include <utility>
#include <cctype>

struct A1 {
    char ch = 'A';
};

struct A2 {
    char ch = 'a';
};

struct B1 {
    char ch = 'B';
};

struct B2 {
    char ch = 'b';
};


template <typename T>
class pair_test : public ::testing::Test {};

using test_types = ::testing::Types<std::pair<A1,A2>, std::pair<B1,B2>>;
TYPED_TEST_CASE(pair_test, test_types);

TYPED_TEST(pair_test, compare_no_case)
{
    typename TypeParam::first_type param1;
    typename TypeParam::second_type param2;
    ASSERT_TRUE(param1.ch == std::toupper(param2.ch));
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

Compile, link, run:

$ g++ -Wall -o gtester gtester.cpp -lgtest -pthread && ./gtester
[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 1 test from pair_test/0, where TypeParam = std::pair<A1, A2>
[ RUN      ] pair_test/0.compare_no_case
[       OK ] pair_test/0.compare_no_case (0 ms)
[----------] 1 test from pair_test/0 (0 ms total)

[----------] 1 test from pair_test/1, where TypeParam = std::pair<B1, B2>
[ RUN      ] pair_test/1.compare_no_case
[       OK ] pair_test/1.compare_no_case (0 ms)
[----------] 1 test from pair_test/1 (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 2 test cases ran. (0 ms total)
[  PASSED  ] 2 tests.
Homs answered 10/9, 2018 at 18:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.