我正在使用QTest
,但在我看来,这个问题比仅仅QTest
具体更普遍。假设我们有一个简单的类:
class Number
{
Number() {}
Number(int i) : m_Value(i) {}
int value() const { return m_Value; }
private:
int m_Value = 0;
};
另一个派生自Number
的课程:
class Ten : public Number
{
public:
Ten() : Number(10) {}
};
类QTest
的测试(使用Number
)可能如下所示:
class NumberTest : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
private slots:
void testNumberConstructor()
{
std::shared_ptr<Number> num = createNumber();
QVERIFY(num->value() == 0);
std::shared_ptr<Number> num = createNumber(1);
QVERIFY(num->value() == 1);
}
private:
virtual std::shared_ptr<Number> createNumber() { return std::make_shared<Number>(); }
virtual std::shared_ptr<Number> createNumber(int i) { return std::make_shared<Number>(i); }
};
这样我们就可以从Ten
推导NumberTest
的测试,以确保Ten
不会无意中破坏Number
的接口合同(例如可能很重要)如果Number
调用了由Ten
覆盖的虚拟方法,或者稍后将其更改为执行此操作)。
class TenTest : public NumberTest
{
Q_OBJECT
public:
using NumberTest::NumberTest;
private slots:
void testTenConstructor()
{
Ten num;
QVERIFY(num.value() == 10);
};
private:
virtual std::shared_ptr<Number> createNumber() override { return std::make_shared<Number>(new Ten()); }
virtual std::shared_ptr<Number> createNumber(int i) override { return std::make_shared<Number>(new Ten()); } //<<< This is the problem!
};
注意:我使用shared_ptr
因为unique_ptr
没有自动捕获正确的析构函数,而且我没有虚拟析构函数。
继承的测试将运行基类的测试和它自己的测试,但是它会在基类测试的第二个断言(QVERIFY
)上失败,因为派生类Ten
不会提供构造函数(或任何其他方式)来提供测试所需的内容(Number
具有特定值)。只有在测试继承类的构造函数(继承测试时)并且我不确定如何最好地解决它时,才会出现这个问题。
我当然不希望从父母的测试中挑选哪些测试将运行以及哪些测试没有甚至更糟糕地复制测试(省略构造函数的测试)。
另一方面,我能想到的唯一解决方案是从将继承的测试类中省略对构造函数的测试(并且对于从中派生的所有测试应该是通用的)并创建单独的测试类仅用于测试其构造函数的基类。毕竟构造函数不是接口的一部分。有没有其他方法(优雅地)解决这个问题?或者我开始时做错了吗?