值参数化测试允许您使用不同的参数测试代码,而无需编写同一测试的多个副本。

假设您为代码编写测试,然后意识到您的代码受到布尔参数的影响。

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 endstep 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)containerbegin, 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---值参数化测试的更多相关文章

  1. Google C++单元测试框架GoogleTest(总)

    之前一个月都在学习googletest框架,对googletest的文档都翻译了一遍,也都发在了之前的博客里,另外其实还有一部分的文档我没有发,就是GMock的CookBook部分:https://g ...

  2. Google C++单元测试框架GoogleTest---GMock的CheatSheet文档

    CheatSheet文档中包含了GMock所有常用的东西,看了这个基本上就可以用它了,本文接上篇博文:Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础 ...

  3. Google C++单元测试框架GoogleTest---AdvancedGuide(译文)下

    因为AdvancedGuide文档太长,分上下两部分,本文档接googletest--AdvancedGuide(译文)上:Google C++单元测试框架GoogleTest---AdvancedG ...

  4. Google C++单元测试框架GoogleTest---GTest的Sample1和编写单元测试的步骤

    如果你还没有搭建gtest框架,可以参考我之前的博客:http://www.cnblogs.com/jycboy/p/6001153.html.. 1.The first sample: sample ...

  5. Google C++单元测试框架

    一.概述 Google C++单元测试框架(简称Gtest),可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian),它提供了丰富的断言.致命和非致 ...

  6. Google C++单元测试框架---Gtest框架简介(译文)

    一.设置一个新的测试项目 在用google test写测试项目之前,需要先编译gtest到library库并将测试与其链接.我们为一些流行的构建系统提供了构建文件: msvc/ for Visual ...

  7. Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础语法

    就在昨天终于做了gtest的分享,我的预研工作终于结束了,感觉离我辞职的日子不远了,毕竟是专注java二百年啊,要告别实习啦.. 这篇是GoogleMock的简介文档,会在后边附带一个自己的例子. 一 ...

  8. Google C++单元测试框架GoogleTest---AdvancedGuide(译文)上

    本文是gtest高级测试指南的译文,由于文章太长,分上下两部分. 一.简介 本文档将向您展示更多的断言,以及如何构造复杂的失败消息,传播致命的故障,重用和加速您的测试夹具,并在您的测试使用各种标志. ...

  9. Pytest单元测试框架之parametrize参数化

    1.参数化的本质:相同的步骤,但测试数据不同,比如登录的场景 import mathimport pytest# 方式一:分离出Listdef list_Test(): list = [ [2, 2, ...

随机推荐

  1. BZOJ 1006 【HNOI2008】 神奇的国度

    题目链接:神奇的国度 一篇论文题--神奇的弦图,神奇的MCS-- 感觉我没有什么需要多说的,这里简单介绍一下MCS: 我们给每个点记录一个权值,从后往前依次确定完美消除序列中的点,每次选择权值最大的一 ...

  2. Linux+apache+mono+asp.net安装教程

    Linux+apache+mono+asp.net安装教程(CentOS上测试的) 一.准备工作: 1.安装linux系统(CentOS,这个就不多讲了) 2.下载所需软件 http-2.4.4.ta ...

  3. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  4. 初尝Brnshop移植到Linux Mono Jexus环境运行

    brnshop是最近社区上比较火的开源商城. Jexus是Linux上的web服务器,简单说就是Linux的iis吧.特别感谢作者宇内流云的指点 一.根据http://www.cnblogs.com/ ...

  5. opengl 笔记(1)

    参考<opengl入门教程>.<OpenGL之坐标转换>.<OpenGL绘制管线操作细节>等资料. 复习下留个备忘:) /*- * Opengl Demo Test ...

  6. 微信硬件H5面板开发(一) ---- 调用openApi

    微信硬件平台是微信推出连接物与人,物与物的IOT解决方案.也就是说可以通过微信控制各种智能设备.比如一些蓝牙设备.空调.电视等等. 我本身不懂硬件(虽然是电子信息专业),硬件是北航的两个研究生在弄,小 ...

  7. iOS开发系列--网络开发

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  8. Python学习--02输入和输出

    命令行输入 x = input("Please input x:") y = raw_input("Please input x:") 使用input和raw_ ...

  9. VS2010开发工具使用技巧<之简单讲解>

    俗语云:工欲善其事必先利其器! 1.代码放大 效果:放大前----------------------------------------------------------------->放大 ...

  10. OpenCASCADE Ring Type Spring Modeling

    OpenCASCADE Ring Type Spring Modeling eryar@163.com Abstract. The general method to directly create ...