Определение используемого базового класса в параметризованном тесте с использованием googletest - PullRequest
1 голос
/ 10 апреля 2019

Физическое моделирование обновляется, и я пытаюсь написать юнит-тесты для функций, которые должны быть заменены с помощью параметризованных тестов. Базовая настройка выглядит примерно так:

using MyTypes = ::testing::Types<base1<1>, base1<2>, base2<1>, base2<2>>;
TYPED_TEST_CASE(tests, MyTypes);
TYPED_TEST(tests, testname){
  auto obj = clname(TypeParam);
  auto parameters = generate_values(TypeParam);      
  for( auto& p : parameters ){
    // Test if obj.func(p) equals the saved values
  }
}

Поскольку число базовых классов и генерируемых значений велико, я хотел бы записать выходные данные текущей (предполагаемой правильной) версии в файл и сравнить выходные данные новых версий с этими значениями. Функция (func) изменяется в зависимости от TypeParam, поэтому мне нужно также сохранить используемый базовый класс в некоторой форме.

Однако я не знаю, как определить используемый базовый класс: одним из решений было бы сохранить и сравнить typeid, как при сохранении

typeid(TypeParam).name()

вместе с результатами, но мне сказали, что это значение может меняться между компьютерами и поэтому бесполезно в качестве значения для использования. Я попытался найти соответствующую запись в MyTypes, т.е. сохранил i, для которого

std::is_same<MyTypes[i],TypeParam>::value

верно, но, похоже, это не относится к любому я. Есть ли хороший способ сделать это с параметризованным тестом? Или мне нужно использовать что-то еще целиком?

1 Ответ

0 голосов
/ 10 апреля 2019

Вы можете пометить base1<1>, base1<2>, base2<1>, base2<2>, ... одномерными целыми числами 0, 1, 2, 3, ... используя следующий шаблон класса TestsWrapper. Более конкретно, TestsWrapper<...T>::getIdx<U>() возвращает позицию типа U в пакете параметров ...T. Например,

  • TestsWrapper<A,B,C,D,E>::getIdx<A>() - это 0,
  • TestsWrapper<A,B,C,D,E>::getIdx<B>() - это 1,
  • TestsWrapper<A,B,C,D,E>::getIdx<C>() - это 2,

и так далее. Это позволяет нам идентифицировать тестируемый класс как TestsWrapper<base1<1>, base1<2>, base2<1>, base2<2>>::getIdx<TypeParam>() во время компиляции:

Live DEMO

template<class ...T>
class TestsWrapper
{
   template<class U>
   static constexpr std::size_t getIdx_impl()
   {
       return 0;
   }

   template<class U, class T0, class ...Ts>
   static constexpr std::size_t getIdx_impl()
   {
       return std::is_same<U, T0>::value ? 0 : (getIdx_impl<U, Ts...>() + 1);
   }

public:
   using Types = ::testing::Types<T...>;

   template<class U>
   static constexpr std::size_t getIdx()
   {
       return getIdx_impl<U, T...>();
   }
};

Пример использования этого шаблона класса для типизированных тестов следующий. Здесь idx - это вышеуказанная целочисленная метка 0, 1, 2, 3, ... и сохраняет, какой тип тестируется в настоящее время. Вы можете использовать этот ярлык для идентификации тестируемого в данный момент класса. Я уже проверил, что этот подход хорошо работает в моей среде Windows:

using TWrapper = TestsWrapper<base1<1>, base1<2>, base2<1>, base2<2>>;

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

TYPED_TEST_CASE(test, TWrapper::Types);

TYPED_TEST(test, testname)
{
   constexpr auto idx = TWrapper::getIdx<TypeParam>();
   ...
}
...