Reputation: 15010
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? 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
.
Upvotes: 1
Views: 7480
Reputation: 61515
Let's mention first that the static class members SetUpTestCase
and
TearDownTestCase
have been renamed respectively to SetUpTestSuite
and TearDownTestSuite
since googletest v1.8. See Beware of the nomenclature
They did that because the names SetUpTestCase
and TearDownTestCase
were grossly
misleading. 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.
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;
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
.
I will stick with the new improved names as I have the latest rev of googletest.
Look at this gtest code that demonstrates the calling order of a fixture's
constructor and destructor, SetUp
and TearDown
, SetUpTestSuite
and TearDownTestSuite
:
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:
...
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
:
fixture_One_Test
- which by inheritance, is
a new instance of fixture
.fixture
constructor is called.fixture_One_Test
constructor is called. (But it's empty.)fixture::Setup()
through the fixture_One_Test
instance.fixture_One_Test::TestBody()
through the fixture_One_Test
instance,
which executes the payload of the test case.fixture::TearDown()
through the fixture_One_Test
instance.fixture_One_Test
instance, which -fixture_One_Test
destructor, which simply -fixture
destructor.Similarly for fixture_Two_Test
and fixture_Three_Test
.
And just before all of that, googletest calls fixture::SetupTestSuite
, if it's
is defined.
And just after all of that, googletest calls fixture::TearDownTestSuite
, if it's
is defined.
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. The constructor,
destructor, SetUp()
and TearDown()
each run 3 times = the number of test cases
in the test suite.
So to your two questions:
When I run the test case CreateReaderAndGetTopic does the Constructor of InjectorTest gets called before executing the test case? 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. It is called before SetUp()
, which is called before TestBody()
, which is the payload of the test case.
Should my class InjectorTest have a constructor...
InjectorTest
will have a constructor, either by default or as defined by you; 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.
... or should the code inside the constructor be moved to SetUpTestCase?
The code you have inside the constructor:
m_reader = CreateReader();
should be moved out to SetUpTestCase
- a.k.a 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
.
As it stands, you cannot move that constructor code into SetUpTestSuite
because it initializes a non-static
class member of InjectorTest
, m_reader
. But do you in fact need or want a new XMLReader
to be created by CreateReader()
for each test case? 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()
. Here you can be guided by the
Googletest FAQ Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()?
Upvotes: 4
Reputation: 6086
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)
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.
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.
To sumup, here is the sequence of operations that will be run:
InjectorTest::InjectorTest()
: test fixture is constructedInjectorTest::SetUp()
: setup for test caseInjectorTest::CreateReaderAndGetTopic
)InjectorTest::TearDown()
: setup is undone for next caseInjectorTest::~InjectorTest()
: destruction of the fixture object Upvotes: 2