Google Test中的测试类的构造方法

时间:2019-03-01 08:21:36

标签: c++ googletest

namespace {

using namespace std;
// Declare the google test case
class InjectorTest : public ::testing::Test {

std::shared_ptr<MyData>> m_reader;
public:
    static void SetUpTestCase() {

    }
    static void TearDownTestCase() {

    }

    InjectorTest()
    {
        //Create Reader code here !!!!
        m_reader = CreateReader();

    }
    std::shared_ptr<DDSTopicReader<MyData>> getXMLReader() {

        return m_reader;
    }
};

TEST_F(InjectorTest, CreateReaderAndGetTopic) {
        auto reader = getXMLReader();
        std::string topic_name = reader->getTopicName();
        EXPECT_EQ(topic_name, "test_topic");
}
}; // anonymous namespace

我的问题是

1)当我运行测试用例CreateReaderAndGetTopic时,是否在执行测试用例之前调用了InjectorTest的Constructor?还是应该明确地调用它?

2)我的类InjectorTest应该具有构造函数,还是应该将构造函数内的代码移至SetUpTestCase

2 个答案:

答案 0 :(得分:1)

如果要确保夹具中的测试用例具有相同的设置,则应实现SetUpTearDown方法(请注意情况)

您的InjectorTest固定装置仅构造一次,但是SetUp步骤(分别为TearDown步骤)将在测试用例执行之前(之后)运行。 / p>

构造函数应该只处理只能完成一次的事情(如果有的话),要为测试用例强制执行的任何行为都应在这两种方法中进行。在您的示例中,如果m_reader成员可以在您所有的测试用例中共享,则可以像在构造函数中一样对其进行初始化。

总而言之,这是将要运行的操作序列:

  1. InjectorTest::InjectorTest():测试夹具已构建
  2. 对于每个测试用例:
    1. InjectorTest::SetUp():设置测试用例
    2. 运行测试用例(在您的示例InjectorTest::CreateReaderAndGetTopic中)
    3. InjectorTest::TearDown():在下一种情况下将撤消设置
  3. InjectorTest::~InjectorTest():销毁灯具对象

答案 1 :(得分:0)

让我们首先提到静态类成员SetUpTestCaseTearDownTestCase已分别重命名为SetUpTestSuite and TearDownTestSuite 从googletest v1.8开始。参见Beware of the nomenclature

之所以这样做是因为SetUpTestCaseTearDownTestCase这两个名字很粗 误导。他们建议将在测试的每个情况下运行的功能 从定义它们的夹具类派生而来,不是。 SetUpTestCase实际上是在从固定装置派生的所有测试中的第一个测试之前运行的。 (如果安装的是旧版googletest,则仍然是),以及TearDownTestCase 在夹具进行的所有测试中的最后一个测试之后运行了。

从googletest 1.8开始,所有源自固定装置的测试-我们将 自然地将其称为 test case -被统称为 test suite ; 因此,在所有功能之前运行的设置功能现在称为SetUpTestSuite 然后运行它们的拆解函数称为TearDownTestSuite。 我将使用经过改进的新名称,因为我拥有最新的googletest版本。

查看此gtest代码,该代码演示了灯具的调用顺序 构造函数和析构函数SetUpTearDownSetUpTestSuiteTearDownTestSuite

gtester.cpp

#include <gtest/gtest.h>
#include <iostream>

struct fixture : ::testing::Test
{
    fixture() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    ~fixture() override {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    void SetUp() override {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    void TearDown() override {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    static void SetUpTestSuite() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }

    static void TearDownTestSuite() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
};

TEST_F(fixture, One) {
    ASSERT_EQ(1,1);
}

TEST_F(fixture, Two) {
    ASSERT_NE(1,0);
}

TEST_F(fixture, Three) {
    ASSERT_LT(1,2);
}

如果您对此进行预处理,则可以在幕后获得一些有用的信息。 文件(最好是通过漂亮的打印机进行传输),然后查看结果:

$   g++ -E -P gtester.cpp | clang-format > gtester.ii

gtester.ii中,您可以找到:

...
class fixture_One_Test : public fixture {
public:
  fixture_One_Test() {}
private:
  virtual void TestBody();
  static ::testing::TestInfo *const test_info_ __attribute__((unused));
  fixture_One_Test(fixture_One_Test const &) = delete;
  void operator=(fixture_One_Test const &) = delete;
};
::testing::TestInfo *const fixture_One_Test::test_info_ =
    ::testing::internal::MakeAndRegisterTestInfo(
        "fixture", "One", nullptr, nullptr,
        ::testing::internal::CodeLocation("gtester.cpp", 31),
        (::testing::internal::GetTypeId<fixture>()),
        ::testing::internal::SuiteApiResolver<fixture>::GetSetUpCaseOrSuite(),
        ::testing::internal::SuiteApiResolver<
            fixture>::GetTearDownCaseOrSuite(),
        new ::testing::internal::TestFactoryImpl<fixture_One_Test>);
void fixture_One_Test::TestBody() {
  switch (0)
  case 0:
  default:
    if (const ::testing::AssertionResult gtest_ar =
            (::testing::internal::EqHelper<
                decltype(::testing::internal::IsNullLiteralHelper(
                    1, ::testing::internal::TypeIsValidNullptrConstant<decltype(
                           1)>()))::value>::Compare("1", "1", 1, 1)))
      ;
    else
      return ::testing::internal::AssertHelper(
                 ::testing::TestPartResult::kFatalFailure, "gtester.cpp", 32,
                 gtest_ar.failure_message()) = ::testing::Message();
}
...

这就是测试用例:

TEST_F(fixture, One) {
    ASSERT_EQ(1,1);
}

在预处理后扩展为。 googletest运行测试用例fixture.One时:

  • 它构造了fixture_One_Test的新实例-通过继承,它是 fixture的新实例。
  • 调用基本的fixture构造函数。
  • 调用派生的fixture_One_Test构造函数。 (但它是空的。)
  • Googletest通过fixture::Setup()实例调用fixture_One_Test
  • 它通过fixture_One_Test::TestBody()实例调用fixture_One_Test, 执行测试用例的有效负载。
  • 它通过fixture::TearDown()实例调用fixture_One_Test
  • 它将销毁fixture_One_Test实例,该实例-
  • 调用fixture_One_Test析构函数,该析构函数简单地-
  • 调用fixture析构函数。

fixture_Two_Testfixture_Three_Test类似。

在这之前,googletest会调用fixture::SetupTestSuite(如果是) 已定义。

然后,如果是,则googletest调用fixture::TearDownTestSuite 已定义。

现在让我们看看它的作用:

$ g++ -Wall -Wextra -o gtester gtester.cpp -lgtest_main -lgtest -pthread
$ ./gtester 
Running main() from /home/imk/Downloads/googletest-master/googletest/src/gtest_main.cc
[==========] Running 3 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 3 tests from fixture
static void fixture::SetUpTestSuite()
[ RUN      ] fixture.One
fixture::fixture()
virtual void fixture::SetUp()
virtual void fixture::TearDown()
virtual fixture::~fixture()
[       OK ] fixture.One (0 ms)
[ RUN      ] fixture.Two
fixture::fixture()
virtual void fixture::SetUp()
virtual void fixture::TearDown()
virtual fixture::~fixture()
[       OK ] fixture.Two (0 ms)
[ RUN      ] fixture.Three
fixture::fixture()
virtual void fixture::SetUp()
virtual void fixture::TearDown()
virtual fixture::~fixture()
[       OK ] fixture.Three (0 ms)
static void fixture::TearDownTestSuite()
[----------] 3 tests from fixture (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests from 1 test case ran. (0 ms total)
[  PASSED  ] 3 tests.

SetUpTestSuite()TearDownTestSuite()都只运行一次。构造函数 析构函数SetUp()TearDown()分别运行3次=测试用例的数量 在测试套件中。

关于您的两个问题:

  

当我运行测试用例CreateReaderAndGetTopic时,是否在执行测试用例之前调用InjectorTest的Constructor?还是应该明确地调用它?

必须调用InjectorTest构造函数来构造类CreateReaderAndGetTopic_InjectorTest_Test的实例, Googletest为您做什么。它在SetUp()之前被调用,而TestBody()在测试用例的有效负载之前被调用。

  

我的类InjectorTest应该有一个构造函数...

InjectorTest 将具有构造函数,默认情况下或由您定义;所以你 想知道是否应该定义一个。

如果您需要做一些准备做的事,应该重新定义 对于每个测试用例,最好在每个测试用例的SetUp()之前完成。

  

...还是应该将构造函数中的代码移至SetUpTestCase?

构造函数中包含的代码:

m_reader = CreateReader();

应移至SetUpTestCase-也就是SetUpTestSuite-如果是这样的话 对于每个测试用例,都需要重新进行 not 操作,但是需要 在InjectorTest的所有测试用例之前 完成一次。

按现状,您不能将构造函数代码移动到SetUpTestSuite中,因为它会初始化非静态 InjectorTestm_reader的类成员。但是您实际上是否需要或想要一个新的XMLReaderCreateReader()为每个测试用例创建?只有你可以决定。

如果您确实想为每个测试用例创建一个新的阅读器,那么您将面临选择 在构造函数或SetUp()中创建它的过程。在这里,您可以通过 Googletest常见问题解答Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()?