设为首页 加入收藏

TOP

C++ 测试框架 GoogleTest 初学者入门篇 丙(一)
2023-07-23 13:33:12 】 浏览:107
Tags:GoogleTest

*以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/RIztusI3uKRnoHVf0sloeg

开发者虽然主要负责工程里的开发任务,但是每个开发完毕的功能都是需要开发者自测通过的,所以经常会听到开发者提起单元测试的话题。那么今天我就带大伙一起来看看大名鼎鼎的谷歌 C++ 测试框架 GoogleTest。

本文上接《C++ 测试框架 GoogleTest 初学者入门篇 乙》,欢迎关注公众号【ENG八戒】查看更多精彩内容。


断言

什么是断言?断言是用来对表达式执行比较的代码块,调用时类似函数。当表达式一致时,断言返回成功,否则失败。

googletest 的断言是一组宏定义。分为 ASSERT_* 和 EXPECT_* 两种。

比如

ASSERT_EQ(1, 2);

EXPECT_EQ(1, 2);

上面用到的两个断言都是比较输入的数据是否相等。主要区别是,ASSERT_* 在失败时终止程序运行,EXPECT_* 在失败时不会终止程序运行,但是都会返回错误信息。因而测试使用 EXPECT_* 可以发现更多的问题而不会打断测试流程。

那么 ASSERT_* 断言失败时,跟在其后的语句会被忽略执行,如果其中包含对资源的释放,那么就有会出现资源泄漏的问题,断言失败报错信息会附带有堆检查错误。这时出现的资源泄漏问题,真的有必要修复码?看具体情况而定。

另外,googletest 在断言失败后除了可以返回标准错误信息,还可以附带返回自定义错误信息,使用操作符 << 添加自定义错误信息。

ASSERT_EQ(1, 2) << "1 is not equal to 2";

EXPECT_EQ(1, 2) << "1 is not equal to 2";

任何可以传递给 ostream 的数据都可以作为自定义错误信息传递给断言,比如 C 字符串、string对象。

那么,测试的基本手段就是利用断言,除了判断型的断言之外,googletest 还提供了其它类型的断言用于协助测试,比如显式成功或失败、布尔类型断言、字符串比较断言等,详情可以前往官网查看手册。

https://google.github.io/googletest/reference/assertions.html

如何测试

前面提到在 googletest 中,测试的范围分为测试套件和单个测试。测试程序可以包含多个测试套件,一个测试套件可以包含多个测试。

简单的测试一般推荐使用 TEST 宏来定义单个测试。

一般的使用方式如下

TEST(test_suite_name, test_name) {
  // test body
}

test_suite_name 是测试套件名,test_name 是单个测试的名称,书写时都应该符合 C++ 的标识符规范,而且不能包含有下划线_。更详细的命名规范可以查看下面的链接

https://google.github.io/styleguide/cppguide.html#Function_Names

那么 TEST 宏到底代表着什么?一起来看看 TEST 宏定义的源代码

#define GTEST_STRINGIFY_HELPER_(name, ...) #name
#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, )

#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
  test_suite_name##_##test_name##_Test

#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id)       \
  static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1,                 \
                "test_suite_name must not be empty");                          \
  static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1,                       \
                "test_name must not be empty");                                \
  class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                     \
      : public parent_class {                                                  \
   public:                                                                     \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default;            \
    ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default;  \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                         \
    (const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &) = delete;     \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=(            \
        const GTEST_TEST_CLASS_NAME_(test_suite_name,                          \
                                     test_name) &) = delete; /* NOLINT */      \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)                         \
    (GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) &&) noexcept = delete; \
    GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) & operator=(            \
        GTEST_TEST_CLASS_NAME_(test_suite_name,                                \
                               test_name) &&) noexcept = delete; /* NOLINT */  \
                                                                               \
   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(                            \
          #test_suite_name, #test_name, nullptr, nullptr,                      \
          ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id),  \
          ::testing::internal::SuiteApiResolver<                               \
              parent_c
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【Visual Leak Detector】VS 中 V.. 下一篇C++的对象和类

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目