别把单测玩出“坏味道”

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#006400","name":"user"}}],"text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"实际上,我从未想过,也从未打算过去写一篇关於单元测试(下述简称“单测”)的文章。早期我主要all in在电商领域,由于业务增速较快,我不可能要求开发人员花大量的美国时间去编写单测代码,以及满足单测覆盖率等硬性指标,换句话说,","attrs":{}},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000080","name":"user"}}],"text":"站在特定的业务角度而言,单测并非是强诉求,只要测试团队资源足够充裕(空间换时间),那么写不写单测最终达成的效果其实是一致的,这是事实","attrs":{}},{"type":"text","text":"。在我加入支付宝之后,面对支付业务的特殊性和复杂性,以及测试团队资源的严重匮乏,注定了单测的必要性和强制性。从理论上来说,85%的bug可以在单测阶段被发现,被修复,从整个迭代交付周期来看,单侧的覆盖率越高,项目整体的交付时间和缺陷数就越少。当然,论证单测的必要性似乎并无太大意义,最终还是要结合具体的业务场景而定,没有绝对的对与错,但把单测过度复杂化,陷于固定思维去思考问题和尝试说服别人,就一定是不对的,容易导致出现“跪久了,站不起来;站久了,跪不下去”的局面。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假设你所在的企业对单测有强诉求,那么单测应该由谁来写?怎么写?这是接下来本文讨论的重点。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#006400","name":"user"}}],"text":"单测的本质","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"单测毋庸置疑应该由开发人员来负责编写,你的逻辑,你最熟悉,而不是交给测试同学,我认为,","attrs":{}},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000080","name":"user"}}],"text":"测试团队的核心关注点应该是集中在功能测试阶段发力","attrs":{}},{"type":"text","text":"。那么如何定义单测?简单来说,单测代码就是在特定的条件下对目标代码执行正确性验证的一种特殊代码,其中关于“单元”的定义,我认为并不需要过于纠结,它的范围可以是一个目标函数,但同样也允许是一个类。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"实际上,我并不是专业的测试人员,对於单元测试、增量测试、全量测试、回归测试、集成测试,以及冒烟测试等不胜枚举的测试方法及手段常常是望洋兴叹,甚至无法准确归类。实际上,我比较赞成和认同google的做法,对于测试,简单分为3类,没那么多花样,如图1所示。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/03/0325382162684fa88331c74881ddf46a.png","alt":null,"title":"图1 google软件测试分类","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"boxShadow"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中小型测试仅关注目标函数的逻辑性验证,其它部分全部mock,强调的是效率;而中型测试关注的是多模块之间的交互性验证;最后大型测试则显得比较重和全面,我们可以理解为集成测试。那么我们的单元测试究竟应该如何归类呢?显而易见,单元测试归类在小型测试中是最适合不过的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#006400","name":"user"}}],"text":"单测究竟应该怎么写","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000080","name":"user"}}],"text":"单测的编写,最重要的就是要写得轻薄,强调的是效率,那就必须采取小步快跑模式","attrs":{}},{"type":"text","text":",如果单测代码还需要考虑连接数据库去验证SQL语法以及语义层面的正确性、访问各类中间件,甚至是触发RPC调用,那么这就不叫做单测,而是集成测试。","attrs":{}},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000080","name":"user"}}],"text":"实际上,笔者所在的团队,甚至大量的互联网企业对於单测的定位均不清晰,其中最主要的问题我认为还是把单测当做了产品质量保证的银弹","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"部分开发者认为,单测环节是整个测试环节中最底层,同时也是最重要的一个测试环节,全面的测试验证可以大幅缩短集成测试和迭代交付的时间窗口,后续放心重构,以及降低bug滞后的修复成本等,因此把大量的测试验证工作都前置在单测环节进行。而我认为,","attrs":{}},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000080","name":"user"}}],"text":"基础测试环节做的过重,只会弊多于利,反而会延长交付周期,增加单测代码的开发成本、维护成本,甚至导致开发人员走形式,走过场去编写单测代码","attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在单测环节,开发人员仅需关注逻辑单元的正确性,其它部分,该mock的就mock,想要跑得快,那就必须丢包袱,在合适的环节去做正确的事,不要总是想着集中在某一个点能解决所有问题。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"====== END ======","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"至此,本文内容全部结束。如果在阅读过程中有任何疑问,欢迎在评论区留言参与讨论。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"推荐文章:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/afb69dbad5329096215ffe9e1","title":"","type":null},"content":[{"type":"text","text":"源码系列 | 阿里 JVM-Sandbox 核心源码剖析","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/8304c894c4e38318d38ceb116","title":"","type":null},"content":[{"type":"text","text":"实操 | 剖析 Java16 新语法特性","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/6ad9f5278c0981de6971c70f4","title":"","type":null},"content":[{"type":"text","text":"专访 | 我与毕玄大师的对话","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/ae514bc05af1f16b151a351f8","title":"","type":null},"content":[{"type":"text","text":"算力 | 手写红黑树","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/d367c19896e4cef6fbb661cf7","title":"","type":null},"content":[{"type":"text","text":"硬核系列 | 深入剖析字节码增强","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/cef6d2931a54f85142d863db7","title":"","type":null},"content":[{"type":"text","text":"硬核系列 | 深入剖析 Java 协程","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/61868b3f66de36d32a5f1434f","title":"","type":null},"content":[{"type":"text","text":"白玉试毒 | 灰度架构设计方案","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/655943e5f85e6f79ffbd03047","title":"","type":null},"content":[{"type":"text","text":"新时代背景下的 Java 语法特性","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/92ba88c7926b5f5c6fbc11830","title":"","type":null},"content":[{"type":"text","text":"剖析 Java15 新语法特性","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/4d571787a3280ef3094338f9b","title":"","type":null},"content":[{"type":"text","text":"看门狗 | 分布式锁架构设计方案 -01","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/545a3accd173d6517ebd0ad59","title":"","type":null},"content":[{"type":"text","text":"看门狗 | 分布式锁架构设计方案 -02","attrs":{}}]}]}]}],"attrs":{}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章