C++ 如何在测试系统中自动注册测试用例?

C++ 如何在测试系统中自动注册测试用例?,c++,function,unit-testing,googletest,C++,Function,Unit Testing,Googletest,通常在测试系统中,当我们编写一个新的测试用例时,我们需要在某个地方注册测试用例,以便调用它 例如,在测试系统中: TESTCASE(a,b){…}可以从main映射到void TESTCASE\u a\u b(){…},测试系统可以调用这些void TESTCASE\u a\u b(),void TESTCASE\u c\u d()等,从而运行所有测试用例 在可执行文件中自动注册测试用例的方法是什么?例如,在Google Test中(就像其他几个测试框架一样),如果我们调用RUN\u ALL\u

通常在测试系统中,当我们编写一个新的测试用例时,我们需要在某个地方注册测试用例,以便调用它

例如,在测试系统中:
TESTCASE(a,b){…}
可以从main映射到
void TESTCASE\u a\u b(){…}
,测试系统可以调用这些
void TESTCASE\u a\u b()
void TESTCASE\u c\u d()
等,从而运行所有测试用例

在可执行文件中自动注册测试用例的方法是什么?例如,在Google Test中(就像其他几个测试框架一样),如果我们调用
RUN\u ALL\u TESTS()
,它会自动执行可执行文件中以
Test(a,b)
等开头的所有声明


Google Test如何知道exe中是否存在
Test(a,b)
?我试图理解(从高层次的设计角度),什么是实现C++中的那种系统的简单方法。类似宏的测试(a,b)自动将自己附加到有效测试用例列表中,这样就可以从main运行,而不用担心单独注册它。

通常,这是通过创建全局对象来完成的,在构建它们时调用注册方法。这与通常认为的C++中的“好实践”相反,因此在尝试这样的实现之前,您应该精通这些问题。 无论如何,这是Google测试使用的方法-预处理器宏
TEST
最终归结为以下内容(gtest internal.h):

//用于定义测试的Helper宏。
#定义GTEST_测试(测试案例名称、测试名称、父类、父id)\
类GTEST\u TEST\u类名称(TEST\u case\u NAME,TEST\u NAME):公共父类{\
公众:\
GTEST_TEST_CLASS_NAME(TEST_case_NAME,TEST_NAME)({}\
私人:\
虚拟void TestBody()\
静态::测试::TestInfo*常量测试信息测试属性未使用\
GTEST不允许复制和分配_(\
GTEST_TEST_CLASS_NAME_(TEST_case_NAME,TEST_NAME))\
};\
\
::测试::TestInfo*常量GTEST\u测试类\u名称(测试案例\u名称,测试名称)\
::测试信息=\
::测试::内部::MakeAndRegisterTestInfo(\
#测试用例名称,#测试名称,NULL,NULL\
(家长id)\
父类::SetUpTestCase\
父类::TearDownTestCase\
新::测试::内部::TestFactoryImpl)\
void GTEST\u TEST\u CLASS\u NAME(TEST\u case\u NAME,TEST\u NAME)::TestBody()

因此,当您使用这个宏时,一个类的全局实例调用
::testing::internal::MakeAndRegisterTestInfo
,其参数对应于测试用例。

谢谢您的回复。那么,在您看来,设计一个不使用静态初始化就能获得相同结果的系统的好方法是什么呢?或者,没有其他方法吗?如果您希望在调用
main
之前发生某些事情,则必须依赖静态初始化。很明显,谷歌选择了这样做——我只是警告,必须非常小心地实现这一点——因为它将很容易创建一个不稳定的实现,如C++ FAQ中所描述的。您的帮助非常值得赞赏:谢谢。
// 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()