简体   繁体   English

Google Test 中测试类的构造函数

[英]Constructor for a test class in Google Test

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

My questions is我的问题是

1) When I run the test case CreateReaderAndGetTopic does the Constructor of InjectorTest gets called before executing the test case? 1) 当我运行测试用例CreateReaderAndGetTopic ,InjectorTest 的Constructor在执行测试用例之前被调用了吗? Or should it be called explictly ?还是应该明确调用?

2) Should my class InjectorTest have a constructor or should the code inside the constructor be moved to SetUpTestCase . 2) 我的类InjectorTest应该有一个构造函数还是应该将构造函数中的代码移到SetUpTestCase

Let's mention first that the static class members SetUpTestCase and TearDownTestCase have been renamed respectively to SetUpTestSuite and TearDownTestSuite since googletest v1.8.让我们首先提到的静态类成员SetUpTestCaseTearDownTestCase已分别更名为SetUpTestSuiteTearDownTestSuite自googletest V1.8。 See Beware of the nomenclature请参阅注意命名法

They did that because the names SetUpTestCase and TearDownTestCase were grossly misleading.他们这样做是因为名称SetUpTestCaseTearDownTestCase具有严重的误导性。 They suggest functions that will be run in every case of a test that is derived from the fixture class in which they are defined, which they weren't.他们建议在从定义它们的夹具类派生的测试的每种情况下运行的函数,它们不是。 SetUpTestCase was in fact run before the first of all tests derived from the fixture (and still is, if you have an older googletest installation), and TearDownTestCase was run after the last of all tests derived from the fixture.实际上, SetUpTestCase是在从夹具派生的所有测试中的第一个之前运行(如果您安装了较旧的 googletest,仍然如此),并且TearDownTestCase在从夹具派生的所有测试中的最后一个之后运行的。

As of googletest 1.8, all of the tests that derived from a fixture - which we'd naturally call its test cases - are collectively regarded as a test suite ;从 googletest 1.8 开始,所有源自夹具的测试——我们自然称之为测试用例——统称为测试套件 so the set-up function that runs before all of them is now called SetUpTestSuite and the tear-down function that runs after of them is called TearDownTestSuite .因此,在所有这些之前运行的设置函数现在称为SetUpTestSuite而在它们之后运行的拆卸函数称为TearDownTestSuite I will stick with the new improved names as I have the latest rev of googletest.我将坚持使用新的改进名称,因为我拥有 googletest 的最新版本。

Look at this gtest code that demonstrates the calling order of a fixture's constructor and destructor, SetUp and TearDown , SetUpTestSuite and TearDownTestSuite :看看这个 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);
}

You can get a useful peek under the hood if you just preprocess this file (and preferably, pipe through a pretty-printer) and look at what comes out:如果你只是预处理这个文件(最好是通过一个漂亮的打印机)并查看结果,你可以在引擎盖下获得有用的窥视:

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

In gtester.ii you'll be able to find: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();
}
...

That is what the test case:这就是测试用例:

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

expands to after preprocessing.扩展为预处理后。 When googletest runs test case fixture.One :当googletest运行测试用例fixture.One

  • It constructs a new instance of fixture_One_Test - which by inheritance, is a new instance of fixture .它构造了一个新的fixture_One_Test实例——通过继承,它是一个新的fixture实例。
  • The base fixture constructor is called.调用基本fixture构造函数。
  • The derived fixture_One_Test constructor is called.调用派生的fixture_One_Test构造函数。 (But it's empty.) (但它是空的。)
  • Googletest calls fixture::Setup() through the fixture_One_Test instance. Googletest 通过fixture_One_Test实例调用fixture::Setup()
  • It calls fixture_One_Test::TestBody() through the fixture_One_Test instance, which executes the payload of the test case.它通过fixture_One_Test实例调用fixture_One_Test::TestBody() ,该实例执行测试用例的payload。
  • It calls calls fixture::TearDown() through the fixture_One_Test instance.它通过fixture_One_Test实例调用调用fixture::TearDown()
  • It destroys the fixture_One_Test instance, which -它破坏了fixture_One_Test实例,其中 -
  • Calls the fixture_One_Test destructor, which simply -调用fixture_One_Test析构函数,它只是 -
  • Calls the fixture destructor.调用fixture析构函数。

Similarly for fixture_Two_Test and fixture_Three_Test .类似的fixture_Two_Testfixture_Three_Test

And just before all of that, googletest calls fixture::SetupTestSuite , if it's is defined.就在这之前,googletest 调用fixture::SetupTestSuite ,如果它被定义了。

And just after all of that, googletest calls fixture::TearDownTestSuite , if it's is defined.就在这一切之后, googletest 调用fixture::TearDownTestSuite ,如果它被定义了。

Now let's see that in action:现在让我们看看它的实际效果:

$ 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() and TearDownTestSuite() each run just once. SetUpTestSuite()TearDownTestSuite()每个只运行一次。 The constructor, destructor, SetUp() and TearDown() each run 3 times = the number of test cases in the test suite.构造函数、析构函数、 SetUp()TearDown()各运行 3 次 = 测试套件中的测试用例数。

So to your two questions:所以你的两个问题:

When I run the test case CreateReaderAndGetTopic does the Constructor of InjectorTest gets called before executing the test case?当我运行测试用例 CreateReaderAndGetTopic 时,是否在执行测试用例之前调用了 InjectorTest 的构造函数? Or should it be called explictly ?还是应该明确调用?

The InjectorTest constructor is necessarily called to construct an instance of the class CreateReaderAndGetTopic_InjectorTest_Test , which Googletest does for you.必须调用InjectorTest构造函数来构造类CreateReaderAndGetTopic_InjectorTest_Test的实例,Googletest 会为您完成该实例。 It is called before SetUp() , which is called before TestBody() , which is the payload of the test case.它在SetUp()之前调用,后者在TestBody()之前TestBody() ,后者是测试用例的有效载荷。

Should my class InjectorTest have a constructor...我的类 InjectorTest 是否应该有一个构造函数...

InjectorTest will have a constructor, either by default or as defined by you; InjectorTest将有一个构造函数,默认情况下或由您定义; so you're wondering whether you should define one.所以你想知道是否应该定义一个。

You should define one if you have something to do that needs to be done anew in preparation for each test case, and that had better be done before the SetUp() for each test case.如果您有某事需要为每个测试用例重新做准备,那么您应该定义一个,并且最好在每个测试用例的SetUp()之前完成。

... or should the code inside the constructor be moved to SetUpTestCase? ...还是应该将构造函数中的代码移至 SetUpTestCase?

The code you have inside the constructor:您在构造函数中的代码:

m_reader = CreateReader();

should be moved out to SetUpTestCase - aka SetUpTestSuite - if it is something that does not need to be done anew in preparation for each test case but needs to be done once just before all test cases of InjectorTest .应该搬出来SetUpTestCase -又名SetUpTestSuite -如果它是什么并不需要在所有的测试案例,但需要准备重新做只是所有测试用例之前进行一次InjectorTest

As it stands, you cannot move that constructor code into SetUpTestSuite because it initializes a non-static class member of InjectorTest , m_reader .就目前而言,您不能将该构造函数代码移动到SetUpTestSuite因为它初始化了InjectorTest的非静态类成员m_reader But do you in fact need or want a new XMLReader to be created by CreateReader() for each test case?但是您实际上是否需要或希望CreateReader()为每个测试用例创建一个新的XMLReader Only you can decide.只有你能决定。

If you do want to create a new reader for each test case, then you face the choice of creating it in the constructor or in SetUp() .如果您确实想为每个测试用例创建一个新的阅读器,那么您将面临在构造函数或SetUp()中创建它的选择。 Here you can be guided by the Googletest FAQ Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()?这里可以参考Googletest FAQ的指导, 我应该使用测试夹具的构造函数/析构函数还是SetUp()/TearDown()?

If you want to make sure your test cases in a fixture have the same setup, you should implement the SetUp and TearDown methods (notice the case)如果您想确保夹具中的测试用例具有相同的设置,您应该实现SetUpTearDown方法(注意案例)

Your InjectorTest fixture only gets constructed once, but the SetUp step (resp. the TearDown step) will be run before (resp. after) your test case is executed.您的InjectorTest夹具仅构建一次,但SetUp步骤(或TearDown步骤)将在您的测试用例执行之前(或之后)运行。

The constructor should only deal with things that should be only done once (if any), any behavior you want to enforce for your test cases should go in these 2 methods.构造函数应该只处理应该只做一次的事情(如果有的话),你想为你的测试用例强制执行的任何行为都应该在这两种方法中。 In your example, if the m_reader member can be shared across all your test cases, you can initialize it in the constructor like you did.在您的示例中,如果m_reader成员可以在您的所有测试用例之间共享,您可以像您一样在构造函数中对其进行初始化。

To sumup, here is the sequence of operations that will be run:总而言之,这是将要运行的操作序列:

  1. InjectorTest::InjectorTest() : test fixture is constructed InjectorTest::InjectorTest() :构建测试夹具
  2. For each test case:对于每个测试用例:
    1. InjectorTest::SetUp() : setup for test case InjectorTest::SetUp() : 测试用例的设置
    2. Test case is run (in your example InjectorTest::CreateReaderAndGetTopic )运行测试用例(在您的示例InjectorTest::CreateReaderAndGetTopic
    3. InjectorTest::TearDown() : setup is undone for next case InjectorTest::TearDown() :为下一个案例撤消设置
  3. InjectorTest::~InjectorTest() : destruction of the fixture object InjectorTest::~InjectorTest() : 销毁夹具对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM