测试自动化的六大原则

开发 测试
我们在软件开发中使用测试来确保代码按预期工作。测试可以是手动的,也可以是自动的。手动测试类似于汽车制造商撞车,以验证它们在道路上是否安全。

​“测试”一词最初是指“用于测定贵金属的小容器”。这意味着测试是一种确定黄金或白银质量的方法。它也用于精炼有价值的合金,如锡。

后来,该术语在其他领域被采用,如今,在教育,医学或软件开发等环境中经常会发现它。然而,它的本质并没有改变:测试被用来提炼最终价值。

我们在软件开发中使用测试来确保代码按预期工作。测试可以是手动的,也可以是自动的。手动测试类似于汽车制造商撞车,以验证它们在道路上是否安全。它可以工作,但经常这样做太昂贵了,所以它通常在生产周期结束时完成。这种方法的问题在于,在此阶段发现的问题可能会将产品的发布延迟数月。

自动化软件测试具有完全不同的成本结构。有一个初始反转和定期维护,但是一旦tes自动化到位,我们就可以根据需要随时运行测试 - 只需几分钱。

通过测试自动化,开发人员可以获得持续的反馈,使他们能够在生产周期的早期发现问题。快速迭代可改进设计、提高质量和更安全的发布。

测试自动化原理

整本书都是专门围绕测试自动化主题编写的。这是每个开发人员在某些时候都需要掌握的技能,最好尽早完成。

以下是简化学习曲线的六个原则:

  1. 测试应能提高质量。
  2. 测试应降低引入故障的风险。
  3. 测试有助于理解代码。
  4. 测试必须易于编写。
  5. 测试套件必须易于运行。
  6. 测试套件应该需要最少的维护。

原则 1:测试自动化提高质量

质量是一个难以捉摸的概念。尽我们所能,不可能用数字来定义它。然而,当我们看到它时,我们就知道它。软件行业提出了许多衡量质量的指标:缺陷数量、代码覆盖率、CI错误率、测试失败率等。每一个都抓住了质量概念的某些方面。

自动化测试通过持续运行数百或数千个测试来改善质量指标;在缺陷进入生产环境之前发现缺陷,通知开发人员潜在的问题,并检查系统是否偏离了用户的期望。

撇开指标不谈,我们知道可靠的设计是质量的先决条件。当测试驱动开发时,开发人员可以轻松尝试不同的想法,并确定哪一个效果最好。测试驱动开发 (TDD) 和行为驱动开发 (BDD) 等实践利用了这一特性,取得了巨大的成功。

原则2:测试自动化降低风险

代码审查和同行编程虽然必要且富有成效,但不能依靠它来查找错误。经验表明,更多的眼球并不能转化为更少的错误。

可靠地发现错误的唯一方法是构建一个全面的自动化测试套件。测试可以从上到下检查整个应用程序。它们在造成任何伤害、发现回归并在各种设备和环境上运行应用程序之前捕获错误,否则手动尝试的成本会非常高昂。

即使团队中的每个人都是一个非常聪明的开发人员,不知何故从未犯过错误,第三方依赖项仍然会引入错误并带来风险。自动测试可以扫描项目中的每一行代码,以查找错误和安全问题。

原则3:测试帮助您了解系统

很多时候,开发人员回到几天前编写的代码,却意识到他们已经完全忘记了它是如何工作的。当开发人员必须处理其他人编写的代码时,情况会更糟。

通常,阅读测试是理解系统的最佳场所,因为它们通过示例来展示事物的工作原理。因此,当有疑问时,开发人员可以参考测试套件。

例如,测试可以向其他开发人员展示API应该如何响应,从而允许他们跳过查看文档。

ctx := context.Background()result, _, err := env.Client.Server.Create(ctx, ServerCreateOpts {   Name:       "test",   ServerType: &ServerType{ID: 1},   Image:      &Image{ID: 2},   SSHKeys: []*SSHKey{      {ID: 1},      {ID: 2},  },})if err != nil {   t.Fatalf("Server.Create failed: %s", err)}if result.Server == nil {   t.Fatal("no server")}if result.Server.ID != 1 {   t.Errorf("unexpected server ID: %v", result.Server.ID)}if result.RootPassword != "" {   t.Errorf("expected no root password, got: %v", result.RootPassword)}if len(result.NextActions) != 1 || result.NextActions[0].ID != 2 {   t.Errorf("unexpected next actions: %v", result.NextActions)}

不确定是否需要一行代码?注释掉它以查看哪个测试失败。有改进功能的想法吗?需要重构一段代码?尝试一下并运行自动测试。你会惊讶于你能从系统的测试中学到多少东西。

原则4:自动化测试应该易于编写

有些测试从手动测试开始,然后自动完成。但是,这通常会导致过于复杂,缓慢和尴尬的测试。当测试和代码具有一定的协同作用时,最好的结果就会出现。编写测试的行为促使开发人员生成更多的模块化代码,这反过来又使测试更简单,更精细。

测试的简单性很重要,因为为测试编写测试是不切实际的。代码也应该易于读取和写入。否则,我们就有可能在测试本身中引入失败,从而导致误报和片状。

许多测试框架使用域特定语言 (DSL) 以简单的英语定义测试。也许最值得注意的例子是小黄瓜测试框架使用的语言Gherkin:

Feature: Is it Friday yet?Everybody wants to know when it's FridayScenario: Sunday isn't Friday  Given today is Sunday  When I ask whether it's Friday yet  Then I should be told "Nope"

总而言之,在编写测试时坚持一些基础知识是个好主意:

  • 每个测试只写一个断言。
  • 将代码与测试分开,即生产代码不应包含测试。
  • 保持测试彼此独立,因为依赖关系很快就会滚雪球般地变成令人头痛的混乱。
  • 将测试重叠保持在最低限度,即不要测试相同的代码两次。
  • 不要破坏测试代码的封装。不,仅测试外部接口。

原则5:测试应易于运行

如果开发人员需要打开清单才能开始测试运行,则测试的运行频率不会达到应有的水平。

理想情况下,每次代码更改时都会运行测试,而无需任何干预。我们在这里很幸运,因为开发人员工具非常复杂。大多数现代IDE可以检测文件中的更改并自动启动测试套件,同样可以通过nodemon,live reload,fswatch或testmon等命令行程序来实现。

说明:VS 代码在后台运行测试

为了使测试易于运行,必须满足一些条件:

  • 幂等性:测试不应有副作用。副作用包括写入文件、保存到数据库或通常更改数据。开发人员应该能够安全地运行任意次数的相同测试。
  • 确定性:在给定相同输入的情况下,测试应始终给出相同的结果。当测试需要开发人员无法控制的外部数据(例如日期/时间或来自 API 的响应)时,应使用模拟或存根伪造这些数据。
  • 独立:测试应该彼此独立,开发人员必须能够以任何顺序运行它们。
  • 轻量级:测试必须足够轻量级,以便在合理的时间内在开发人员的计算机上运行。
  • 粒度:开发人员必须能够逐个运行测试套件。

在开发人员的机器上运行测试只是等式的一部分。测试还必须在持续集成管道中进行。您的 CI/CD 管道充当质量门;它在每次提交时运行测试套件,提供即时反馈,并允许开发人员检测何时引入故障。

原则6:自动化测试套件需要低维护

最后一个原则是前五个原则的必然结果。也就是说,如果你很好地满足了其他人,你就可以免费获得它。尽管如此,这很重要,所以最好把它说出来。

开发人员希望做有创意和有益的工作。自动化使机器能够处理测试的苦差事。当测试易于编写且频繁执行时,将创建正反馈循环。开发人员倾向于欣赏自动化如何使他们的生活更轻松,因此被激励编写和维护测试。

当然,需要一些定期维护来保持测试的良好状态。以下是编写和维护测试套件的四条建议:

  • 编写足够多的测试以使其有效(但不是更多)。如果错误溜走,则需要更多的测试。相反,如果您发现测试因小更改而中断,则需要删除一些测试。
  • 选择适合该情况的最佳测试类型。单元测试快速且以激光为重点,而端到端测试涵盖 UI,并且更繁重且更全面。遵循测试金字塔的测试套件具有健康的各种测试。

  • 保持测试的可靠性。当代码正确时失败的测试称为误报。有时无缘无故失败的测试称为片状测试。两者都会在测试套件中引起问题,因为它们是巨大的时间浪费者和挫折感的来源。
  • 保持测试速度快。一个缓慢的测试套件将阻碍开发。

结论

那些认为测试成本高昂的人并不完全意识到质量差的代价。单独来看,错误和缺陷对产品价值的影响可能难以衡量,但如果它们得不到解决,它们可能会迅速失控。幸运的是,您可以通过构建和完善自动化测试套件来防止这种情况,从而为出色的开发人员体验和出色的高质量软件奠定基础。​


责任编辑:华轩 来源: 今日头条
相关推荐

2012-02-07 13:29:25

云计算HP

2022-05-31 21:08:41

云原生容器

2010-09-09 13:54:06

DIV CSS

2013-11-13 10:20:13

运维管理数据中心

2015-08-24 10:30:25

数据中心选址

2013-01-16 15:41:59

SDNJuniper

2012-02-06 10:28:21

云计算

2014-07-26 09:56:43

WOT2014敏捷开发PO

2018-11-02 15:05:19

IT运维故障操作

2022-02-25 15:56:44

云计算架构基础设施

2009-06-18 11:12:00

2012-03-15 11:15:13

Java设计模式

2012-03-05 13:58:34

设计模式里氏置换

2012-03-07 10:40:19

Java设计模式

2012-03-07 11:03:13

Java设计模式

2020-06-09 07:00:00

面向对象编程编程原则

2015-09-23 17:12:18

API设计原则

2010-03-31 17:26:52

SaaS

2012-03-08 10:57:00

Java设计模式

2015-09-24 08:52:53

API设计原则
点赞
收藏

51CTO技术栈公众号