GTest基础学习-02-第一个单元测试-函数级的单元测试

这篇开始学习单元测试示范,在GTest这个下载包,里面有一个samples文件夹,里面有10个单元测试例子,告诉我们怎么去使用googletest这个测试框架。我认为,这种官方文档,是十分有必要认真,一个一个学习完成,你才可以说基本会用GTest这个框架。我们先学习会用,高级的原理层我们等有基础再尝试去看看源码学习学习。

 

1.第一个单元测试:n的阶乘和n是否素数两个函数的单元测试

一共三个文件,一个头文件,一个实现文件,一个是单元测试文件。典型模拟我们真实项目中的情况。

 

2.相关代码拷贝到vs2015

我把这三个文件,拷贝到了vs2015环境,然后把注释用中文写了一遍

第一个头文件sample01.h 代码如下

// 使用Google C++ testing 框架的一个简单的编程示例
#ifndef GTEST_SAMPLES_SAMPLE01_H_
#define GTEST_SAMPLES_SAMPLE01_H_

// 返回n的阶乘,如果n为负数,返回1
int Factorial(int n);

// 如果是素数返回true,否则返回false
bool IsPrime(int n);


#endif  // GTEST_SAMPLES_SAMPLE01_H_

 

实现类cpp文件

// 使用Google C++ testing 框架的一个简单的编程示例

#include "sample01.h"

// 返回n的阶乘,如果n为负数,返回1
int Factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; i++) {
	    result *= i;
    }
    return result;
}

// 如果是素数返回true,否则返回false
bool IsPrime(int n) {
    // 分支1: n小于等于1的数
    if (n <= 1) return false;

    // 分支2: 偶数
    if (n % 2 == 0) return n == 2;

    // 接下来n为奇数,且n>=3

    // i从3开始,尝试用n去除奇数i
    for (int i = 3; ; i += 2) {
	// 我们只需要尝试i直到n的平方根
	if (i > n / i) break;

	// 现在 i <= n/i < n.
	// 如果n能被i整除,n不是素数
	if (n % i == 0) return false;
    }

    // n 在范围 (1, n)没有整数因子,所以n是素数
    return true;
}

上面两个函数,第一个求n的阶乘。第二个是判断一个数是不是素数。具体什么是素数可以先百度一下,这种函数内部分支覆盖的白盒测试是需要完整理解函数内部的逻辑。

单元测试类代码

// 使用 1-2-3步骤,很容易使用Gtest框架编写单元测试

// 步骤1. 根据你的实际情况,包含所需的头文件
// 不要忘记包含 gtest.h, 采用使用GTest测试框架

#include <limits.h>
#include "sample01.h"
#include "gtest/gtest.h"

namespace {

	// 步骤2. 使用TEST宏去定义你的测试
	//
	// TEST 宏有两个参数: 测试用例名称 和测试名称.
	// 使用TEST宏之后, 你需要在{}之内定义你的测试逻辑。你可以使用一堆宏来断言成功还是失败.  EXPECT_TRUE 和 EXPECT_EQ 
	// 是这堆断言宏的两个常用的宏.  可以打开gtest.h阅读找到全部的断言宏。
	//
	//在GTest中,测试被划分为不同的测试用例. 这样组织用例,保证了测试代码的井井有条。
	//你应该把逻辑相关的测试放入奥相同的测试用例中。
	//
	// 测试名称和测试用例名称都需要符合C++标识符规范
	// 并且在测试名称和测试用例名称中,你不能使用下划线(_)

	// Google Test 框架可以确保每个测试都执行一次,但不确保测试顺序执行。
	//所以,你要确保你写的测试的结果不依赖其他测试的顺序
	

	// 测试函数 Factorial().

	// 使用负数测试斐波那契数列
	TEST(FactorialTest, Negative) {
		// This test is named "Negative", and belongs to the "FactorialTest"
		// 测试用例
		EXPECT_EQ(1, Factorial(-5));
		EXPECT_EQ(1, Factorial(-1));
		EXPECT_GT(Factorial(-10), 0);

		// EXPECT_EQ(expected, actual) 等价于 EXPECT_TRUE((expected) == (actual))
		
		// 当断言发生失败,EXPECT 相关宏会同时打印实际结果和预期结果
		// 这在调试的时候非常有用
		// 因此在这种情况下首选 EXPECT_EQ宏用来断言
		//
		// 另一边,EXPECT_TRUE 宏接受一切的布尔表达式,更为笼统。
	}

	// 测试0的阶乘
	TEST(FactorialTest, Zero) {
		EXPECT_EQ(1, Factorial(0));
	}

	// 测试正整数的阶乘
	TEST(FactorialTest, Positive) {
		EXPECT_EQ(1, Factorial(1));
		EXPECT_EQ(2, Factorial(2));
		EXPECT_EQ(6, Factorial(3));
		EXPECT_EQ(40320, Factorial(8));
	}


	// 以下测试函数 IsPrime()

	// 测试负数输出
	TEST(IsPrimeTest, Negative) {
		// 这个测试点属于 IsPrimeTest测试用例
		EXPECT_FALSE(IsPrime(-1));
		EXPECT_FALSE(IsPrime(-2));
		EXPECT_FALSE(IsPrime(INT_MIN));
	}

	// 测试一些简单的数字n=0,1,2,3
	TEST(IsPrimeTest, Trivial) {
		EXPECT_FALSE(IsPrime(0));
		EXPECT_FALSE(IsPrime(1));
		EXPECT_TRUE(IsPrime(2));
		EXPECT_TRUE(IsPrime(3));
	}

	// 测试一些正整数n
	TEST(IsPrimeTest, Positive) {
		EXPECT_FALSE(IsPrime(4));
		EXPECT_TRUE(IsPrime(5));
		EXPECT_FALSE(IsPrime(6));
		EXPECT_TRUE(IsPrime(23));
	}
}  // namespace

   // 步骤3. 在 main()调用 RUN_ALL_TESTS() .
   // 这个我们写在了LearnGtest.cpp文件中的main函数
  

保存之后,点击 生成->生成解决方案,然后 调试->开始执行(不调试),观察测试结果输出报告

上面具体素数的逻辑,需要好好想以下。

 

3.总结

3.1 上面说的编写Gtest用例采用 1-2-3 三步法,其实就两部:

步骤1:引入头文件,包括被测试对象头文件和gtest.h这个头文件

步骤2:使用TEST宏,有两个参数,第一个是测试用例名称,第二个是测试点名称

文档中说得步骤3是我们在别的文件的main()函数中调用了RUN_ALL_TESTS()方法。

 

3.2 Gtest中提供了一堆断言用的宏,可以在gtest.h文件找到更多宏

3.3 不需要我们手动把用例注册到Gtest框架,这个框架会自动发现TEST宏的测试用例。

3.4 每个TEST宏的测试会被执行,但是执行不确保用例的顺序

3.5 当前在断言,建议使用EXPECT开头的宏,因为断言出错之后,会打印实际结果和预期结果,方便调试问题

 

4.其他练习

可以修改断言语句中一个值,让其中一条用例执行失败,看看控制台打印失败的信息能不能根据失败日志,找到定位出问题的代码行,并修复,使测试成功运行通过。

 

 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值