随笔十一:测试概述
作者:互联网
测试一直是编程的一部分。
测试发展的核心是开发人员驱动的自动化测试实践。
自动化测试可以防止缺陷逃逸,这些缺陷可能会影响到用户。在开发周期中,一个缺陷被捕获的时间越晚,它的成本越高。
“捕获缺陷”只是做自动化测试的一部分动机。
另一个同样重要的原因是支持变更的能力。无论添加新功能还是进行保持代码健康的重构,或是进行更大的重新设计,自动化测试都可以快速发现错误,这使得有信心地更改成为可能。
迭代速度更快的公司可以更快的使用不断变化的技术、市场条件和客户口味。自动化测试可以保证质量。越想快地改变系统,九月需要一种快速的方法来测试他们。
编写测试的行为也改进了系统的设计。
作为代码的第一个客户,测试可以告诉你关于设计选择的很多信息。
- 系统和数据库的耦合是否过紧?
- API是否支持所需的测试用例?
- 系统能处理所有的边界用例吗?
编写自动化测试会迫使你在开发周期的早期面对这些问题。
- 这样做通常会使得软件更加模块化
- 具有更大的灵活性
为什么要写测试?
一个间的的测试,通常包括以下四部分:
- 一个你正在测试的单一行为,一般来说是一个你正在调用的方法或者API
- 一个特定的输入,可能是一些需要传递给API的数值
- 一个可观察到的输出行为
- 一个受控环境,例如一个单独隔离的进程
执行以上流程,你将了解系统是否按预期运行。
创建和维护一个健康的测试提高见需要正真的努力。
确定测试并不是时候才考虑的事情,专注于质量和测试是我们工作的一部分。
编写、运行、响应
自动化测试包括三个活动:编写测试、运行测试和对测试失败做出相应。
一个做自动化测试是一小段代码,通常是一个函数或者方法,它会调用你要测试的大型系统的某个独立部分。
测试代码首先设置一个预期的环境,然后调用该系统,通常在已知输出的情况下,最终验证其结果。
写测试和写好测试是不同的。
编写测试只是自动化测试过程中的第一步。在写了测试之后,需要频繁地运行他们。
自动化测试的核心是一遍又一遍地重复同一个动作,只有当某个东西被破坏时才需要人的注意。
测试即代码的另一个好处时很容易将他们模块化,以便在各个环境中执行。
强调快速修复中断的测试用例,以便在整个过程中保持高度的信心。
测试代码的好处
将编写测试作为提高生产力和速度的一种手段的想法可能看起来是不可能的。毕竟,编写测试的过程和实现一个特性所花费的实践是一样长。
在测试中投资有一些好处:
-
- 更少的测试:大多数缺陷会在代码提交之前被捕获。
- 增强变更的信心
- 改进的文档:所有文档都是不可靠的,从过时的需求到丢失的边界用例,文档和代码之间的关系通常是很脆弱的,
- 更简洁的评审:如果代码评审包括了演示代码正确性、边界情况和错误条件的全面测试,则代码评审将花费较少的精力来验证代码是否按预期工作。
- 深思熟虑的设计:为新代码编写测试时验证代码自身API设计的一种使用方法。如果代码很难测试,通常是因为被测试的代码承担了太多的职责,或者有很难管理的以来关系。精心设计的代码应该是模块化的,避免紧耦合,并专注于特定的职责,尽早解决设计问题通常意味着以后更少的返工。
- 快速、高质量的发布
设计测试套件
要学会如果设计和执行测试套件的知识,这些知识是通过犯错和时候梳理学到的。
教训一:工程师喜欢编写更大的、系统级的测试,但是这些测试比那些小测试执行速度要慢,而且结果不可靠,更难调试。
减少痛苦的愿望趋势团队开发出越来越小的测试没结果测试云心更快、更稳定,通常也更少痛苦。
结论:每个测试用例都应该有两个不同的维度,粒度和范围:
-
- 粒度:是指运行测试用例所需的资源,如果内存、进程、时间;
- 范围:是指我们正在验证的特性代码路径。
粒度和范围是相互关联但是有截然不同的概念。
测试粒度
一个测试的粒度,并不是由它的代码行数决定的,二十由他如何运行、允许它做什么以及它消耗了多少资源决定的。
事实上,某些情况下,我们对小型、中型、大型的定义实际上被转化为测试基础设施可以在测试上实施的约束。
小测试可以在一个进程中运行,中型测试在一台机器上运行,大型测试则在任何需要的地方运行。
重要:小型测试进行严格的限制,更容易实现高速度的和确定性,虽则和测试粒度的增大,很多限制也都被放宽了。
中型测试有更大的灵活性,但是也有更大声的不确定性。
大型测试仅用于最复杂的和最困难的测试常见。
小型测试
小型测试是最受欢迎的。主要约束时小测试必须在单个进程中运行。
这意味者执行测试的代码必须在与被测试代码相同的进程中进行,不能将一个单独的测试进程连接到其他服务器,这也意味着你不能在测试中运行第三方程序,比如数据库。
小型测试的另一个重要限制是不允许他们休眠、执行IO操作或者进行任何其他阻塞调用。
这些限制是确保不会访问令他们运行速度变慢或者带来不确定性的主要源头。
这些限制一开始可能开起来有些过分,但是考虑一下一个由几百个小测试用例组成的测试套件全天的运行的情况。
中型测试
中型测试可以跨多个进程,使用线程,并且可以对本地机器进行阻塞操作,包括网络调用。
唯一的限制是不允许中型测试对本地机器以外的任何系统进行网络调用,换句话说,就是必须在同一台机器中运行。
运行多个进程的能力带来了许多可能性,例如可以运行一个数据库实例来验证正在测试的代码是否在一个更实际的环境中正确的集成了。
不幸的是,随着灵活性的增加,测试变得缓慢和不确定的可能性也随着增加。
编写中型测试时,“安全性”是不高的,工程师需要更加小心。
大型测试
允许测试和被测试跨越多台计算机。例如测试可能在远程集群中的系统运行。
增加灵活性会增加风险。测试速度变慢、不确定性增加。
我们主要为完整的端到端测试而写大型测试,这些测试更多的是验证配置,而不是代码片段,另外为测试那些不可能使用测试替身的遗留组件也会使用大型测试。
我们需要将大型测试和中小型测试隔离开来,只在构建和发布过程中运行它们,以免影响到开发人员的工作流程。
所有测试的通用属性
所有测试都应该力求封闭性:测试应该包括设计、执行和环境回收所必须的所有信息。
测试因该尽可能少地假设外部环境,例如测试的运行顺序。例如他们不应该依赖共享数据库。这种测试在大型测试中更具有挑战性,但应该确保隔离。
测试因该只包括测试相关行为所需的信息。
保持测试的清晰和简单,有助于评审者检查代码是否按照它所说的做了。
清晰的代码还有助于在出现执行失败时进行诊断。
人们读代码的时间远远大于写代码,因此请确保你编写的测试是易读的。
测试范围
窄范围测试的设计目的是在代码库的一个小的、集中的部分中验证逻辑。
中型范围的测试一再验证少量组件之间的交互。例如服务器与数据库之间的交互。
大范围测试旨在验证系统中有几个不同部分的交互,或者未在单个类或方法中表的涌现行为。
我们将单元测试成为窄范围的测试时,我们指的是被验证的代码,而不是正在被执行的代码。一个类有很多依赖,但是我们关注的是正在我们需要验证的代码。
窄测试往往是小型测试,宽测试一般是中型或大型测试,但是情况并非总是如此,例如可以对服务器编写一个范围广泛的测试,该测试涵盖了服务器端点的所有正常解析、请求验证、业务逻辑,但粒度较小,因为它本身使用替身来表示所有进程依赖项,例如数据库或者文件系统。
我们鼓励工程师编写更窄的测试,作为一个非常粗略的指导原则,我们倾向于大约80%的窄范围单元测试即验证大多数业务逻辑的测试,15%是验证两个或者多个组件之间的交互的中等范围集尘测试;以及5%是验证整个系统的端到端的测试。
冰激凌桶模式,工程师白那些了许多端到端的测试,但是很少编写继承或者单元测试,这样的套件往往速度慢,不可靠,而且很难使用。这种模式进程出现在以原型开始并迅速投入生产的项目中,这种项目会不停地处理测试债务。
漏斗模式中有许多端到端的测试和单元测试,但是集成测试很少,它并没有“冰激凌筒”那么糟糕,但它仍然会导致许多端到端的测试失败,而通过一系列中等粒度的测试,这些失败可能会被更快、更容易的捕获。当紧密耦合使独立实例化单个依赖项变得困难时,会出现沙漏模式。
当考虑自己的组合时,可能需要一个不同的平衡,如果你强调集成测试,你可能会发现测试套件需要更长的时间才能运行,但会捕获组件之间的更多问题。当你强调单元测试时,你的测试套件可以非常快速的测试完成,并且捕获许多常见的逻辑错误。但是单元测试无法验证组件之间的交互。
一个好的测试套件时包含适合框架和组织现状的不同测试粒度和范围的组合。
碧昂斯规则
经常会被问道:哪些行为或则和属性实际上需要测试?
答案是:测试所有不想被破破坏的东西。
如果想确信某个系统展示出现了某个特定的行为,那么唯一能使用的方法就是为整个特性编写一个自动化测试。这里包括所有常见的容易出问题的地方,例如性能、行为正确性、可访问性或者安全性。
代码覆盖率
代码覆盖率是衡量功能代码行被测试的比例。
代码覆盖率通常被视为了解测试质量的黄金标准指标。
大型测试套件的陷阱
脆弱测试中一些最糟糕的情况来自对mock对象的误用。
除了脆弱性,大型的测试套件还会运行的越来越慢。
如果不能保证测试套件的确定性和运行快速型,那么它将成为提高生产力的障碍。
与大型测试套件共处的方式是给予它们足够的尊重。总体来说,就是把测试当作生产代码,一旦某个简单的变更花费大量时间,一定要花点精力让测试不那么脆弱。
本章重点
自动化测试是实现软件变更的基础。
要进行大规模测试,必须实现自动化
为了保持健康的测试覆盖率,平衡的测试套件是必要的
”如果你喜欢它,你就应该测试它“
改变组织中的测试文化需要时间
标签:十一,验证,代码,套件,概述,测试,编写,随笔,运行 来源: https://www.cnblogs.com/use-D/p/16421827.html