我使用Google Test和Google Mock使用测试驱动开发编写代码。我正在写一个小插件"用于Google Test。为了确保测试在预期时使用正确的消息失败,我创建了一个简单的FailureReporter
类,我将子类并在插件中注入模拟版本以捕获结果并与预期值进行比较。
本着TDD极端主义的精神,我还写了一个测试来确保FailureReporter
有效。要做到这一点,我已经取代了#34; FAIL()
宏,以便不会导致失败但捕获生成的错误消息。但是,这就是事情变得奇怪的地方。它在一台机器上工作,但在另一台机器上工作。在搜索原因时,我发现可以通过更改链接顺序来修复它。这看起来很奇怪,因为"修复"是使用宏完成的,我认为它在编译时会被硬编码,并且链接它不会产生影响。
我发现的是:连接测试本身不会导致任何问题。将它与使用模拟版本的FailureReporter的测试相关联,只有在FailureReporterTest.
为什么会发生这种情况后链接另一个测试时才有效?
FailureReporter.hpp:
#ifndef FAILURE_REPORTER_H
#define FAILURE_REPORTER_H
#include "gtest/gtest.h"
class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
FAIL() << errorMessage;
}
};
#endif
FailureReporterTest.cpp:
#include <sstream>
#include "gtest/gtest.h"
static std::stringstream* failStream;
#ifdef FAIL
#undef FAIL
#endif
#define FAIL() *failStream << ""
#include "FailureReporter.hpp"
TEST(FailureReporterTest, failMethod) {
const char* errorMessage = "Test error message";
FailureReporter *reporter;
std::stringstream stream;
failStream = &stream;
reporter = new FailureReporter();
reporter->fail(errorMessage);
EXPECT_STREQ(errorMessage, stream.str().c_str());
delete reporter;
}
MockFailureReporter.cpp
#ifndef MOCK_FAILURE_REPORTER_HPP
#define MOCK_FAILURE_REPORTER_HPP
#include "gmock/gmock.h"
#include "FailureReporter.hpp"
class MockFailureReporter : public FailureReporter {
public:
MOCK_METHOD1(fail, void(const char*));
};
#endif
DummyTest.cpp
#include "gtest/gtest.h"
#include "MockFailureReporter.hpp"
TEST(DummyTest, dummy) {
new MockFailureReporter();
SUCCEED();
}
使用
编译源代码g++ -c DummyTest.cpp
g++ -c FailureReporterTest.cpp
并将它们与
相关联g++ DummyTest.o FailureReporterTest.o -pthread -lgtest -lgmock -lgmock_main
生成一个未通过failMethod测试的a.out可执行文件,同时将它们与
链接g++ FailureReporterTest.o DummyTest.o -pthread -lgtest -lgmock -lgmock_main
生成一个可执行两次测试的a.out可执行文件。为什么呢?
答案 0 :(得分:2)
class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
/* code */
创建inline
的隐式FailureReporter::fail
实现。
inline
个函数。如果链接器看到两个具有相同名称和类型的inline
函数,它将以静默方式丢弃一个。如果它们实际上不相同,那么您的程序就会形成,并且不需要诊断。
当您仅在一个编译单元中重新定义FAIL()
并将其与其他编辑单元链接时,最终会得到FailureReporter::fail
的两个定义。它们链接,并且未定义的行为结果。在您的情况下,您可以在两种情况下运行其中一个,确定链接器选择丢弃内联冲突的任意规则。这看起来像'保留我看到的第一个'。