简单示例(Test宏)

  1. #include "gtest/gtest.h"
  2. // 此函数用于判断入参是否为正整数:如果是,则返回0;否则,返回-1
  3. int Positive(int nNum) {
  4. if (nNum > 0) {
  5. return 0;
  6. } else {
  7. return -1;
  8. }
  9. }
  10. // 测试入参2是否为正整数
  11. /* Test()宏
  12. 1. 第一个参数:是Test Case的名称
  13. 2. 第二个参数:隶属于第一个Test Case的参数,即Test的名称
  14. 一个测试的完整名称包括TestCase名称及Test名称
  15. 不同Test Case的Test名称可以相同
  16. */
  17. TEST(PositiveTest, HandlesPositiveInput)
  18. {
  19. EXPECT_EQ(Positive(2), 0);
  20. }
  21. // 测试入参0是否为正整数
  22. TEST(PositiveTest, HandlesZeroInput)
  23. {
  24. EXPECT_EQ(Positive(0), -1);
  25. }
  26. // 测试入参-2是否为正整数
  27. TEST(PositiveTest, HandlesNegativeInput)
  28. {
  29. EXPECT_EQ(Positive(-2), -1);
  30. }
  31. int main(int argc, char **argv)
  32. {
  33. // 分析gtest程序的命令行参数
  34. testing::InitGoogleTest(&argc, argv);
  35. // 调用RUN_ALL_TESTS()运行所有测试用例
  36. // main函数返回RUN_ALL_TESTS()的运行结果
  37. return RUN_ALL_TESTS();
  38. }

在上述代码中,我们编写了三个 test,分别为:HandlesPositiveInput、HandlesZeroInput 和 HandlesNegativeInput,这三个 test 都属于同一个 test case(PositiveTest)。

多个Test用同一套数据(TEST_F宏)

  1. #include "gtest/gtest.h"
  2. //当我们想让多个test使用同一套数据配置时,就需要用到Test Fixtures
  3. //创建fixture的具体方法
  4. class FooTest: public testing::Test { //定义测试类FooTest
  5. //1. 创建一个类,并继承testing::test,并将该类中的一些内容声明为protected类型,以便在子类中进行访问
  6. protected:
  7. //2. 根据实际情况,编写默认的构造函数或Setup函数,来为每个test准备所需内容
  8. void SetUp() {
  9. // 这里的代码将在构造函数之后立即被调用(就在每个测试之前)
  10. m_nTarget = 5;
  11. }
  12. //3. 根据实际情况,编写默认的析构函数或TearDown函数,来释放Setup()中分配的资源
  13. void TearDown() {
  14. //这里的代码将在每次测试之后立即被调用(就在析构函数之前)
  15. }
  16. public:
  17. int IsLargeThan5(const int & nNum);
  18. int m_nTarget;
  19. };
  20. // 判断入参是否大于5:如果是,则返回0;否则返回-1
  21. int FooTest::IsLargeThan5(const int & nNum)
  22. {
  23. if (nNum > m_nTarget)
  24. {
  25. return 0;
  26. }
  27. else
  28. {
  29. return -1;
  30. }
  31. }
  32. //4. 根据实际情况,定义test共享的子程序
  33. //当使用fixture时,我们使用TEST_F()宏代替TEST()宏,TEST_F()允许我们在test fixture中访问对象和子程序
  34. //TEST_F()的第一个参数(即 test case 的名称)必须是test fixture类的名字(即FooTest)
  35. TEST_F(FooTest, HandlesInput6)
  36. EXPECT_EQ(IsLargeThan5(6), 0);
  37. }
  38. TEST_F(FooTest, HandlesInput5) {
  39. EXPECT_EQ(IsLargeThan5(5), 0);
  40. }
  41. TEST_F(FooTest, HandlesInput4) {
  42. EXPECT_EQ(IsLargeThan5(4), -1);
  43. }
  44. int main(int argc, char **argv) {
  45. // 分析gtest程序的命令行参数
  46. ::testing::InitGoogleTest(&argc, argv);
  47. // 调用RUN_ALL_TESTS()运行所有测试用例
  48. // main函数返回RUN_ALL_TESTS()的运行结果
  49. return RUN_ALL_TESTS();
  50. }

TEST_F的工作原理:

  1. 对于TEST_F()定义的每个test,googletest 将会在运行时创建一个新的test fixture
  2. 并立即通过 SetUp() 对其进行初始化,然后运行 test
  3. 之后通过调用 TearDown() 进行数据清理,最后删除 test fixture。

需要注意的是

  1. 同一个 test case 中不同的 test 具有不同的 test fixture 对象
  2. 并且 googletest 每次创建新的 test fixture 前都会先删除之前的 test fixture
  3. 多个 test 不会重用相同的 test fixture,某个 test 对 fixture 进行的修改对其他 test 无影响

在上述代码中,我们编写了三个 test,分别为:HandlesInput6、HandlesInput5 和 HandlesInput4,这三个 test 都属于同一个 test case(即 FooTest)。注意,这里的 test case(即 FooTest) 一定要是 test fixture 类。

上述代码中的 test 运行时,主要会进行如下操作:

  1. googletest 构造一个 FooTest 类的对象(我们称之为 f1);
  2. f1.SetUp() 函数对 f1 进行初始化;
  3. 使用对象 f1,运行第一个 test(HandlesInput6);
  4. f1.TearDown() 在 test 完成后,进行清理工作;
  5. 对象 f1 被析构。
  6. 上述5个步骤在另一个 FooTest 类的对象(如 f2)中重复,此次会运行 HandlesInput5。

    Google Test

    main()

    编写 main() 函数时,要返回 RUN_ALL_TESTS() 宏的值。

main() 函数中的 ::testing::InitGoogleTest() 函数将会解析命令行中的 googletest 参数,它允许用户通过多样的命令行参数来控制测试程序的行为(即定制命令行参数的功能)。需要注意的是,::testing::InitGoogleTest() 函数必须要在 RUN_ALL_TESTS() 之前调用,否则对应的 flag 可能不会被正常地初始化。

RUN_ALL_TESTS()

在上面的代码示例中我们能够看到,调用 Test 的操作是通过 RUN_ALL_TESTS() 宏完成的。

  1. RUN_ALL_TESTS() 宏在所有 test 都成功时,返回0;否则返回1
  2. 需要注意的是,RUN_ALL_TESTS() 会运行所有关联的 test,这些 test 可以来自不同的 test case,甚至不同的源文件

当我们调用 RUN_ALL_TESTS() 宏的时候,会进行以下操作:

  1. 保存所有 googletest flag 的状态;
  2. 为第一个 test 创建一个 test fixture 对象;
  3. 通过 SetUp() 对上一步创建的 test fixture 对象进行初始化;
  4. 使用 test fixture 对象运行 test;
  5. 通过 TearDown() 清理 fixture;
  6. 删除 fixture;
  7. 还原所有 googletest flag 的状态;
  8. 为下一个 test 重复上述操作,直到所有的 test 执行完成。

注意:main() 函数必须要返回 RUN_ALL_TESTS() 宏的结果。同时,RUN_ALL_TESTS() 只能运行一次,多次调用会与 googletest 的一些功能(如 thread-safe death tests)发生冲突。

Google Test 是线程安全的,其线程安全特性要依赖 pthreads 库。

运行指定测试

  1. int main(int argc, char **argv) {
  2. ::testing::InitGoogleTest(&argc, argv);
  3. ::testing::GTEST_FLAG(filter) = "Test_Cases1*";
  4. return RUN_ALL_TESTS();
  5. }

参考文章

  1. Google Test介绍(一)
  2. Google Test介绍(二)
  3. 在 Visual Studio 中编写 C/C++ 单元测试