$ ls ~yifei/notes/

单元测试的笔记和心得体会

Posted on:

Last modified:

编写优质测试的前提

  1. 明确最小单元,以及单元的功能点都有哪些。如果在写代码之前都没有明确功能有哪些,或者编写 功能已经跑偏了,那么测试究竟测些什么呢?
  2. 确定方案能够解决问题,然后再写测试,否则是徒劳的。

编写测试的基本原则

  • 每一个测试单元必须完全独立。每一个必须能够独立运行,以及在其他的测试组中组合运行,不管 他们的顺序如何。加载和清空数据应该使用 setup()teardown() 方法。
  • Sans-IO。也就是把逻辑和 IO 分开来,这样在测试的时候方便指定输入,以及捕获输出。
  • 尽量让测试跑的快一点。如果一个测试在几毫秒之内跑不完的话,开发就会慢下来,以至于没有人 再去跑这些测试了。如果实在有很耗费时间的测试,把他们单独放在一起定期执行。
  • 使用有描述性的长名字。实际代码中你可能使用 square() 这样的名字,但是在测试用你要用 test_square_of_number_2 这样的名字。
  • 如果你在开发某样东西的过程中被打断,可以写一个测试,这样当你回过头来的时候还能很快想 起来需要做什么。
  • 测试代码的另一个用途是作为新手的介绍。让别人来看你的代码的时候,看看测试就知道代码是干 什么的了。

如何测试包含 IO 的函数

  1. 使用依赖注入;
  2. 把 IO 操作放在单独的地方,在测试的时候 mock 这个类或者方法;
  3. 在 pytest 中还可以使用 fixture 提供依赖;
  4. 搭建一个测试用的数据库等服务器。

IO 依赖主要包括依赖文件和外部数据库。对于依赖文件名作为参数的函数,甚至可以认为是一个非常 差的实践。而且根据单一职责原则,一个方法也不应该做两件事,要么做计算,要么做 IO, 而接受 文件名作为参数就隐含了既要负责打开文件,又要负责处理文件中的数据。

但是不用文件名的话,有时候对于用户来说又不是很方便。建议把分成两个函数,一个只做计算, 另一个既打开文件,又做计算。

虽然使用 mock 的方式可能会提高速度或者更方便一些,但是这样的话又可能和实际生产环境的差异 过大,而且 mock 库也不是那么好找的。

编写测试的思路

从软件可靠性的角度,测试当然是越完备越好,但是不是每一个软件都是核弹控制器,还是要根据 实际情况折中一下。

追求功能测试

只需要按照功能点,把正常和常见的异常情况测试一下就好了。重点还是要先明确功能点有哪些。

追求 100% 覆盖度

按照代码逻辑分支测试,把代码的每一个分支的

  1. 入口参数是什么
  2. 出口参数是什么
  3. 副作用是什么
  4. 产生的异常是什么

都测试到。

测试的粒度

在每个 endpoint 上做集成测试。

不要过度测试。给门添加第二把锁会让门更安全一点,但是添加一百道锁并没有任何用,和两把锁是 一样的。加一百把锁的话,抢劫犯可能直接破门而入或者选择走窗户了。但是一百把锁反倒会让主人 进入更加复杂。单元测试也是同样的道理,不可或缺,但是要适可而止。

所以,总的来说,应该添加单元测试,但是要确保:

  1. 单元测试提供了价值,
  2. 单元测试比集成测试更适合这件事。

References

  1. https://tyrrrz.me/blog/unit-testing-is-overrated
WeChat Qr Code

© 2016-2022 Yifei Kong. Powered by ynotes

All contents are under the CC-BY-NC-SA license, if not otherwise specified.

Opinions expressed here are solely my own and do not express the views or opinions of my employer.

友情链接: MySQL 教程站