[英]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
。
讓我們首先提到的靜態類成員SetUpTestCase
和TearDownTestCase
已分別更名為SetUpTestSuite
和TearDownTestSuite
自googletest V1.8。 請參閱注意命名法
他們這樣做是因為名稱SetUpTestCase
和TearDownTestCase
具有嚴重的誤導性。 他們建議在從定義它們的夾具類派生的測試的每種情況下運行的函數,它們不是。 實際上, SetUpTestCase
是在從夾具派生的所有測試中的第一個之前運行的(如果您安裝了較舊的 googletest,仍然如此),並且TearDownTestCase
是在從夾具派生的所有測試中的最后一個之后運行的。
從 googletest 1.8 開始,所有源自夾具的測試——我們自然稱之為測試用例——統稱為測試套件; 因此,在所有這些之前運行的設置函數現在稱為SetUpTestSuite
而在它們之后運行的拆卸函數稱為TearDownTestSuite
。 我將堅持使用新的改進名稱,因為我擁有 googletest 的最新版本。
看看這個 gtest 代碼,它演示了夾具的構造函數和析構函數、 SetUp
和TearDown
、 SetUpTestSuite
和TearDownTestSuite
的調用順序:
文件
#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
構造函數。 (但它是空的。)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_Test
和fixture_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()?
如果您想確保夾具中的測試用例具有相同的設置,您應該實現SetUp
和TearDown
方法(注意案例)
您的InjectorTest
夾具僅構建一次,但SetUp
步驟(或TearDown
步驟)將在您的測試用例執行之前(或之后)運行。
構造函數應該只處理應該只做一次的事情(如果有的話),你想為你的測試用例強制執行的任何行為都應該在這兩種方法中。 在您的示例中,如果m_reader
成員可以在您的所有測試用例之間共享,您可以像您一樣在構造函數中對其進行初始化。
總而言之,這是將要運行的操作序列:
InjectorTest::InjectorTest()
:構建測試夾具InjectorTest::SetUp()
: 測試用例的設置InjectorTest::CreateReaderAndGetTopic
)InjectorTest::TearDown()
:為下一個案例撤消設置InjectorTest::~InjectorTest()
: 銷毀夾具對象
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.