版权相关声明:本文所述方案来自于《深入理解C++11—C++11新特性解析与应用》(Michael Wong著,机械工业出版社,2016.4重印)一书的学习。

  项目管理中,C语言工程做单元测试用例直接写就可以了,对于C++语言工程,曾经听到过“C++类的私有成员在外部无法访问没法写啊,就测测接口吧?”,对于项目管理人员与开发人员,作为C/C++语言使用者的你是否也有过这种烦恼?

  提案“单元测试用例以私有成员函数的形式写在被测类的里面,通过预处理宏开关,使得发布时不让单元测试编译链接进去”,方案在语法上可以,而且也没有破坏封装性,但是测试用例的量很庞大跟生产代码搞在一起好不爽有么有,不优雅,没有人会这么做会让自己的代码变成那样。

  提案“通过预处理宏开关,使得单元测试时将private替换为public”,看上去这个提案简单,但是也不完美,使用默认的private成员限制(如class FooTest : Foo { int x;}),这个方案处理不了这个情形,另外这个方案要求你的程序中变量名和函数名中不能含有private子字符串。


  下面将介绍书中的类单元测试的完美解决方案:

  1.语法知识准备:“可以为类模板声明友元”(C++11新特性)

    template<typename T>

    class Foo {

      friend T;

    }

  如果FooTest是类,那么Foo<FooTest>会被实例化为一个定义了类FooTest为其友元的Foo<FooTest>类。

  而若T为内置类型时,如Foo<int>会被实例化为一个普通的没有友元定义的类型。

  2.生产代码中的类模板实例化

    template<typename T>

    class FooT {

    public:

      friend T;

      void DoSomthing(){}

    private:

      int m_data;

    }

    using Foo = FooT<int>;

    后续的生产代码可以直接使用Foo,生产代码很优雅。

  3.测试代码中的设计(与原书稍有出入,根据自身需求调整)

    class FooTester;  //测试类

    using FooTestee = FooT<FooTester>;   //被测试类

    class FooTester{

    public:

      void Testcase1() {}

    }

    在FooTester类里面,我们可以测试FooTestee的私有或公有成员函数,可以访问FooTestee的私有成员变量进行验证。总之单元测试很优雅。


  学习了上面的完美方案,为C++11的新特性感到欢欣鼓舞,做一名重视单元测试的对自己有要求的C/C++工作者。感谢深入理解C++11这本书。

    

C++类的完美单元测试方案——基于C++11扩展的friend语法的更多相关文章

  1. 真正意义上的spring环境中的单元测试方案spring-test与mokito完美结合

    真正意义上的spring环境中的单元测试方案spring-test与mokito完美结合 博客分类: java 测试 单元测试SpringCC++C#  一.要解决的问题:     spring环境中 ...

  2. 如何写好、管好单元测试?基于Roslyn+CI分析单元测试,严控产品提测质量

    上一篇文章中,我们谈到了通过Roslyn进行代码分析,通过自定义代码扫描规则,将有问题的代码.不符合编码规则的代码扫描出来,禁止签入,提升团队的代码质量. .NET Core技术研究-通过Roslyn ...

  3. JMessage是让App 同时集成 Push 功能与 IM 功能最完美的方案

    历经几个月的沉寂,以及兄弟们的奋战,极光推送的兄弟产品诞生了:极光IM,英文名 JMessage. 极光IM 是我们团队基于大量客户的需求反馈,在很多客户的殷切期盼下所开发的.团队成员一方面要支撑极光 ...

  4. 基于类(Java)和基于原理(JavaScript)的对象系统的比较

    Java:面向对象编程语言,吸收了C++语言的各种优点,丢掉了C++让人头疼的多继承.指针等概念.具有功能强大和简单易用的两大特征.Java具有简单性.面向对象.分布式.健壮性.安全性.平台独立与可移 ...

  5. svg操纵方案 基于 D3 还是 angular?

    之前还是想简单了, 现在重新写这篇.把逻辑拆分粒度的辨析,放到外面去. 问题提出:svg控制方案 基于 D3 还是 angular 根据这个,html 4种展现样式:普通的html,svg,2D ca ...

  6. 基于Spark自动扩展scikit-learn (spark-sklearn)(转载)

    转载自:https://blog.csdn.net/sunbow0/article/details/50848719 1.基于Spark自动扩展scikit-learn(spark-sklearn)1 ...

  7. 基于C++11的线程池实现

    1.线程池 1.1 线程池是什么? 一种线程管理方式. 1.2 为什么用线程池? 线程的创建和销毁都需要消耗系统开销,当线程数量过多,系统开销过大,就会影响缓存局部性和整体性能.而线程池能够在充分利用 ...

  8. 基于C++11的数据库连接池实现

    0.注意 该篇文章为了让大家尽快看到效果,代码放置比较靠前,看代码前务必看下第4部分的基础知识. 1.数据库连接池 1.1 是什么? 数据库连接池负责分配.管理和释放数据库连接,属于池化机制的一种,类 ...

  9. ExtJS4.2学习(13)基于表格的扩展插件---rowEditing

    鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-24/182.html --------------- ...

随机推荐

  1. MCB2300的CTM1050(CAN) - 系列示意图

    这一系列示意图由Portel DXP 2004绘. 截图: 文件下载: CTM1050.7z 版权声明:本文博客原创文章,博客,未经同意,不得转载.

  2. 在微信浏览器里使用js或jquery实现页面重新刷新

    function refresh() { var random = Math.floor((Math.random() * 10000) + 1); var url = decodeURI(windo ...

  3. 有了VARCHAR,为什么还要有CHAR?

    VarcharVarchar往往用来保存可变长度的字符串.简单的说,我们只是给其固定了一个最大值,然后系统会根据实际存储的数据量来分配合适的存储空间.为此相比CHAR字符数据而言,其能够比固定长度类型 ...

  4. JS 中按键处理

    <script type="text/javascript">        //关于键的问题        onload = function () {        ...

  5. 【shell】递归函数----调用自身的函数

    什么是递归函数? 一句话,调用自己的函数称为递归函数! #!/bin/bash declare -i count checkoutCount(){ read -p "Enter an cou ...

  6. System.Data.SQLite 中GUID的处理

    原文:System.Data.SQLite 中GUID的处理 项目中正好用到System.Data.SQLite,在手持上使用这个数据库,因为要做数据同步,所以表中的主键都是Guid的数据类型. 在数 ...

  7. Android零基础入门第20节:CheckBox和RadioButton使用大全

    原文:Android零基础入门第20节:CheckBox和RadioButton使用大全 本期先来学习Button的两个子控件,无论是单选还是复选,在实际开发中都是使用的较多的控件,相信通过本期的学习 ...

  8. C#高性能大容量SOCKET并发(十一):编写上传客户端

    原文:C#高性能大容量SOCKET并发(十一):编写上传客户端 客户端封装整体框架 客户端编程基于阻塞同步模式,只有数据正常发送或接收才返回,如果发生错误则抛出异常,基于TcpClient进行封装,主 ...

  9. .net core 利用Selenium和PhantomJS后台生成EChart图片

    1.引用 NuGet安装: Selenium.Support Selenium.WebDriver Selenium.WebDriver.PhantomJS.CrossPlatform  (分布Lin ...

  10. CentOS7 无法使用yum命令,无法更新解决方法

    前言 设置网卡开机自动启动 设置国内dns服务器系统 修改CentOS-Base.repo中的地址 所参考的文章地址 前言 刚安装完的CentOS7的系统,发现无法使用yum命令进行更新,在更新的时候 ...