Google C++单元测试框架GoogleTest---值参数化测试
值参数化测试允许您使用不同的参数测试代码,而无需编写同一测试的多个副本。
假设您为代码编写测试,然后意识到您的代码受到布尔参数的影响。
TEST(MyCodeTest, TestFoo) {
// A code to test foo().
}
通常人们在这种情况下将他们的测试代码考虑为具有布尔参数的函数。 该函数设置标志,然后执行测试代码:
void TestFooHelper(bool flag_value) {
flag = flag_value;
// A code to test foo().
}
TEST(MyCodeTest, TestFoo) {
TestFooHelper(false);
TestFooHelper(true);
}
但这种设置有严重的缺点。 首先,当测试断言在测试中失败时,不清楚参数的什么值导致它失败。 您可以将澄清消息流式传输到EXPECT / ASSERT语句中,但是您必须对所有这些语句进行。 第二,你必须为每个测试添加一个这样的帮助函数。 如果你有十个测试怎么办? 二十? 一百?
值参数化测试将允许您只写一次测试,然后轻松实例化并使用任意数量的参数值运行它。
一、如何写值参数化测试
1. 要写值参数化测试,首先应该定义一个fixture类。 它必须继承:: testing :: Test和:: testing :: WithParamInterface <T>(后者是纯粹的接口),其中T是参数值的类型。
为了方便,你可以从:: testing :: TestWithParam <T>派生fixture类,它本身是从:: testing :: Test和:: testing :: WithParamInterface <T>派生的。 T可以是任何可复制类型。 如果它是一个原始指针,你负责管理指向的值的生命周期。
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual fixture class members here.
// To access the test parameter, call GetParam() from class
// TestWithParam<T>.
};
// Or, when you want to add parameters to a pre-existing fixture class:
class BaseTest : public ::testing::Test {
...
};
class BarTest : public BaseTest,
public ::testing::WithParamInterface<const char*> {
...
};
2.告诉gtest你拿到参数的值后,具体做些什么样的测试
这里,我们要使用一个新的宏(嗯,挺兴奋的):TEST_P,关于这个"P"的含义,Google给出的答案非常幽默,就是说你可以理解为”parameterized" 或者 "pattern"。我更倾向于 ”parameterized"的解释,呵呵。在TEST_P宏里,使用GetParam()获取当前的参数的具体值。
TEST_P(FooTest, DoesBlah) {
// Inside a test, access the test parameter with the GetParam() method
// of the TestWithParam<T> class:
//在测试中,使用TestWithParam <T>类的GetParam()方法访问测试参数:
int n = GetParam();
EXPECT_TRUE(IsPrime(n));
...
}
TEST_P(FooTest, HasBlahBlah) {
...
}
3. 您可以使用INSTANTIATE_TEST_CASE_P来实例化具有任何您想要的参数的测试用例。 Google Test定义了一些用于生成测试参数的函数。 它们返回我们所谓的参数生成器(surprise!)。 这里是它们的摘要,它们都在testing命名空间中:
Range(begin, end[, step]) |
Yields values {begin, begin+step, begin+step+step, ...}. The values do not include end. step defaults to 1. |
|---|---|
Values(v1, v2, ..., vN) |
Yields values {v1, v2, ..., vN}. |
ValuesIn(container)and ValuesIn(begin, end) |
Yields values from a C-style array, an STL-style container, or an iterator range [begin, end). container, begin, and end can be expressions whose values are determined at run time. |
Bool() |
Yields sequence {false, true}. |
Combine(g1, g2, ..., gN) |
这个比较强悍,它将g1,g2,...gN进行排列组合,g1,g2,...gN本身是一个参数生成器,每次分别从g1,g2,..gN中各取出一个值,组合成一个元组(Tuple)作为一个参数。 说明:这个功能只在提供了<tr1/tuple>头的系统中有效。gtest会自动去判断是否支持tr/tuple,如果你的系统确实支持,而gtest判断错误的话,你可以重新定义宏GTEST_HAS_TR1_TUPLE=1。See comments in include/gtest/internal/gtest-port.h for more information. |
有关更多详细信息,请参阅源代码中这些函数的定义中的注释。
以下语句将从FooTest测试用例中实例化测试,每个测试用参数值“meeny”,“miny”和“moe”。
INSTANTIATE_TEST_CASE_P(InstantiationName,
FooTest,
::testing::Values("meeny", "miny", "moe"));
为了区分模式的不同实例(是的,您可以多次实例化),
INSTANTIATE_TEST_CASE_P的第一个参数是测试案例的前缀,可以任意取。
第二个参数是测试案例的名称,需要和之前定义的参数化的类的名称相同,如:IsPrimeParamTest
第三个参数是可以理解为参数生成器,上面的例子使用test::Values表示使用括号内的参数。Google提供了一系列的参数生成的函数:
请记住为不同的实例化选择唯一的前缀。 从上面的实例化的测试将有这些名称:
- InstantiationName / FooTest.DoesBlah / 0 for“meeny”
- InstantiationName / FooTest.DoesBlah / 1 for“miny”
- InstantiationName / FooTest.DoesBlah / 2 for“moe”
- InstantiationName / FooTest.HasBlahBlah / 0 for“meeny”
- InstantiationName / FooTest.HasBlahBlah / 1 for“miny”
- InstantiationName / FooTest.HasBlahBlah / 2 for“moe”
您可以在--gtest_filter.中使用这些名称。
请注意,INSTANTIATE_TEST_CASE_P将实例化给定测试用例中的所有测试,无论它们的定义是在INSTANTIATE_TEST_CASE_P语句之前还是之后。
You can see these files for more examples.
二、创建值参数化抽象测试
在上面,我们在同一个源文件中定义和实例化FooTest。有时您可能想在库中定义值参数化测试,并让其他人稍后实例化它们---这种模式称为抽象测试。
作为其应用程序的一个例子,当你设计一个接口时,你可以编写一个标准的抽象测试套件(也许使用一个工厂函数作为测试参数),该接口的所有实现都应该通过。当有人实现该接口时,他可以实例化您的套件以免费获得所有的接口一致性测试。
要定义抽象测试,你应该这样组织你的代码:
1.将参数化测试夹具类(例如FooTest)的定义放在头文件中,例如foo_param_test.h。这是你抽象测试的声明。
2.将TEST_P定义放在foo_param_test.cc中,其中include foo_param_test.h。这是你抽象测试的实现。
一旦定义它们,您可以通过包括foo_param_test.h,调用INSTANTIATE_TEST_CASE_P()和链接foo_param_test.cc来实例化它们。您可以多次实例化相同的抽象测试用例,可能在不同的源文件中。
三、一个简单的代码示例
//被测函数
bool IsPrime(int n) {
// Trivial case 1: small numbers
if (n <= 1) return false;
// Trivial case 2: even numbers
if (n % 2 == 0) return n == 2;
// Now, we have that n is odd and n >= 3.
// Try to divide n by every odd number i, starting from 3
for (int i = 3; ; i += 2) {
// We only have to try i up to the squre root of n
if (i > n / i) break;
// Now, we have i <= n/i < n.
// If n is divisible by i, n is not prime.
if (n % i == 0) return false;
}
// n has no integer factor in the range (1, n), and thus is prime.
return true;
}
//第一步
class FooTest : public ::testing::TestWithParam<int> {
// You can implement all the usual fixture class members here.
// To access the test parameter, call GetParam() from class
// TestWithParam<T>.
//在这里面可以实现fixture类的所有成员 };
//第二步
TEST_P(FooTest, DoesBlah) {
// Inside a test, access the test parameter with the GetParam() method
// of the TestWithParam<T> class:
//在测试中,使用TestWithParam <T>类的GetParam()方法访问测试参数:
int n = GetParam();
EXPECT_TRUE(IsPrime(n));
//...
} //第三步
//第一个参数是前缀;第二个是类名;第三个是参数生成器
INSTANTIATE_TEST_CASE_P(MyPrimeParamTest,
FooTest,
::testing::Values(-5,0, 3, 5, 11)); int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();
}
运行结果:

从上面的框框中的案例名称大概能够看出案例的命名规则,对于需要了解每个案例的名称的我来说,这非常重要。 命名规则大概为:
prefix/test_case_name.testname/index
Google C++单元测试框架GoogleTest---值参数化测试的更多相关文章
- Google C++单元测试框架GoogleTest(总)
之前一个月都在学习googletest框架,对googletest的文档都翻译了一遍,也都发在了之前的博客里,另外其实还有一部分的文档我没有发,就是GMock的CookBook部分:https://g ...
- Google C++单元测试框架GoogleTest---GMock的CheatSheet文档
CheatSheet文档中包含了GMock所有常用的东西,看了这个基本上就可以用它了,本文接上篇博文:Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础 ...
- Google C++单元测试框架GoogleTest---AdvancedGuide(译文)下
因为AdvancedGuide文档太长,分上下两部分,本文档接googletest--AdvancedGuide(译文)上:Google C++单元测试框架GoogleTest---AdvancedG ...
- Google C++单元测试框架GoogleTest---GTest的Sample1和编写单元测试的步骤
如果你还没有搭建gtest框架,可以参考我之前的博客:http://www.cnblogs.com/jycboy/p/6001153.html.. 1.The first sample: sample ...
- Google C++单元测试框架
一.概述 Google C++单元测试框架(简称Gtest),可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian),它提供了丰富的断言.致命和非致 ...
- Google C++单元测试框架---Gtest框架简介(译文)
一.设置一个新的测试项目 在用google test写测试项目之前,需要先编译gtest到library库并将测试与其链接.我们为一些流行的构建系统提供了构建文件: msvc/ for Visual ...
- Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础语法
就在昨天终于做了gtest的分享,我的预研工作终于结束了,感觉离我辞职的日子不远了,毕竟是专注java二百年啊,要告别实习啦.. 这篇是GoogleMock的简介文档,会在后边附带一个自己的例子. 一 ...
- Google C++单元测试框架GoogleTest---AdvancedGuide(译文)上
本文是gtest高级测试指南的译文,由于文章太长,分上下两部分. 一.简介 本文档将向您展示更多的断言,以及如何构造复杂的失败消息,传播致命的故障,重用和加速您的测试夹具,并在您的测试使用各种标志. ...
- Pytest单元测试框架之parametrize参数化
1.参数化的本质:相同的步骤,但测试数据不同,比如登录的场景 import mathimport pytest# 方式一:分离出Listdef list_Test(): list = [ [2, 2, ...
随机推荐
- ReactNative入门(安卓)——API(上)
Alert - 弹窗 通过 Alert.alert() 方法调用唤起原生弹窗,点击会触发 onPress 回调(参考下方代码)并清除弹窗. import React, { AppRegistry, C ...
- 博客已经迁移至 http://barretlee.com/entry/,时而同步分享到这里
博客园是一个十分好的写作平台,不过个人比较喜欢倒腾,所以将文章都做了搬迁. 博客已经迁移至 http://barretlee.com/entry/,感谢一直以来的关注和支持. 博客订阅地址: http ...
- mysql sleep进程过多,应用级配置
<property name="hibernateProperties"> <props> <prop key="hibernate.dia ...
- 跟我一起数据挖掘(23)——C4.5
C4.5简介 C4.5是一系列用在机器学习和数据挖掘的分类问题中的算法.它的目标是监督学习:给定一个数据集,其中的每一个元组都能用一组属性值来描述,每一个元组属于一个互斥的类别中的某一类.C4.5的目 ...
- 06.移动先行之谁主沉浮----我的代码我来写(Xaml的优势)
如果移动方向有任何问题请参考===> 异常处理汇总-移动系列(点) 前面几节课,我们都是在前台创建对象,进行一些设置,那么我们为什么不用传统的方法来编程呢? 我们今天来试试你就明了了~~ 打开M ...
- 【Win 10 应用开发】TCP通信过程
基于TCP协议的通信,估计大伙儿都不陌生的,以前玩.net或玩C++的时候应该玩得很多吧.现在老周简单介绍一下在RT中如何用. TCP是基于连接的,所以,肯定有一方是监听者,通常称服务端或服务器,它负 ...
- 【转】利用反射快速给Model实体赋值
原文地址:http://blog.csdn.net/gxiangzi/article/details/8629064 试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有 ...
- Oracle从文件系统迁移到ASM存储
环境:RHEL 6.4 + Oracle 11.2.0.4 需求:数据库存储由文件系统迁移到ASM 数据库存储迁移到ASM磁盘组 1.1 编辑参数文件指定新的控制文件路径 1.2 启动数据库到nomo ...
- RHEL 本地yum源配置
1.创建挂载目录 # mkdir -p /media/cdrom 2.挂载对应系统版本的iso光盘镜像文件 # mount -o loop -t iso9660 /opt/rhel-server- ...
- SpringMVC一路总结(一)
SpringMVC听闻已久,早在去年就被学长问到关于SpringMVC的基础知识,当时也没在意.主要是工作中也没有用到关于SpringMVC的技术,因此免于没有时间和精力的借口就没有接触和学习Spri ...