6.18-GTest

GTest and ROSTest

TOC

致谢

Linux 大棚
ROSTest

前言

为什么要学GTest

  • 开源框架,完全免费
  • 用得人多,项目多,比如ROS就用这个做测试,这是我学习GTEST的直接原因
  • 软件工程师入门啊!

科普

  • 如果你是一名开发工程师,或者你编写的程序要用到生产环境中,那么,你不可避免的需要学习和掌握一种自动化测试框架,以确保你的程序测试充分,质量上乘。
  • 其实啊,测试工具是什么并不重要,重要的是测试思想,还是在大学期间上过的课,亲身做过的项目才是真货,好吧,去考个计算机三级软件测试技术?

好的测试框架应该是(软件测试思想)

  • 软件应该是独立的且可重复的,每个测试应该是一个独立的对象
  • 应该有一套好的方法来组织测试,这种组织方法能够较好的反映程序代码的结构
  • 测试应该是可迁移的且可复用的(平台中立)(支持多种编译器)
  • 在测试失败时,要能够提供足够充分的测试信息
  • 测试框架应该让开发者从琐碎的工作中解脱出来,让他们能够专注在测试内容上
  • 测试应该是高效的

GTest 入门

综述

  • 第一步就是:把gtest编译成一个库,并且链接到你的测试程序中
  • 你的测试项目程序要引用gtest/gtest.h,你的gtest安装在GTEST_ROOT路径下

断言assertion

  • gtest 中的断言是一些宏,assertion在测试一个函数时,可以有两种方案,即ASSERT_和EXPECT_。在失败发生时,ASSERT_这类assertion会产生fatal failure,并且会终止当前函数;而EXPECT_则只会产生nonfatal failure。
  • 常用的宏有
    EXPECT_EQ/NE/LT/LE/GT/GE([表达式],[表达式])
  • 对于ASSERT_EQ比较两个C字符串指针,只会检查两个指针是否指向同一块区域,要想检查两个(C风格字符串)字符串内容是否相同,要使用ASSERT_STREQ,不过比较两个C++字符串的话就用ASSERT_EQ就可以了。
  • 特殊的比较宏——字符串比较宏
    ASSERT_STRCASEEQ(),此处CASE指不区分大小写的比较
  • 字符串比较宏的特殊规则
    NULL和空字符串""是不相等的。
  • 如果你想了解更多有关字符串比较的trick方法,比如在assertion中处理子字符串、前缀、后缀、正则匹配等,请进入“高级gtest指南”。

创建一个test

  • 三件事
  1. 使用TEST()宏来定义和命名一个test函数,这个test函数不需要return任何值。
  2. 在这个test函数中,你可以写任何C++语句,并且使用assertion来检查。
  3. 这个test的结果是由assertion决定的。如果任何一个assertion失败了,或者这个test函数崩溃了,这个test则会返回fail。否则,会返回success。
  • 语法
TEST(test_case_name, test_name) {
... test body ...
}
  • Test Fixtures
    如果你发现你所写的多个test都在操作类似的数据,那么我推荐你使用test fixture。这个特性允许你在不同的test里复用相同的配置。
    机制主要是类的继承,具体请看参考教程,见文首
    使用Test Fixtures时的宏
TEST_F(test_case_name, test_name) {
... test body ...
}// test_case_name 必须是定义的test fixture类的名称

运行测试

如果要触发运行,请执行RUN_ALL_TESTS()宏,如果所有的test都测试通过,它会返回0,否则会返回1。

  • 注意
    你bixu在你的main函数中return这个值。

编写测试的main函数

  • 参考如下模板
#include "this/package/foo.h"
#include "gtest/gtest.h"

namespace {

// The fixture for testing class Foo.
class FooTest : public ::testing::Test {
protected:
// You can remove any or all of the following functions if its body is empty.

FooTest() {
// You can do set-up work for each test here.
}

Virtual ~FooTest() {
// You can do clean-up work that doesn't throw exceptions here.
}

// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:

virtual void SetUp() {
// Code here will be called immediately after the constructor
}

virtual void TearDown() {
// Code here will be called immediately after each test
}

// Object declared here can be used by all tests in the test case for Foo.
};

// Tests that the Foo::Bar() method does Abc.
TEST_F(FooTest, MethodBarDoesAbc) {
const string input_filepath = "this/package/testdata/myinputfile.dat";
const string output_filepath = "this/package/testdata/myoutputfile.dat";
Foo f;
EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
}

// Tests that Foo does Xyz.
TEST_F(FooTest, DoesXyz) {
// Execises the Xyz feature of Foo.
}
} // namespace

int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
原文地址:https://www.cnblogs.com/lizhensheng/p/11117280.html