Сначала отметим, что статические члены класса SetUpTestCase
и TearDownTestCase
были переименованы соответственно в SetUpTestSuite
и TearDownTestSuite
начиная с googletest v1.8.См. Остерегайтесь номенклатуры
Они сделали это, потому что имена SetUpTestCase
и TearDownTestCase
вводили в заблуждение.Они предлагают функции, которые будут запускаться в каждом случае теста , который получен из класса фикстуры, в котором они определены, а это не так.SetUpTestCase
фактически выполнялся до первого из всех тестов, полученных из приспособления (и остается, если у вас более старая установка googletest), а TearDownTestCase
запускался после последнего извсе тесты, полученные из прибора.
Начиная с googletest 1.8, все тесты, которые были получены из прибора - который мы естественным образом назвали бы тестовыми примерами - собраны вместекак набор тестов ;таким образом, функция настройки, которая запускается до того, как все они теперь называются SetUpTestSuite
, а функция разрыва, которая выполняется после них, называется TearDownTestSuite
.Я буду придерживаться новых улучшенных имен, так как у меня последняя версия googletest.
Посмотрите на этот код gtest, который демонстрирует порядок вызова конструктора и деструктора прибора, SetUp
и TearDown
, SetUpTestSuite
и 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);
}
Вы можете получить полезный взгляд под капотом, если вы просто предварительно обработаете этот файл (и желательно, pipe)через симпатичный принтер) и посмотрите, что получится:
$ 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
. - Base
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_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()
, который является полезной нагрузкой тестового примера.
Если у моего класса InjectorTest есть конструктор ...
InjectorTest
будет иметь конструктор, либо по умолчанию, либо как вы определили;поэтому вы задаетесь вопросом, следует ли вам определять один.
Вы должны определить один, если у вас есть что-то, что нужно сделать заново при подготовке к каждому тестуcase, и это лучше сделать перед SetUp()
для каждого тестового случая.
... или код внутри конструктора должен быть перемещен в SetUpTestCase?
Код, который вы имеете внутри конструктора:
m_reader = CreateReader();
должен быть перемещен в SetUpTestCase
- иначе SetUpTestSuite
- если это что-то, что не нужно сделать зановов подготовке к каждому тесту, но это должно бытьвыполняется один раз непосредственно перед во всех тестовых случаях InjectorTest
.
В существующем состоянии вы не можете переместить этот код конструктора в SetUpTestSuite
, поскольку он инициализирует нестатический член класса InjectorTest
, m_reader
.Но вам действительно нужно или вы хотите, чтобы CreateReader()
создавал новый XMLReader
для каждого теста?Только вы можете решить.
Если вы хотите создать новое средство чтения для каждого тестового случая, тогда перед вами стоит выбор - в конструкторе или в SetUp()
.Здесь вы можете руководствоваться Googletest FAQ Должен ли я использовать конструктор / деструктор тестового устройства или SetUp () / TearDown ()?