单元测试总结

定义

单元测试的对象是代码
单元测试即对代码中最小可测试的函数或者类进行验证,关注其内部逻辑,mock所有需要的服务

意义

保证“自己写的代码是自己想要的结果” 最有效的办法
单元测试总结_第1张图片

  • 单元测试对我们的产品质量是非常重要的。
  • 单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次有保证能够代码覆盖率达到100%的测试,是整个软件测试过程的基础和前提
  • 单元测试防止了开发的后期因bug过多而失控。据微软的统计,bug在单元测试阶段被发现,平均耗时3.25小时,如果漏到系统测试阶段,要花费11.5小时。

单元测试总结_第2张图片

  • 单元测试的性价比是最好的。据统计,大约有80%的错误是在软件设计阶段引入的,并且修正一个软件错误所需的费用将随着软件生命期的进展而上升。错误发现的越晚,修复它的费用就越高,而且呈指数增长的趋势。作为编码人员,也是单元测试的主要执行者,是唯一能够做到生产出无缺陷程序这一点的人,其他任何人都无法做到这一点
    单元测试总结_第3张图片
    通常单元测试的好处不仅是减少了bug,而且还促使你优化代码结构,设计出更易于理解和维护的代码。

用例设计

通过需求文档,给定用例的输入和预期输出
输入数据可以使被测试函数的输入数据,也可以是被测试函数读取的在函数内部读取的静态变量或者全局变量,也可以使调用子函数获取到的数据
预期输出可以是被测函数的返回值、被测函数的输出参数、被测函数所需改变的全局变量、被测函数更新的数据库、被测函数对kafka中的数据进行更新以及一些rpc(远程过程调用)相关的返回值。

驱动代码

单元测试总结_第4张图片
通过驱动程序生成测试用例、执行用例,最后生成测试报告。

桩代码

A函数调用B函数的返回值,但是B函数还没有实现,需要构造一个假函数来代替函数B,这个假函数就叫桩函数。

Mock代码

Mock代码和桩代码都是用例临时替换未实现的模块。
桩代码主要是通过桩函数的返回值来控制被测函数的代码执行路径的。
而Mock代码则是通过Mock的返回值来做断言用的。

单元测试特别耗时?

在《单元测试的艺术》这本书提到一个案例:找了开发能力相近的两个团队,同时开发相近的需求。进行单测的团队在编码阶段时长增长了一倍,从7天到14天,但是,这个团队在集成测试阶段的表现非常顺畅,bug量小,定位bug迅速等。最终的效果,整体交付时间和缺陷数,均是单测团队最少。
单元测试总结_第5张图片
单测,存在即合理。一方面,需要把单测放在整个迭代周期来观测其效果;一方面,写单测也是技术活,写得好的同学,时间少代码质量高(不是说写了单测,就能写好单测)

谁写单测?

· 开发同学
优点:开发人员对代码最熟悉,而且开发人员编程技能相对比较强,所以开发人员自己写单元测试效率上和覆盖率上都比较高缺点:开发人员平时写业务代码就要花费很多时间,有时候确实没有时间写单元测试;而且大部分开发人员没有太好的测试思想,单元测试可能只是写个最简单的用例就完了;自己写的代码自己测,往往都是不靠谱!

· 具有写单测的能力的测试同学
优点:测试人员有比较系统的测试思想,可以更好地保证用例的覆盖。而且通过写单测测试能更好地了解具体代码结构、流程,对于后续的业务测试也非常有利。
缺点:测试人员的编程技能相对比较弱,如果不同编程是无法开展单元测试的。并且测试人员对代码没有开发人员熟悉,效率会比较低。

增量还是存量

· 单测case针对增量代码
· 当存量代码出现大规模重构,后者质量暴露出极大风险时,都是推动补全单测的好时机

单元测试的阶段

一. 广义的单元测试,我们指这三部分的有机组合:
code review
静态代码扫描
单元测试用例编写

单元测试的指标

bug类指标(间接指标):连续迭代的bug总数趋势、迭代内新建bug的趋势、千行bug率
单测的需求覆盖度(50%以上),参与人员覆盖度(80%以上)
单测case总数趋势,代码行增量趋势
增量代码的行覆盖率(接入层80%,客户端30%)
单函数圈复杂度(低于40),单函数代码行数(低于80),扫描告警数

go单元测试框架选型

基本选型:testify + gomonkey 附加:httptest + sqlmock

Java单元测试框架选型

JUnit、TestNG

Python单元测试框架选型

unittest 、pyTest

单元测试标准

优秀的测试套件可以让人在更改代码时感到安全,从而使工作更为轻松;糟糕的测试套件会让人痛苦不堪,且浪费大量时间。编写好的、可维护的单元测试存在着一些特定规则,可使单元测试质量更高、更具效率。

1、尽可能简短
  因为我们测试的是由单个代码单元交付的单个功能,所以测试应该相当短是有意义的。至于具体需要多短就取决于多种因素,但通常不会超过几行代码。

2、切忌自我重复
  良好的编码实践应用于测试代码的方式与应用于生产代码的方式相同。从实践经验上来说,单元测试中最容易违反的规则之一是“Dont Repeat Yourself”。有些人甚至声称单元测试根本不应该共享任何代码。那是全然的废话。当然,我们希望尽可能保持测试的可读性,但是复制粘贴不是解决方案。

3、选择组合而非继承
  一旦了解了前面的两点,你可能会想要为自己的测试创建一些包含常用代码的基类。如果确实如此,请立马停止!这样的基类就像磁铁一样吸引着各种不相关的共享代码,并且增长非常迅速,直到接管你的项目、迭代、产品……为保证这些不被它逐步侵蚀,务必使用组合方式!

4、使其速度更快
  单元测试几乎可以一直运行。出于这个原因,一定要模拟外部依赖项和其他可能会减慢测试速度的东西,这通常是数据库、外部系统或文件操作。同时,不要做得太过——完全隔离被测单元也不是一个好的解决方案。

5、使其具有确定性
  每当听到有人拥有了95%的可用测试套件,并认为这已经足够好到可以投入生产时,我总是哭笑不得,因为单元测试应该必须保证100%可工作性。只有100%通过测试才意味着一切正常(对于单元,您还需要其他类型的测试)。如果你的单元测试看起来不可靠,请确保找到根本原因并尽快修复它。

6、不要为测试标注“可忽略”
  在第四条和第五条的基础上,必须要提及的是给测试添加“可忽略”注释,这并不是修复测试套件的方法,反而会使测试套件更加不可靠,因为它并不能避免回归Bug之类的问题。

7、测试你的测试
  这一条不是说为你的测试编写测试,而是指进行如突变测试、测试驱动开发或频繁地在代码库中“随机更改东西”这样的实践,以查看是否有测试失败。还可以经常做一些脑力练习,试图找出自己的测试中无法发现的对代码的潜在更改。

8、合理命名测试
  尽管我不相信每个项目都应该为测试使用一些花哨的命名约定,但合理的命名能够通过只读失败的测试用例的名称来判断代码的哪一部分被破坏了。

9、每个测试仅包含一个逻辑断言
  为了实现仅仅通过读取失败测试的名称就可以判断出错误的目标,需要的不仅仅是好的名称。一个测试检查也必须限制一些事情。因此,一个好的单元测试应该只包含一个逻辑断言,即只检查被测试方法的一个输出/副作用。

10、设计你的测试
  这是一个元技巧,它涵盖了本文中所有其他技巧以及在这里没有提到的技巧。对待测试要像对待/编写代码一样谨慎。考虑良好的设计原则和指标,如测试代码和生产代码之间的低耦合,以及代码的重复、死代码等。

你可能感兴趣的:(测试,单元测试)