Re: [讨论] Unit test 的撰写请益

楼主: GALINE (天真可爱CQD)   2022-11-09 14:19:33
※ 引述《shane87123 (阳光大肥宅)》之铭言:
先说在前面
虽然听起来很干话,但很多东西没有标准答案
有时是合适度的问题,也可能是喜好(品味?)的问题
同一个题目,实际的 code 长得不一样,可能也会用不同的方法处理
另外,除了资源丰富到人力充沛到不行的专案,以及几乎没有时程压力
的专案(很多开源专案属于后者),少有专案能把测试能做到真正完整
很多时候是取舍,花时间写多少测试,能 cover 到最大的范围
剩下的部分靠整合测试(包含自动与手动)来抓
经验能让人能更快做出效益更好的取舍
: 先说我对 Unit test 的看法:测试单元(可能是 function)的逻辑是否正确
: 常常会有一份 code 内其实呼叫了很多别份 code 的 function,
: 举例来说
: A() {
: B();
: C();
: if (check)
: D();
: }
在“unit test”的前提之下,A() 这个“单元”要怎么被定义?
- B() C() D() 的集合体?
- 负责分派逻辑前往 B() C() D() 的 router?
- A() 本身就做了一大堆事情,BCD 只是辅助?
- 其他?
在不同的状况下,该测的单元功能会完全不一样
适合的可能做法也完全不同
例如说对于状况1
- 也许该把那个 if 检查丢进 D(),让 A() 就只是依序呼叫三个其他人的传声筒
接着不测 A() 但认真测 B() C() D()
- 没有副作用可以,有副作用的话怎么验证副作用?
例如说对于状况2
- 是不是该把 B / C / D 弄成变量传进 A?
- 没在写 C 不知道 C 能怎么做,function pointer?
- 或是有某种类似 router 定义的东西,然后测 router 功能?
例如说对于状况3
- 全部 fake 是不是比较快?
- 是不是该把这个 function 拆掉?
- 诶,看到七层的 if else,真的觉得拆的掉吗?
- 诶,看到七层的 if else,真的觉得要伴他一生一世吗?
其实“重构”是个很常该被考虑的选项。
但当然,重构有时是个繁重的工作,也不见得是最常被选择的选项
这也是 TDD 曾经风行一时的一部分原因,因为脑袋正常的工程师走 TDD
会避免自己写出“啊,这要能测会把测试写的有够屎”的 code
但走 TDD 也可能写出“看得懂想测什么,但逻辑怎么会这样切”的东西
另外自己经验是通常测试难写是跟资料有关
“某些时候”如果非常辛苦的把资料 IO 全部 mock 一层,后面会好做一点
例如之前看过 api 专案平常线上是戳 MySQL 拿资料
在跑测试的时候直接开一个 in memory 的 sqlite 来当后端
测试逻辑会先把资料塞好好再来跑测试
于是就可以测“拿文章的时候会把内文特定 tag 换成其他 table 的资料”
之类资料连结度高的东西
走这条路的话不 fake 直接把逻辑跑完也是个好选项了
或者不用全部 fake,可以只 fake 几个
这大概不算是“单元”测试吧
但该测的有测到,而且在艰苦的工程之后可以轻松往上叠一堆其他测试
(但..如果没有那么多东西要测,这会不会太厚工?)
另外不同程式语言(或不同辅助函式库?)的状况会天差地北
例如上面的 A(),如果是 python 的话可能可以不改 code
直接用 patch() 把 B() C() D() 变成 mocker,会回传需要的值
测试就直接检查 B/C 是不是每次都被呼叫到
D() 是不是条件对的时候有呼叫到
因为 mock 容易写,全部 fake 掉会变成更有吸引力的选项
所以回到原本的题目:
全部 fake 跟全部不要 fake,选哪边?
我的回答是:
这两个都是选项,但不是只有这两个选项。
例如重构,例如在其他地方准备抽象资料层,也都是选择。
甚至手上的专案也可能变出不同的把戏。
这些都是能打的牌,要看场上环境怎样,再来取舍该打哪几张。
作者: hackfox (自家朘仔歪,嫌人尿桶漏)   2022-11-09 14:50:00
靠金燕,a.k.a姊姊
作者: FatFatPig (胖胖の猪)   2022-11-09 16:49:00
推推
作者: t64141 (榕树)   2022-11-09 16:56:00
推,满全面的分析
作者: Burwei (系馆守护神)   2022-11-09 19:41:00
作者: k7ji91ab5m (囧嘻嘻)   2022-11-09 19:58:00
推 说得很好
作者: markbex (马克杯)   2022-11-09 21:21:00
推 敝单位也是视情况测"服务"或是测"单一元件"
作者: viper9709 (阿达)   2022-11-09 23:56:00
推这篇
作者: sssyoyo (柚子)   2022-11-10 08:48:00
作者: devilkool (对猫毛过敏的猫控)   2022-11-10 09:18:00
推这篇
作者: strlen (strlen)   2022-11-10 14:14:00
我一直认为当初业界一堆在洗风向要写测试的主因之一 就是要利用测试来强迫大家做好封装与架构分离
楼主: GALINE (天真可爱CQD)   2022-11-10 14:31:00
也许喔,但 TDD 最大问题是写测试的人通常不控制 spec...
作者: NDark (溺于黑暗)   2022-11-10 17:23:00
就跟 product owner 其实不是真正能决定事情的人一样
作者: scottxxx666 (高高)   2022-11-10 21:55:00
作者: akitoex (神无月人鱼)   2022-11-10 22:58:00
作者: claymath (轮回的印记 藏在我眉宇)   2022-11-11 00:20:00
推一下
作者: nec1002 (训练自己 加强能力)   2022-11-15 15:12:00
找本专业书籍k一下

Links booklink

Contact Us: admin [ a t ] ucptt.com