写点什么

单元测试 vs 集成测试,你该怎么选?

2021 年 1 月 12 日

单元测试 vs 集成测试,你该怎么选?

在 1998 年,Kent Beck 编写了 sUnit,一个面向 SmallTalk 的单元测试框架。之后,他将这个框架移植到 Java,即 jUnit。从那时起,xUnit 框架扩展到那些最流行的编程语言。比较新的语言,如 Golang 和 Rust,已经将测试直接合并到编译器和标准库中。



但是单元测试并不是唯一。还有集成测试和性能测试等等。在我看来,集成测试和单元测试是健壮软件的基石。因此,今天让我们看看单元测试与集成测试之间的区别,以及你什么时候该选择哪种测试。


什么是一个单元?



一个单元是逻辑上分离的最小代码块


单元测试是一种孤立地测试尽可能小的代码片段的测试。那么,什么是一个单元?


术语“单元”来自数学。数字 1 被认为是单元,因为它是最小的自然数。它是最小的正整数。以此类推,你源代码的一个单元就是逻辑上与其余代码分离的最小代码片段。它是一个完整的且逻辑上不同的代码片段,而且是最小的部分。


在大多数编程语言中,你的单元会是一个函数或方法调用。


单元测试的好处是,如果你的代码由独立的小片段组成,那么,为它们编写测试就相当容易。这种易编写性意味着你可以在开发功能时完成单元测试。


与其它形式的测试相比,单元测试的执行时间相当短。这意味着你可以频繁运行单元测试。随着软件的成熟,一套单元测试是防止回归和降低维护成本的有力工具。


追溯单元测试


在考虑将单元测试添加到现有软件时,需要考虑成本和收益。


单元测试的一个关键假设是,被测试的软件很容易分成不同的单元。在没有考虑单元测试编写的软件中,这个假设很少成立。向现有软件添加单元测试通常是一种非常好的方法,来稳定软件并防止将来回归,但是重构代码来支持简单的单元测试可能需要大量工作,甚至会引入新的缺陷。在考虑将单元测试添加到现有软件时,需要考虑成本和收益。如果你的代码正在工作,如果代码很少需要修改,如果代码不容易进行单元测试,那么加入单元测试的好处可能无法保证成本。在这些情况下,可以依靠集成测试来防止该领域的缺陷。


什么是集成测试?


集成测试聚焦于整个软件栈


如果单元测试的哲学是基于这样一种认识,即测试小的独立代码片段是防止回归的一种好方法,那么集成测试是基于这样一种理解,即事情通常在边缘状态出错。外部世界是一个混乱的地方,它与你代码交互的地方通常是意外发生的地方。


你可以通过单元测试实现 100%代码覆盖率,但仍然发现你的软件失败。你可能试图从错误的位置读取文件,或者你的软件可能从一个调用的服务得到预期之外的输出,或者它可能以一种无效的方式调用数据库。


尽管单元测试应该快速运行并且数量众多,但是一个好的集成测试策略应该关注较少数量的高影响测试。


这些测试应该跨越单元测试无法跨越的所有界限,写入文件系统,接触外部资源,等等。


当集成测试棘手时


某些外部系统确实很难集成到测试中。这是因为它们在现实世界中有着无法消除的副作用:金融交易、电子邮件发送、物理移动一个喷漆机器人等。在你在测试中放弃并避开它们之前,找找解决方案。


许多外部系统有一个文档化的方法来在集成测试中使用它们。支付处理程序通常有测试信用卡号,可以设置具有测试邮箱账户的测试用户来测试邮件发送。


集成测试越接近真实世界的交互,就越有可能发现问题并提供真正的价值。


Amazon SES——Test email addresses


Paypal——Test credit card numbers


UPS——Test api mode


一个电子商务例子


假设你正在编写一个简单的电商网站,一个简化版的 amazon.com。这里的细节很重要,所以我们假设,你会使用 PostgreSQL 作为你的数据存储,使用 PayPal 进行支付,使用 UPS 进行发货、使用 Amazon Simple Email Service 来发送电子发票邮件。


单元测试:


单元测试策略将以一种孤立的方式测试应用程序的逻辑。这可能包括:


  • 测试税费计算逻辑是否正确地计算出各个司法管辖区的税费

  • 测试放置到购物车数据结构中的项目是否被正确添加

  • 测试折扣代码是否被正确使用


这些领域中的每一个都可能有几个测试。每个测试将验证一小部分功能。单元测试的能力来自它们的数量、简单性以及它们的执行速度和便捷性。


集成测试:


另一方面,你的集成测试将专注于测试你的电子商务代码与其它系统的交互。这意味着不仅要测试与数据存储的集成,还要测试与邮件发送服务的集成、与支付服务的集成等等。这些可能包括:


  • 测试是否可以从外部运输服务中检索运输费率

  • 测试发票是否可以生成并正确发送

  • 测试订单信息是否可以持久化并从数据存储中正确检索

  • 测试交易是否可以发送并被支付处理程序正确处理


这些功能中的每一个都可能需要一个或两个集成测试来验证。这些测试运行起来会比较慢,可能涉及一些安装和拆卸步骤。结果是,每个测试的代码覆盖率会相当大。这些测试将通过捕获单元测试不能捕获的问题来产生价值。然而,维护成本和执行时间可能会比较高。


集成测试 vs 单元测试


是时候正面比较了


那么,应该首选哪种类型的测试呢?单靠两者中的任一个都是不够的。这两者都是综合测试计划的一部分。让我们直接比较一下:



基于理想化测试的工作软件


每种情况都是独特的,基于在其它情况下有效的建议不应盲目遵循。


现在我们明白了,单元测试不应该触及文件系统,而集成测试应该只集成松散的组件。但实际上,将测试划分为两个明确的类别有点太简单了,如果我们只关注定义,我们就会忽略目标,即正确的工作软件。


一些非常有想法的开发者认为单元测试可以并且应该读写数据库。其它人则认为单元测试是一种浪费,粗粒度的集成测试提供的价值最大。


问题是,每种情况都是独特的,基于在其它情况下有效的建议不应盲目遵循。需要牢记的一个问题是,这个测试要捕获什么类型的缺陷。如果每个测试都是经过深思熟虑编写来提升软件可靠性的,如果测试在不再有价值时被删除,那么随着时间的推移,将发现为特定项目提供最大价值的特定测试方法。


原文链接:


https://blog.earthly.dev/unit-vs-integration/

2021 年 1 月 12 日 14:351013
用户头像

发布了 118 篇内容, 共 37.9 次阅读, 收获喜欢 195 次。

关注

评论 1 条评论

发布
用户头像
将测试金字塔永远记在心里,写代码的时候就想想这个模型,保证你不会把事情最差
2021 年 01 月 12 日 16:28
回复
没有更多了
发现更多内容

不以涨工资为目的的技术学习,都会以失败而告终

陆陆通通

程序员 面试 涨薪

在谈判中,你有哪些属于自己的独特的方法和技巧?

Yolanda

从【炉石传说】到矩阵运算

Tango

Python 学习 矩阵 数学

运维 Harbor 镜像仓库的法宝:Operator

亨利笔记

Kubernetes 容器 k8s Harbor operator

“WHY-HOW-WHAT”这个被誉为伟大的领袖如何激励行动的黄金圈法则,非常值得大家学一学!

数列科技杨德华

思维方式

决定我们认知深度的究竟是什么?

石君

深度思考 方法论 连接

前端如何搞监控总结篇

大前端洞见

前端监控 监控 全链路监控

死磕Java并发编程(4):happens-before是什么?JMM最最核心的概念,看完你就懂了

七哥爱编程

Java Java并发 happens-before JMM

“消灭你,与你无关”——阿里巴巴的风险 | 旧文重发

赵新龙

阿里巴巴 风险 蒋凡 IPO

除了负载均衡的算法,你还应该知道这些

松花皮蛋me

Java 负载均衡 分布式

爱他,就让他走?

Selina

团队管理 领导力 团队协作

Golang 真的好用吗?

极客时间

golang 编程语言

程序员5分钟:你了解32位带符号的整型吗?

顾仲贤

程序员

Harbor和Dragonfly双剑合璧 打造容器镜像运维新模式

亨利笔记

容器 k8s Harbor dragonfly 镜像

OpenCV 在 Android 上的应用

fengzhizi715

android OpenCV 计算机视觉

批注MYSQL开发规范,助你了解其背后的“道”

三石

数据库规范 规范背后的原理 白话规范

我不是怕表错态,而是怕我会不自觉地捍卫它

池建强

个人成长

vSphere 7融合Kubernetes,构建现代化应用的平台

亨利笔记

Kubernetes 容器 云原生 k8s vSphere

微信朋友圈为什么没有阅读数?

彭宏豪95

微信 产品 产品设计

别总说CMS、G1,该聊聊ZGC了

猿人谷

CMS G1 ZGC JVM

程序员都应该了解的运维知识经验

松花皮蛋me

DevOps 分布式 运维

回"疫"录(3):让人怀念的普通一天

小天同学

疫情 回忆录 现实纪录 纪实

世界知识产权日碎碎念

尹晓铁

成长 随笔 知识产权

ZGC都出来了,你还不懂G1?

岁月安然

G1 JVM

我为什么选择infoq写作平台

三爻

像产品设计一样思考、像程序运行一样执行

水色

祝这些不要脸的王八蛋同行家里着火

二爷

回"疫"录(4):见证历史

小天同学

疫情 回忆录 现实纪录 纪实

程序员5分钟:你的程序占用了多少内存?

顾仲贤

程序员

Java并发编程系列插曲——对象的内存结构

孙苏勇

Java 内存模型 面向对象 ClassLayout

程序员陪娃漫画系列——看医生

孙苏勇

生活 程序员人生 陪伴 漫画

NLP领域的2020年大事记及2021展望

NLP领域的2020年大事记及2021展望

单元测试 vs 集成测试,你该怎么选?-InfoQ