в настоящее время я смотрю на саморегистрационные классы (да, я также читал о проблемах, связанных с ними, но я все еще думаю, что у меня есть вариант использования для этого) и закончил UO с googletest, который использует эту технику для создания и зарегистрировать новые тесты с помощью макроса TEST(test_suite_name, test_name)
. См. Следующие определения:
в gtest.h
#define GTEST_TEST(test_suite_name, test_name) \
GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
::testing::internal::GetTestTypeId())
#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
в gtest-internal.h
// Helper macro for defining tests.
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public parent_class { \
public: \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
\
private: \
void TestBody() override; \
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
}; \
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)::test_info_ = \
::testing::internal::MakeAndRegisterTestInfo(...)\
Как следует из названия MakeAndRegisterTestInfo
, чьи аргументы я опущено выше для краткости, создает новый экземпляр TestInfo
и регистрирует его в одноэлементном объекте UnitTest
. Вот цитата из документации googletest :
TEST () и TEST_F () неявно регистрируют свои тесты в googletest. Таким образом, в отличие от многих других C ++ каркасов тестирования, вам не нужно повторно перечислять все определенные тесты, чтобы запустить их.
После определения ваших тестов вы можете запустить их с помощью RUN_ALL_TESTS (), которая возвращает 0, если все тесты пройдены успешно, или 1 в противном случае. Обратите внимание, что RUN_ALL_TESTS () запускает все тесты в вашем блоке ссылок - они могут быть из разных наборов тестов или даже из разных исходных файлов.
Как я понимаю, я могу написать несколько тестов через макрос TEST(...)
в нескольких единицах перевода, и все они будут зарегистрированы. Это правильно? Если это так, то возникает еще один вопрос:
Каково точное определение «блока ссылок»? Я искал этот термин, но полученные результаты не были действительно удовлетворительными.
Как гарантируется, что регистрация произойдет до запуска gtest_main()
, который запускает все зарегистрированные тесты (я знаю, что рекомендуется создать свой собственный main()
)? Вот почему я спрашиваю (см. Этот ответ ):
C ++ явно позволяет инициализировать нелокальные переменные после запуска main; единственное ограничение заключается в том, что они должны быть инициализированы перед выполнением любого кода из файла, который их определяет.
То есть, если исходный файл определяет новый тест с помощью TEST(...)
, как гарантируется, что переменная-член stati c ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name,test_name)::test_info_
инициализируется и тест зарегистрировано до запуска всех тестов?
Чтобы уточнить, я хочу понять, как и почему это работает или какие неправильные представления существуют с моей стороны. Я не ищу плюсы и минусы саморегистрации.
Спасибо за вашу помощь.
Всего наилучшего, Стефан