什么是单元测试?
单元测试是测试代码中最小的功能单元的过程。软件测试有助于确保代码质量,是软件开发过程中不可或缺的一部分。软件开发的最佳实践是将软件编写为小型功能单元,然后为每个代码单元编写单元测试。您可以先将单元测试编写为代码。然后,在每次更改软件代码时自动运行该测试代码。这样,如果测试失败,您就能快速隔离出存在漏洞或错误的代码区域。单元测试可以强化模块化思维范式,并提高测试的覆盖率和质量。自动单元测试有助于确保您或您的开发人员有更多时间专注于编码。
什么是单元测试?
单元测试是一个代码块,用于验证较小、孤立的应用程序代码块(通常是函数或方法)的准确性。单元测试旨在根据代码块背后的开发人员理论逻辑检查其是否按预期运行。单元测试只能通过输入和捕获的断言(true 或 false)输出与代码块进行交互。
单个代码块也可以有一组单元测试,称为测试用例。一整套测试用例涵盖了代码块的全部预期行为,但并不总是需要定义完整的测试用例集。
当一个代码块的运行需要系统的其他部分时,不能将单元测试与此外部数据结合使用。单元测试需要隔离运行。代码的功能可能需要其他系统数据,例如数据库、对象或网络通信。如果是此情况,则应该改用数据存根。为逻辑上简单的小型代码块编写单元测试是最简单的工作。
单元测试策略
若要创建单元测试,您可以遵循一些基本技巧来确保涵盖所有测试用例。
逻辑检查
给定正确的、预期的输入,系统是否执行正确的计算并遵循通过代码的正确路径? 给定的输入是否涵盖通过代码的所有路径?
边界检查
对于给定的输入,系统如何响应? 系统如何响应典型输入、边缘用例或无效输入?
假设您期望输入的整数介于 3 和 7 之间。当您使用 5(典型输入)、3(边缘用例)或 9(无效输入)时,系统会如何响应?
错误处理
当输入中出现错误时,系统会如何响应? 是否提示用户输入其他内容? 软件是否会崩溃?
面向对象的检查
如果通过运行代码更改任何持久对象的状态,则该对象是否正确更新?
单元测试示例
以下是 Python 中一个非常基本的方法的示例,以及一些带有相应单元测试代码的测试用例。
Python 方法
def add_two_numbers(x, y):
return x + y
对应的单元测试
def test_add_positives():
result = add_two_numbers(5, 40)
assert result == 45
def test_add_negatives():
result = add_two_numbers(-4, -50)
assert result == -54
def test_add_mixed():
result = add_two_numbers(5, -5)
assert result == 0
单元测试有哪些优点?
单元测试在许多方面让软件开发项目受益。
高效发现错误
如果代码块中存在任何基于输入、输出或逻辑的错误,单元测试可以帮助您在错误进入生产环境之前发现它们。当代码更改时,您可运行同一组单元测试(以及集成测试等其他测试),并且可预期得到相同的结果。如果测试失败(也称为中断的测试),则表示存在基于回归的错误。
单元测试还有助于更快地查找代码中的错误。开发人员不会在调试活动上花费大量时间。他们可以快速查明存在错误的确切代码部分。
文档
务必记录代码,以确切地知道该代码应该执行的功能。也就是说,单元测试也可以充当某种形式的文档。
其他开发人员可阅读测试结果,以了解代码在运行期间预计会表现出哪些行为。他们使用这些信息来修改或重构代码。重构代码可使其表现更出色、结构更合理。可以再次运行单元测试,以检查代码在更改后是否按预期运行。
开发人员如何使用单元测试?
开发人员在软件开发生命周期的不同阶段使用单元测试。
测试驱动的开发
测试驱动的开发(TDD)是指开发人员先构建测试以检查软件的功能要求,然后再编写完整的代码。通过先编写测试,在编码完成并运行测试后,即可立即根据要求对代码进行验证。
完成代码块后
一旦代码块视为已完成,如果其未通过 TDD 进行开发,则应开发单元测试。然后,您可以立即运行单元测试来验证结果。在系统测试期间,单元测试也作为其他全套软件测试的一部分运行。它们通常是在完整系统软件测试期间运行的第一组测试。
DevOps 效率
将 DevOps 应用于软件开发实践的核心活动之一是持续集成和持续交付(CI/CD)。代码的任何更改都会自动集成到更广泛的代码库中,通过自动测试运行,然后在测试通过后进行部署。
单元测试与集成测试共同构成测试套件的一部分。这些测试在 CI/CD 管道中自动运行,以确保随着时间推移升级和更改的代码质量。
何时单元测试的优点会减少?
对于每个项目的每个代码块,并非始终需要对其中的每个测试用例运行单元测试。以下是一些可能省略单元测试的情况示例。
当时间受限时
即使使用生成式单元测试框架,编写新的单元测试也需要开发人员花费大量时间。虽然可以轻松生成基于输入和输出的单元测试,但很难执行基于逻辑的检查。
一旦开发人员开始编写测试,他们还会在代码块中看到重构的机会,从而分散完成测试的注意力。这可能会导致开发时间延长,并且产生预算不足的问题。
用户界面/用户体验应用程序
如果主系统关注外观和感觉而非逻辑,就可能没有太多可运行的单元测试。在这些情况下,其他类型的测试(例如手动测试)就是比单元测试更合适的策略。
遗留代码库
事实证明,几乎无法编写测试来封装现有的遗留代码,具体取决于所编写代码的风格。由于单元测试需要虚拟数据,因此为具有大量数据解析的高度互联系统编写单元测试也可能过于耗时。
快速变化的要求
根据不同的项目,在任何给定的工作冲刺阶段,软件都可能发展壮大、转变方向或完全删除整个部分。如果要求可能经常发生变化,那么每次开发代码块时就没有太多理由编写单元测试。
有哪些单元测试最佳实践?
我们提供了一些单元测试最佳实践,协助您充分利用自己的流程。
使用单元测试框架
为每个代码块编写明确的、完全自定义的单元测试相当浪费时间。每种流行的编程语言都带有自动测试框架。
例如,Python 提供 pytest 和 unittest 这两个不同的单元测试框架。测试框架广泛用于各种规模的软件开发项目。
自动执行单元测试
应根据软件开发中的不同事件触发单元测试。例如,可以在使用版本控制软件将更改推送到分支或部署软件更新之前使用单元测试。
单元测试也可以按设定的时间表在完整的项目上运行。在整个开发生命周期中,自动单元测试可确保测试在所有适当的事件和案例中运行。
一次断言
对于每个单元测试,应只有一个 true 或 false 的结果。确保您的测试中只有一条断言语句。在多个断言语句块中失败的断言语句可能会导致无法区分哪条语句产生问题。
实施单元测试
单元测试是构建软件的重要组成部分,但是许多项目并未为此投入资源。如果项目作为原型启动,是基于社区的小规模工作,或者只是快速编码,则由于时间限制,可能会不执行单元测试。
但是,如果从一开始就将单元测试作为标准实践来构建项目,此流程就会变得更容易遵循和重复。
单元测试和其他类型的测试有什么区别?
除了单元测试之外,还有许多其他类型的软件测试方法。这些方法在软件开发生命周期中发挥特定的作用:
- 集成测试会检查软件系统中设计进行交互的不同部分是否正确交互。
- 功能测试检查软件系统是否符合构建前概述的软件要求。
- 性能测试检查软件是否按照预期的性能要求运行,例如速度和内存大小。
- 验收测试是指利益相关者或用户组对软件进行手动测试,以检查其是否按预期正常运转。
- 安全测试检查软件是否存在已知的漏洞和威胁。这包括对威胁面的分析,涉及软件的第三方入口点。
这些测试方法通常需要采用专门的工具和独立的流程来检查软件。在开发基本的应用程序功能之后也会执行其中的许多方法。
相比之下,每次生成代码时都会运行单元测试。可以在编写任何代码后立即编写单元测试,并且不需要任何特殊工具即可运行。单元测试被视为最基本的软件测试类型之一。
AWS 如何帮助满足您的单元测试要求?
Amazon Web Services(AWS)为开发人员提供了大量优势。您可以开发和运行代码以及测试软件,例如通过单元测试和集成测试。还可以运行 DevOps 管道并寻求诸多发展机会。
AWS 开发人员工具为多种编程语言和编程使用案例提供集成开发环境(IDE)、插件和开发工具包。除其他优点外,这些工具还能提高单元测试的效率。
AWS Fargate 是一种无服务器、随用随付的计算引擎,可让您专注于构建应用程序,而无需管理服务器。可以在 Fargate 上轻松运行自动化单元测试软件,以此简化应用程序开发。
还可以在 AWS Marketplace 上找到第三方单元测试软件。可以使用所需的控件快速实施软件。AWS Marketplace 卖家提供灵活的定价选项,因此您可以在需要时按需求量付费。
立即创建账户,开始在 AWS 上进行单元测试。