优点

为什么很多技术或者知识要说优点?因为有些道理看着很简单,大家表面上都觉得对,但是做的时候又不去做或者做不到。其中有一个很重要原因是骨子里或者潜意识并没有真实觉得这是对的,一旦想去做的时候同时会冒出更多不去做的理由。

方法更健壮

更明确方法的职责

很多小伙伴在编写方法或者程序的时候,先简单写一下“大体”的逻辑。好一些的,在写完后,会根据不同"情况"验证一下,如果有错再继续修改。但是往往更多的情况下,自己也不知道这个方法对外是一种什么形态,需要满足多少种情况,在异常的情况下提供的是什么表现。所以最终需要使用者(有可能是服务调用者,测试者或者真正的用户)来纠正问题,然后再去修订。
这样一来,整个编写方法的周期其实更长,资料的损耗更大。

通常情况下,是需要知道这个方法的职责。

明确服务职责边界

最好是单一的职责(web层或者流程聚合的接口除外)。

现在是做一个判空的工具。首先要分析的是这个判空的服务范围和职责。一个集合判空、一个字符串判空,跟一个同时支持,包装类,字符串(包括Char等),集合,数组,字典,对象等的判空。这就是两个完全不同的职责。不同的职责最终的case是不同的。

明确正常case

一般是根据第一步的服务范围和职责来提供的,这样是黑盒,和使用者的视角是一样的(推荐)。也有喜欢通过白盒列case的,通过if等拐点来确定case(不是很推荐)。最终要保证对的肯定是对的,而且要和预期结果一样。

明确异常的case

特别重要的是需求明确的异常,比如说,需要去支付,但是你的钱是非法的。还有抽象域的一些问题要考虑:比如说:冥等,批量操作时的原子性,依赖服务异常等。最终要保证错的一定要错

明确case输入

明确每一个case输入应该是什么,只关注和这个case相关的,这样每个都是具义的。如果一个case有太多的输入和case无关,最好是考虑对依赖的结点进行mock。

明确case输出

明确每一个case输出是什么。这样可以进行断点和结果预期。然后执行时,就能反向知道这个方法提供的服务是否正确。如果不正确的话,需要修改方法。

大胆重构

只有有case了,才能使用自动化的验证。否则有可能只是改了一个很小的地方,但是会引起其他case的错误,改一个小地点就得手动的把所有case测试一下。而且最害怕的是历史方法,因为没有人能说清楚到底有多少种case。

重构时错误常见的场景:

  • 一个判断条件或者设计的链路,想的是对的,但是写的时候出错,导致正常业务都出错了
  • 误删或者重构时遗漏代码,导致部分业务错误。

让编写的方法更独立

一旦耦合度太高,在造输入数据的时候就会特别困难。这样也反向的能促进我们在写代码的时候尽可能的不依赖,至少不深度或者嵌套依赖。

比如:以前是写个a方法,要知道b方法使用c对象的d属性。这样造输入的时候就特别难受。所以就会促进我们变成写个a方法,最多使用和关心b方法。其他是b方法的职责,让b方法自己去测试。

这样也能让每个方法更原子和内聚。

隔离依赖

无感依赖细则

不用关注依赖的细则,特别是不用跨层或者跨服务去关注细节。从树状结构关注点变为平级关注点。从关注细则到关注服务。

并行开发

以前的方式是,相互耦合依赖,上游没做完,下游没数据,没办法或者很难并行开发。但是使用隔离后,就可以基于接口的服务职责来mock预期的行为,所以互相就不会依赖,可以并行去开发。

结果可预见

比较头疼的是,要根据不同的业务case,造各种场景,有的场景还要开关或者编数据等特殊方式才可以。但是使用隔离mock后,想要有什么预期结果是非常稳定的,也是很简单自然的。
比如:有N个集合中,调用指定的服务后,如果有部分失败,部分成功。这个case用mock是非常好造的。

解决重复问题

当前,在编写单元测试的时候也会有很多工作量,所以可以通过单元测试框架来解决重复的问题。

  • mock简洁化和自动化。通过注解和ioc基本很容易做到。
  • 设置参数很头疼,还有很多魔鬼数字,有的时候还得硬着头皮造一些无喱头的数据。

哪些需要写

怎么写

  • 根据case准备数据,mock
  • 触发验证场景
  • 期待的结果是什么

何时写

我个人推荐的是,先大体明确方法的职责和边界,然后把突出的case大体设计出来。然后和具体实现代码同步。一来可以补充case,只有对需求有一定的理解后才能知道什么是代码的正确性,才能写出有效的单元测试来验证正确性,而能写出一些功能代码则说明对需求有一定理解了。二来可以使用重构的思维去解决思考两次而且还互相打架的问题。

陷阱

多验证点

多验证点的case,一旦业务稍微改变一点点,很容易造能case的通过不了,也说明了方法的职责不是很原子。有可能可以进一步拆分。

过度依赖上下文

说明方法不够健壮,职责不清楚。如果一旦上下文变更,就会导致case的失败。介时就分不清楚是上下文数据的问题,还是自己服务的问题。

还需要做的事

工具类库

虽然,单元测试框架做了很多重复的事,但是还有很多重复的事,其实都是可以封装成工具类的。
比如:一个方法有很多参数,然后每个参数都都可以赋默认值,那就得手写半天。像这种抽象上一致的都可以封装成工具类

规范

在不同的单元测试之间,其实有很多重复的思考和沟通。
比如:单元测试的方法名怎么命名更好些?一个方法放一个case还是多个case。什么样的异常需要验证case。

有了规范或者规约后。重复的内容可以通过代码片段,文件模板等方式半自动化的生成,甚至可以通过代码生成器等小工具,默认把一些手工的操作怎么自动生成。而且规范后,大家阅读和维护单元测试的成本就会降低。

理想状态的单元测试,应该是只验证正确的业务点,和异常的业务点,以及一些从系统和抽象问题领域角度的异常业务点。其他的要么交给工具,要么交给规范。

参考资料

单元测试er——为什么真的真的要写单元测试的更多相关文章

  1. Java基础学习总结(89)——为什么单元测试应该我们开发人员来写

    软件测试是为了保证项目质量,单元测试可以快速执行测试回归测试,做好单元测试可以大大提升测试效率,项目开发真正达到敏捷效果. 单元测试做什么? 1. 核心类方法 2. 异常处理 3. 边界值测试 4. ...

  2. 为什么从前那些.NET开发者都不写单元测试呢?

    楔子 四年前我虽然也写了很多年代码,由于公司虽然规模不小,却并非一家规范化的软件公司,因此在项目中严格意义上来说并没有架构设计.也不写单元测试,后来有幸加入了一家公司,这家公司虽然也是一家小公司,但是 ...

  3. VSTS写单元测试

                          用VSTS写单元测试                           许多应用程序都会用到“用户”类型,今天我要用的是ConsoleApplicatio ...

  4. 如何为 Vue 项目写单元测试

    https://www.w3ctech.com/topic/2052 如何为 Vue 项目写单元测试 前端工程 明非 2017-07-18 4685 访问 1 分享 微信分享 译者:明非 链接:htt ...

  5. 为什么不针对internal接口写单元测试?

    测试驱动的开发(TDD,Test Driven Development)的核心理念,是要使得重构(refactoring)更为有效,而不是创建更多的测试. 对一个有着长生命周期的项目来讲,在它的第一个 ...

  6. 腾讯工作近十年大佬:不是我打击你!你可能真的不会写Java

    文章核心 其实,本不想把标题写的那么恐怖,只是发现很多人干了几年 Java 以后,都自认为是一个不错的 Java 程序员了,可以拿着上万的工资都处宣扬自己了,写这篇文章的目的并不是嘲讽和我一样做 Ja ...

  7. 【快学springboot】在springboot中写单元测试[Happyjava]

    前言 很多公司都有写单元测试的硬性要求,在提交代码的时候,如果单测通不过或者说单元测试各种覆盖率不达标,会被拒绝合并代码.写单元测试,也是保证代码质量的一种方式. junit单元测试 相信绝大多数的J ...

  8. 【快学springboot】在springboot中写单元测试

    前言 很多公司都有写单元测试的硬性要求,在提交代码的时候,如果单测通不过或者说单元测试各种覆盖率不达标,会被拒绝合并代码.写单元测试,也是保证代码质量的一种方式. junit单元测试 相信绝大多数的J ...

  9. Xcode 5 单元测试(一)使用XCTest进行单元测试

    在Objc.io #1的Testing View Controllers中讲解的就是单元测试的相关内容.本文说下如何通过Xcode 5中集成的XCTest框架进行简单的单元测试. 什么是单元测试 首先 ...

随机推荐

  1. Ubuntu16.04+cuda9.0+matlab+opencv3.3+caffe服务器配置(问题汇总)

    Ubuntu16.04+cuda9.0+matlab+opencv3.3+caffe服务器配置(附遇到的错误和解决方法) 1.具体安装前需要的依赖包: ubuntu dependency: sudo ...

  2. windows下python3.4安装lxml提示"Unable to find vcvarsall.bat"

    "https://pypi.python.org/pypi/lxml/3.6.0"从这个网址直接下载对应的lxml包,exe格式的,直接安装,问题解决!

  3. linux命令之 ifconfig

    许多windows非常熟悉ipconfig命令行工具,它被用来获取网络接口配置信息并对此进行修改.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config).通常需 ...

  4. AXI总线简介

    AXI全称Advanced eXtensible Interface,是Xilinx从6系列的FPGA开始引入的一个接口协议,主要描述了主设备和从设备之间的数据传输方式.在ZYNQ中继续使用,版本是A ...

  5. Android线程间通信机制——深入理解 Looper、Handler、Message

    在Android中,经常使用Handler来实现线程间通信,必然要理解Looper , Handler , Message和MessageQueue的使用和原理,下面说一下Looper , Handl ...

  6. AM335x(TQ335x)学习笔记——GPIO按键驱动移植

    还是按照S5PV210的学习顺序来,我们首先解决按键问题.TQ335x有六个用户按键,分别是上.下.左.右.Enter和ESC.开始我想到的是跟学习S5PV210时一样,编写输入子系统驱动解决按键问题 ...

  7. linux下测试磁盘的读写IO速度

    有时候我们在做维护的时候,总会遇到类似于IO特别高,但不能判定是IO瓶颈还是软件参数设置不当导致热盘的问题.这时候通常希望能知道磁盘的读写速度,来进行下一步的决策. 下面是两种测试方法:(1)使用hd ...

  8. Struts2(七) Struts2访问Servlet的API

    当接受表单参数,向页面保持数据时.要用到Struts访问Servlet 的API .下面只做参考,有错误或不同意见可以发送邮箱2440867831@qq.com  .建议大家看struts文档,源代码 ...

  9. Spring 之BeanFactory(转)

    BeanFactory是Spring的“心脏”.它就是Spring IoC容器的真面目. Spring使用BeanFactory来实例化.配置和管理Bean.但是,在大多数情况我们并不直接使用Bean ...

  10. Splay入门解析【保证让你看不懂(滑稽)】

    BST真是神奇的东西... 而且种类好多呀... 我这个蒟蒻只学会了splay orzCJ老爷,各种树都会 好好好,不说了,直接说splay. 不知道splay是啥,,你也要知道平衡树是啥... 平衡 ...