如何在测试系统中自动注册测试用例?
How to auto-register test cases in a test system?
通常在测试系统中,当我们编写一个新的测试用例时,我们需要在某个地方注册测试用例,以便可以调用它。
例如在测试系统中:
TESTCASE(a,b){...}
可以映射到 void testcase_a_b() {...}
并且测试系统可以从 main 调用这些 void testcase_a_b()
、void testcase_c_d()
等中的每一个,因此 运行 所有测试用例。
在可执行文件中自动注册测试用例的方法是什么?例如,在 Google Test 中(就像其他几个测试框架一样),如果我们调用 RUN_ALL_TESTS()
它会自动执行可执行文件中以 TEST(a,b)
等开头的所有声明。
Google测试如何知道exe中存在TEST(a,b)
?我试图理解(从高级设计的角度)什么是用 C++ 实现类似系统的简单方法。其中像 TEST(a,b) 这样的宏会自动将其自身附加到有效测试用例列表中,因此它可以 运行 来自 main 而不必担心单独注册它。
通常这是通过创建全局对象来完成的,全局对象在构造时调用注册方法。这与 C++ 中普遍认为的 "good practices"(参见 https://isocpp.org/wiki/faq/ctors#static-init-order)相反,因此在尝试这样的实现之前,您应该非常精通这些问题。
无论如何,这是 googletest 使用的方法 - TEST
预处理器宏最终归结为 (gtest-internal.h):
// Helper macro for defining tests.
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
public:\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
#test_case_name, #test_name, NULL, NULL, \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
new ::testing::internal::TestFactoryImpl<\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
因此,当您使用此宏时,class 的全局实例调用 ::testing::internal::MakeAndRegisterTestInfo
并使用对应于测试用例的参数。
通常在测试系统中,当我们编写一个新的测试用例时,我们需要在某个地方注册测试用例,以便可以调用它。
例如在测试系统中:
TESTCASE(a,b){...}
可以映射到 void testcase_a_b() {...}
并且测试系统可以从 main 调用这些 void testcase_a_b()
、void testcase_c_d()
等中的每一个,因此 运行 所有测试用例。
在可执行文件中自动注册测试用例的方法是什么?例如,在 Google Test 中(就像其他几个测试框架一样),如果我们调用 RUN_ALL_TESTS()
它会自动执行可执行文件中以 TEST(a,b)
等开头的所有声明。
Google测试如何知道exe中存在TEST(a,b)
?我试图理解(从高级设计的角度)什么是用 C++ 实现类似系统的简单方法。其中像 TEST(a,b) 这样的宏会自动将其自身附加到有效测试用例列表中,因此它可以 运行 来自 main 而不必担心单独注册它。
通常这是通过创建全局对象来完成的,全局对象在构造时调用注册方法。这与 C++ 中普遍认为的 "good practices"(参见 https://isocpp.org/wiki/faq/ctors#static-init-order)相反,因此在尝试这样的实现之前,您应该非常精通这些问题。
无论如何,这是 googletest 使用的方法 - TEST
预处理器宏最终归结为 (gtest-internal.h):
// Helper macro for defining tests.
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
public:\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
#test_case_name, #test_name, NULL, NULL, \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
new ::testing::internal::TestFactoryImpl<\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
因此,当您使用此宏时,class 的全局实例调用 ::testing::internal::MakeAndRegisterTestInfo
并使用对应于测试用例的参数。