簡體   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

我的問題是

1) 當我運行測試用例CreateReaderAndGetTopic ,InjectorTest 的Constructor在執行測試用例之前被調用了嗎? 還是應該明確調用?

2) 我的類InjectorTest應該有一個構造函數還是應該將構造函數中的代碼移到SetUpTestCase

讓我們首先提到的靜態類成員SetUpTestCaseTearDownTestCase已分別更名為SetUpTestSuiteTearDownTestSuite自googletest V1.8。 請參閱注意命名法

他們這樣做是因為名稱SetUpTestCaseTearDownTestCase具有嚴重的誤導性。 他們建議在從定義它們的夾具類派生的測試的每種情況下運行的函數,它們不是。 實際上, SetUpTestCase是在從夾具派生的所有測試中的第一個之前運行(如果您安裝了較舊的 googletest,仍然如此),並且TearDownTestCase在從夾具派生的所有測試中的最后一個之后運行的。

從 googletest 1.8 開始,所有源自夾具的測試——我們自然稱之為測試用例——統稱為測試套件 因此,在所有這些之前運行的設置函數現在稱為SetUpTestSuite而在它們之后運行的拆卸函數稱為TearDownTestSuite 我將堅持使用新的改進名稱,因為我擁有 googletest 的最新版本。

看看這個 gtest 代碼,它演示了夾具的構造函數和析構函數、 SetUpTearDownSetUpTestSuiteTearDownTestSuite的調用順序:

文件

#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_One_Test實例調用fixture::Setup()
  • 它通過fixture_One_Test實例調用fixture_One_Test::TestBody() ,該實例執行測試用例的payload。
  • 它通過fixture_One_Test實例調用調用fixture::TearDown()
  • 它破壞了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 的構造函數? 還是應該明確調用?

必須調用InjectorTest構造函數來構造類CreateReaderAndGetTopic_InjectorTest_Test的實例,Googletest 會為您完成該實例。 它在SetUp()之前調用,后者在TestBody()之前TestBody() ,后者是測試用例的有效載荷。

我的類 InjectorTest 是否應該有一個構造函數...

InjectorTest將有一個構造函數,默認情況下或由您定義; 所以你想知道是否應該定義一個。

如果您有某事需要為每個測試用例重新做准備,那么您應該定義一個,並且最好在每個測試用例的SetUp()之前完成。

...還是應該將構造函數中的代碼移至 SetUpTestCase?

您在構造函數中的代碼:

m_reader = CreateReader();

應該搬出來SetUpTestCase -又名SetUpTestSuite -如果它是什么並不需要在所有的測試案例,但需要准備重新做只是所有測試用例之前進行一次InjectorTest

就目前而言,您不能將該構造函數代碼移動到SetUpTestSuite因為它初始化了InjectorTest的非靜態類成員m_reader 但是您實際上是否需要或希望CreateReader()為每個測試用例創建一個新的XMLReader 只有你能決定。

如果您確實想為每個測試用例創建一個新的閱讀器,那么您將面臨在構造函數或SetUp()中創建它的選擇。 這里可以參考Googletest FAQ的指導, 我應該使用測試夾具的構造函數/析構函數還是SetUp()/TearDown()?

如果您想確保夾具中的測試用例具有相同的設置,您應該實現SetUpTearDown方法(注意案例)

您的InjectorTest夾具僅構建一次,但SetUp步驟(或TearDown步驟)將在您的測試用例執行之前(或之后)運行。

構造函數應該只處理應該只做一次的事情(如果有的話),你想為你的測試用例強制執行的任何行為都應該在這兩種方法中。 在您的示例中,如果m_reader成員可以在您的所有測試用例之間共享,您可以像您一樣在構造函數中對其進行初始化。

總而言之,這是將要運行的操作序列:

  1. InjectorTest::InjectorTest() :構建測試夾具
  2. 對於每個測試用例:
    1. InjectorTest::SetUp() : 測試用例的設置
    2. 運行測試用例(在您的示例InjectorTest::CreateReaderAndGetTopic
    3. InjectorTest::TearDown() :為下一個案例撤消設置
  3. InjectorTest::~InjectorTest() : 銷毀夾具對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM