Я использую структуру Google Test для написания модульных тестов для кода C ++. Среди других тестов я хочу проверить правильность построения объектов разных классов, которые все являются производными от одного абстрактного класса. Начнем с абстрактного класса:
class AbstractClass
{
public:
virtual ~AbstractClass() = default;
std::string getName() const { return name_; }
std::string toString() const { return toStringImpl(); }
protected:
AbstractClass(std::string name) : name_(name) {}
private:
virtual std::string toStringImpl() const = 0;
std::string name_;
};
Он имеет функцию getName()
, которая реализуется самим абстрактным классом. И у него есть функция toString()
, реализация которой делегируется производным классам частной чистой виртуальной функцией toStringImpl()
. toString()
здесь не представляет особого интереса, но его концепция делает этот класс абстрактным.
У меня есть два производных класса conctrete, а именно:
class ConcreteClassA : public AbstractClass
{
public:
ConcreteClassA(std::string name) : AbstractClass(name) {}
private:
virtual std::string toStringImpl() const override { return ""; }
};
class ConcreteClassB : public AbstractClass
{
public:
ConcreteClassB(std::string name) : AbstractClass(name) {}
private:
virtual std::string toStringImpl() const override { return ""; }
};
Ничего особенного, просто тот факт, что конструктор абстрактного класса вызывается во время построения этих конкретных классов.
Если я хочу проверить правильность конструкции, я, конечно, могу написать все тесты для всех производных классов, как в следующем примере, где я включаю тесты для функциональности абстрактного класса:
class ConcreteClassATests : public ::testing::Test
{};
TEST_F(ConcreteClassATests, constructionSuccessful)
{
ConcreteClassA a {"TestA"};
ASSERT_EQ(a.getName(), "TestA");
}
class ConcreteClassBTests : public ::testing::Test
{};
TEST_F(ConcreteClassBTests, constructionSuccessful)
{
ConcreteClassB b {"TestB"};
ASSERT_EQ(b.getName(), "TestB");
}
Учитывая m производные классы и n тесты для содержимого абстрактного класса, это приведет к m * п рукописных тестов. Я думаю, что это должно быть решено с помощью n рукописных тестов (в результате получаются n или m * n выполненные тесты).
Я уже читал около абстрактных тестов с параметризацией значений , которые звучат многообещающе, а также примерно типизированных тестов , но похоже, что это применимо только к функциям тестирования, которые получают ввод и выводят результат. Я не уверен, можно ли применить эти концепции для проверки правильности построения объектов.
Итак, может ли кто-нибудь сказать мне, можно ли каким-то образом определить тест для «абстрактной функции» только один раз?
Чтобы воспроизвести и запустить мой пример, все фрагменты можно объединить в один исходный файл. Просто добавьте следующие две строки вверху и сделайте ссылку на gmock_main
и pthread
:
#include <string>
#include <gmock/gmock.h>