自愈式自动化介绍:自动测试失败的补救措施

581 阅读9分钟

在CI/CD环境中,自动化测试是成功构建和部署的关键。当测试出现问题时,它们会导致构建失败,进行必要的研究和检查。当然,如果真的有错误,需要修复并重新运行。然而,经常发生的情况是,一个测试稍有变化,或者底层环境发生变化,可能导致测试在某些时候失败,但在其他时候不会。这些情况令人沮丧,我经常喃喃自语:"测试不能自己解决这些事情吗?"今天,答案是 "是的,他们可以!"或者,至少在某种程度上他们可以。

通常情况下,当我们考虑测试自动化时,我们正在寻找像WebDriver这样的工具或其他变化,它允许用户使用定位器对网页或应用程序上的特定元素选择动作和执行操作。如果这些定位器是一致的或没有变化,那么测试就有可能运行,并能够作出反应,因为它正在寻找的定位器或元素或它需要确定通过或失败条件的断言是存在的。当我们不能保证这些值是什么或者这些值有可能改变时,问题就出现了。即使页面上的元素没有变化,如果页面的内容是动态的,或者在渲染方式上足够复杂,渲染页面所需的时间可能会成为一个问题。我很熟悉这个问题,多年来我尝试了很多方法来有效地处理这个问题,从隐含的等待,到创建循环来确认一个元素的存在,然后再继续前进。这两种方法都有其问题。

人工智能和机器学习能帮助我们治愈我们的测试吗?

目前,我们正在努力利用人工智能和机器学习来帮助脚本适应变化,使我们的测试更加稳健。要深入了解人工智能和机器学习的细节,可能要花上一两本书的时间;但是,其核心是,这些工具的运作原理是进行小规模的测试和比较。这些比较创造了我们称之为 "代理 "的变量值。当一个代理被创建时,它被赋予了一个值,随着时间的推移,这个值会根据程序运行时的交互作用被向上或向下修改。

举个例子,如果一个程序有一个断言语句,它找到了正确的值,那么它就会根据它的成功来增加该代理变量(或不改变该值)。然而,可能会有价值改变或失败的情况。在这种情况下,代理的加权值将被递减,并在其位置上尝试另一个值。如果该值是成功的,第二个代理的计数值将被增加。这是一个基本的描述,但其想法是,脚本有能力根据页面或应用程序的反应方式来适应和尝试不同的东西。复杂程度可以而且可能会增加,但总体方法是一样的。通过创建这些代理,并采用人工智能和机器学习的原则,我可以让我的测试脚本有能力更加适应环境的变化,或者在页面的渲染方式或屏幕上加载的内容方面有多种选择。

让测试更具有包容性

当我创建测试用例时,我面临的最大挑战之一是我对如何与系统互动的理解。在大多数情况下,我会依靠有一组定位器(无论是ID,CSS类,还是XPath)来让我访问页面上的特定元素,例如能够与表单字段互动并按下按钮,点击特定的链接,前进到一个特定的页面,或接收一个必要的值来确定测试是否成功。如果我只有一个选项可以做到这一点(比如我只通过 "用户名 "这个ID访问一个用户名字段),我将能够顺利地运行我的测试。假设开发者选择让这个ID更加具体,比如说 "initialUsername"。在这一点上,我的测试很可能会失败,因为我正在寻找一个叫做 "用户名 "的值,而它已经不存在了。在正常情况下,我会去改变我的脚本,使任何提到 "用户名 "这个元素的地方现在都用 "initialUsername "代替。成功了吗?可能吧。消耗时间?肯定是的。

为什么这是个问题?我们依赖一个元素的一个特定属性来保证其准确性。如果该元素的值发生了变化,那么我们很可能会遇到这种脆性的情况。解决这个问题的方法是要有一个策略,能够捕捉或理解一个网络元素的多个方面以及如何与之互动。以Chrome浏览器为例,如果我们在网页上选择一个元素并点击 "检查",我们可以看到任何我们想与之互动的元素并不是孤立存在的。还有许多其他属性来定义这个元素。它可能是一个CSS类。它可能是一个名称。它可能有一个前面的文本标签。它可能被嵌套在一个标签的层次结构中。

重点是,一个定位器通常不只是由一个属性来定义。我们可以使用各种方法来获得该元素并与之互动。有一个稳定定义的ID当然是有好处的,但是如果页面还在加载,而我们还不能访问这个ID呢?我的脚本应该等待吗?我应该暂停,直到我可以确认这个ID吗?我可以,或者我可以让我的测试与元素的其他方面互动。同样,这又回到了拥有代理的想法,这些代理将是 "待命 "的。当然,我有我的首选代理,但在我的首选代理不能采取行动的情况下,我可以调用另一个代理来尝试不同的方法。如果这个方法是成功的,那么这个代理人的权重就会增加,而且随着时间的推移,我的测试可能会依靠这个备用代理人来确定它应该在什么地方和什么时候发挥作用。随着这种变化,我们给我们的测试提供了更多成功的机会。

一个使用TestIM的简单例子

在寻找AI自动化工具的例子时,有3个主要的例子。Mabl,TestIM, 和Testcraft。Mabl和Testcraft要么付费,要么需要与销售代表聊天;TestIM不需要与销售代表聊天,但需要注意的是,完整的 "自我修复 "实际上是未来的产品,还不是100%可用。

作为一个测试例子,我将使用TestIM(它有一个免费版本,你可以试用),做一个基本的产品搜索。在这种情况下,我们将寻找并确认我们可以找到一个特定的USB音频接口。

对于我们的搜索,我们将使用 "Focusrite Scarlett 8i6 "作为我们的搜索词,我们将比较一些数值来确定测试是否通过。

TestIM的好处是,任何人都可以介入并记录基本的测试开始,在他们提供的可视化块编辑器中结构化,或者导出代码加载到IDE中进行进一步修改。

如果你想建立一个测试,以下是步骤:

  1. 下载TestIM编辑器(最容易通过Chrome扩展获得的插件。
  2. 点击记录新的测试。
    • 转到www.amazon.com
    • 在搜索文本框中,输入 "Focusrite Scarlett 8i6"
    • 点击放大镜,或按 "Tab",然后按 "Enter"(我喜欢后一种方法,但两种方法都可以)。
    • 向下滚动到过滤标准项目,选择 "Focusrite "的复选框
    • 你应该看到一个搜索列表,其中引用了一些项目。
    • 滚动到 "Amazon Choice "图标并点击它。
    • 验证文本 "Focusrite Scarlett 8i6 (3rd Gen) USB Audio Interface with Pro Tools | First "是否存在。
  3. 完成后,点击 "停止",完成录音。
  4. 点击 "Save "来保存你的测试。给它起一个有意义的名字(我用了 "搜索Scarlett 8i6")。

通过这些步骤,你现在可以运行你的测试。需要提醒的是,在本地运行测试可能会出现各种不寻常的错误,难以调试。为了避免大多数这些问题,我鼓励你在 "TestIM-Grid "配置中运行测试。

一旦你确认测试运行成功,现在你可以检查测试中的项目,看看系统如何使用人工智能对元素进行分类和排序。

我如何能从中受益?

用户代理背后的原则以及人工智能和机器学习的工作原理是基本的;但是,正如所有事情一样,魔鬼在细节中。虽然听起来很简单,但要使你的测试脚本能够与这些代理和这种自我修复的方法一起运行,对于一个软件测试人员来说可能是一项重大的任务。幸运的是,目前许多可用的工具都利用人工智能和机器学习来作为其框架的一部分。另一件需要注意的事情是,当自我修复被打开或启用时,它可能会增加测试运行的时间,因为现在测试需要考虑多种方式与一个元素进行交互,而以前只有一条路径通往该元素并与之交互。根据运行的测试案例的数量,额外的时间可能是很重要的。尽管如此,即使它确实增加了时间,我认为增加的几秒钟或几分钟的运行时间超过了被通知失败的测试,而这可能是或不是一个合法的失败。更重要的是,修复和重新提交测试所需的时间肯定比运行大部分(如果不是全部)额外路径所需的时间长,以确保被检查的过程或程序有多次成功的机会。

结论

自愈式自动化听起来很神奇,但实际上,它是给你的测试提供多种成功的机会。无论我是用现成的工具来处理这个问题,还是与我的开发团队互动,准备好各种代理来创建测试,或者简单地创建多个路径来让我识别并与一个元素互动,自我修复自动化是一种可以随时使用的技术,不需要害怕或吓人。虽然我不能保证你的所有测试都能通过,或者说,易碎或易损的测试不会成为现实,但在部署自愈策略时,它们成为现实的几率会大大降低。