当前位置: 首页 > news >正文

端到端测试(End-to-end tests)重试策略

作者|Giuseppe Donati,Trivago公司Web测试自动化工程师

整理|TesterHome


失败后重试,是好是坏?

为什么要在失败时重试所有测试?为什么不?

作为Trivago(德国酒店搜索服务平台)酒店搜索前端QA团队,过去几年我们试图避免针对失败的暴力重试策略,我们宁愿只在选定的情况下执行测试重试。

最近,当我们为新的前端 Web 应用程序转而采用持续部署方法时(该方法允许开发人员自主合并和发布某些拉取请求),我们比以前更需要可理解且稳定的测试结果。

因此,为了确保对测试结果有足够的信心,并避免拖慢软件开发生命周期,对拉取请求的自动检查显示尽可能少的 "危险信号 "变得更加重要。至少在某些情况下,要求和确定性结果与成功率之间的平衡发生了变化。

我们不同的重试策略

由于我们的新 Web App 存储库位于 GitHub 上,并且我们在 GitHub Actions 中为其运行端到端自动化测试,因此我们通过针对不同的测试套件或工作流程采用不同的重试策略来满足新的要求。他们是:

  • 无论出于何种原因,在失败时重试任何内容 -> 在每次提交时运行的“核心”测试上实现。在任何情况下重试的原因是为了增加对拉取请求的信心,而不会对反馈周期造成太大影响。测试很少,并且可以快速且低成本地再次执行。

  • 根据特定的失败原因对失败进行过滤重试 -> 在“扩展”测试上实现,利用我们的测试自动化框架的重新运行检测器插件部分。这是一个插件,用于将测试失败与自定义异常列表(例如环境问题)进行比较,以便触发它们进入第二个重新运行阶段。一个示例可能是在搜索酒店时遇到空结果列表,假设这可能是由后端中断引起的。我们认为,某些完全或主要属于外部因素的失败原因应该是在运行所有其他测试时在最后重试相同测试的有效理由。异常子字符串的示例可以是:Session timed out or not foundEmpty page detectedError communicating with the remote browser

  • 手动重试场景子集 -> 添加到我们箭袋中的最新箭头。这也是属于“扩展”测试执行的一个功能,它简化了实际故障的识别,同时使我们的 QA 工程师能够更好地控制测试执行时间和资源使用。我们将在接下来的段落中深入探讨细节。

查看GitHub Actions中的trupi扩展工作流程

现在介绍一些关于如何执行测试的背景知识。

我们的 Web 平台的自动化测试由内部开发的名为 trupi 的框架执行。Trupi 基于 Selenium 和 Cucumber,并用 Java 编写。

我们的测试方案是用 Cucumber 编写的故事。我们有一些 "核心 "测试,每当一个新的拉取请求被打开,以及每一个后续的推送事件发生时,这些测试就会直接在 CI 工作流中运行,它们由一个自定义的 Cucumber 标签"@core "(https://cucumber.io/docs/cucumber/api/?lang=java#tags)来标识。除了测试最频繁的用户流并确保核心功能正常运行的核心测试外,我们还有 "扩展 "套件,它们规模更大,因此运行速度更慢。它们的执行是通过聊天机器人式的方法手动触发的。是否以及何时运行此类测试由质量保证工程师或开发人员决定,但通常至少要运行一次--在代码审查完成后,也可能在广泛的探索性测试之前。


在拉取请求中留下以 /trupi-extended 开头的注释将触发这些扩展测试的执行。

图片

目前,在 trupi-extended 工作流程中有三个不同的工作,使用矩阵策略,分别在 Chrome 桌面、Chrome 移动(移动模拟模式)和未启用 JavaScript 的 Chrome 浏览器中运行测试。每个工作都能处理同一文件夹中的不同测试套件,并根据标签表达式选择单个测试。

图片

然后,扩展测试运行的结果会以新注释的形式添加到同一拉取请求中,其中包含失败或成功的信息以及相关测试报告的链接。

为了获得更好的反馈,注释实际上是逐步添加和修改的:执行开始时会添加第一条注释,然后在成功或失败时将其替换,并用表情符号对原始触发注释做出反应。该命令有可选参数,可以只执行子集,例如只执行 "桌面",或在执行测试时应用某些变化。最新添加的 "失败 "参数可以手动重新运行上次运行失败的作业,只挑选失败的测试执行。

测试执行时间和不稳定问题

尽管我们在测试设置的多个方面和每个测试场景中不断应用优化策略,但所有端到端测试套件都会受到一些不稳定性的困扰。

也就是说,即使代码没有改变,测试也可能在不同的运行中通过或失败。对于 Selenium 测试来说,98% 或 99% 的成功率在纸面上可以说是不错了,但它显然没有真正的稳定性好。在大量测试(如300或400次)中,哪怕只有 或2次测试失败,也会让人产生某种怀疑,这还不如全面成功和green check。

出现少量失败时怎么办?个人的决定可能是重新运行整个测试套件。再次运行由数百个测试组成的扩展测试套件大约需要10分钟,这会推迟发布时间,消耗更多资源,从而导致额外成本。此外,这也不能保证其他测试不会遇到环境问题或其他随机失败原因。面对这一挑战,我们寻找一种解决方案,使开发人员和质量保证工程师能够在这种情况下获得更快、更准确的反馈周期。

如何半自动重新运行失败的测试


我曾做过一次题为 "测试半自动化 "的演讲,重点介绍了我为支持自己和团队进行探索性测试而编写的 Chrome 浏览器扩展。

谈到 "自动化 "这个话题,只要人工智能没有完全接管整个测试和反馈周期(如果它能做到的话),我仍然认为测试中最重要的部分是人

自动化工具只是一种工具,可以帮助我们更快更好地完成测试工作。当我们考虑如何利用自动化改善体验时,特别是在长期运行的 trupi-extended 工作流程中,我们选择了退一步,实行半自动化。这里的半自动化是指在流程中需要更多必需的人工操作,同时保持简单快捷的体验。

我们要解决的第一个问题是:由于我们使用开源的 Cucable 插件(由我们的测试自动化工程师 Benjamin Bischoff 开发)来并行化测试执行,因此生成的 "切片 "运行程序不再基于原始特征文件,我们也无法列出原始 Cucumber 场景在特征文件中的位置。Benjamin 挽救了这一问题,他发布的 Cucable 1.10.0 新版本正是提供了这一功能,因为它创建了一个generated-features.properties 文件,其中存储了所有生成的特性名称及其对相应源特性的引用。文件内容如下:

Calendar_scenario001_run001_IT=src/test/resources/features/search-form/Calendar.feature:124GuestSelector_scenario003_run001_IT=src/test/resources/features/search-form/GuestSelector.feature:31

接下来的问题是如何处理测试工作运行结束时的失败列表。由于 GitHub Actions 工作流运行结束时不会持久化自定义数据,而且考虑到工作流总是从主分支运行,因此顺序是非线性的(所有拉取请求的 trupi-extended 运行都由相同的主分支标识),我们考虑了几种方案:

  • 将生成的 txt 文件作为工作流运行工件,并通过下载操作从 "重试失败 "运行中获取。

  • 将生成的 txt 文件推送到Google Cloud Storage (GCS) 存储桶,然后从那里下载。

上述两个选项实际上都需要一些步骤来识别上一次运行的 ID 或 GCS 的唯一标识符,然后才能下载列表。总的来说,还需要几个额外的步骤。因此,我们考虑了第三种可能更简单的方案:

  • 如果发生故障,工作流程中的每个测试任务都将解析 failed_scenarios.txt 内容。然后,它会删除由于场景大纲示例失败而产生的任何重复内容,因为它们是不同的测试,但在 Cucumber 特征文件中的位置相同。最后,它会在结果注释中添加一个用<!-- -->包装的隐藏注释部分。

图片

图片

这种方法有几个优点:

  • 数据保留在需要的地方:在拉取请求中。

  • 只需查看包含特定文本(如 "tests executed with result:FAILED "这样的特定文本。

  • 如果需要,甚至可以手动检查或编辑。

然后,我们添加了实际的失败重试。通过在命令中使用 "failures "参数,即 /trupi-extended failures,工作流将不会创建通常默认的由三个任务组成的矩阵,而是会读取最后一条现有注释中包含失败信息的隐藏部分。它将查找识别故障列表的特定关键字(如 "mobile_failed="等),以分隔符"; "分隔,收集每个关键字的列表,并在此基础上创建一个大小可变的矩阵(1到3个作业),为每个作业提供要执行的相应方案列表。

图片

这样,结果注释也会反映出只执行了先前失败的测试,而且还会指向先前的运行ID以供参考。此外,还可以注释/trupi-extended 失败,并再次递归运行,但希望此时任何异常测试都已通过。如果在第二次尝试时出现同样的异常,那么真正的失败就显而易见了。

图片

结论

端到端测试的重试策略因测试套件的要求和执行环境而异。我们最新增加的故障手动重试解决方案帮助我们在 "在任何情况下重试一切 "的方法和整个测试套件的完全手动重新运行之间找到了有价值的折中方案。

现在,我们的质量保证工程师可以自己评估情况,大多数情况下,只需再写一条注释并多等几分钟,就能使最大的一组自动化测试完全成功。

我们解决了所有问题吗?当然没有,因为缺陷和环境问题会继续存在,有时还会给我们带来麻烦,尽管我们每天都在解决这些问题。除了持续观察测试结果并对其进行维护外,我们还采用了不同的重试方法,这增强了我们在合并之前的信心,然后通过我们的CD流程直接发布到生产中,呈现给我们的数百万用户。


了解更多国内的质量保证方面的落地实践,可以来看看这场测试开发圈年度技术交流大会!

将于11月25日举办的MTSC2023第十二届中国互联网测试开发大会(深圳站),特别设置有质量保障专场(详见下图),来自头部科技、互联网公司的技术专家,将就质量保障体系建设、风险防控、能力建设等相关话题展开分享。

欢迎来MTSC2023深圳大会一起讨论,目前大会门票,7折优惠已经结束,限时8折优惠进行中,先到先得!

相关文章:

端到端测试(End-to-end tests)重试策略

作者&#xff5c;Giuseppe Donati&#xff0c;Trivago公司Web测试自动化工程师 整理&#xff5c;TesterHome 失败后重试&#xff0c;是好是坏&#xff1f; 为什么要在失败时重试所有测试&#xff1f;为什么不&#xff1f; 作为Trivago&#xff08;德国酒店搜索服务平台&…...

三相交错LLC软启动控制驱动波形分析--死区时间与占空比关系

三相交错LLC软启动控制驱动波形分析 文章目录 三相交错LLC软启动控制驱动波形分析一、电路原理二、时序分析三、环路分析四、控制策略1.软启动驱动波形趋势2.软启动驱动波形占空图3.软启动驱动波形详细图4.软启动代码分析5.Debug调试界面5.死区时间与实际输出5.1 死区时间50--对…...

数据结构详细笔记——栈与队列

文章目录 栈的三要素逻辑结构&#xff08;定义&#xff09;数据的运算&#xff08;基本操作&#xff09;存储结构&#xff08;物理结构&#xff09;顺序栈&#xff08;顺序存储&#xff09;链栈&#xff08;链式存储&#xff09; 队列的三要素逻辑结构&#xff08;定义&#xf…...

JVM调试命令与调试工具

目录 一、JDK自带命令 1、jps 2、jstat&#xff08;FullGC频繁解决方案&#xff09; 3、jmap 4、jhat 5、jstack(cpu占用高解决方案) 6、jinfo 二、JDK的可视化工具JConsole 1、JConsole 2、VisualVM 一、JDK自带命令 Sun JDK监控和故障处理命令如&#xff1a; 1、jps JVM Proc…...

《软件方法》第1章2023版连载(07)UML的历史和现状

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.3 统一建模语言UML 1.3.1 UML的历史和现状 上一节阐述了A→B→C→D的推导是不可避免的&#xff0c;但具体如何推导&#xff0c;有各种不同的做法&#xff0c;这些做法可以称为“方…...

chromium 54 chrome 各个版本发布功能列表(109-119)

chromium Features 109-119 From https://chromestatus.com/features chromium109 Features:12 Auto range support for font descriptors inside font-face rule Auto range support for variable fonts in ‘font-weight’, ‘font-style’ and ‘font-stretch’ descrip…...

Linux实现原理 — I/O 处理流程与优化手段

Linux I/O 接口 Linux I/O 接口可以分为以下几种类型&#xff1a; 文件 I/O 接口&#xff1a;用于对文件进行读写操作的接口&#xff0c;包括 open()、read()、write()、close()、lseek() 等。 网络 I/O 接口&#xff1a;用于网络通信的接口&#xff0c;包括 socket()、conne…...

第 367 场 LeetCode 周赛题解

A 找出满足差值条件的下标 I 模拟 class Solution { public:vector<int> findIndices(vector<int> &nums, int indexDifference, int valueDifference) {int n nums.size();for (int i 0; i < n; i)for (int j 0; j < i; j)if (i - j > indexDiffe…...

最新百度统计配置图文教程,获取siteId、百度统计AccessToken、百度统计代码教程

一、前言 很多网友开发者都不知道百度统计siteId、百度统计token怎么获取&#xff0c;在网上找的教程都是几年前老的教程&#xff0c;因此给大家出一期详细百度统计siteId、百度统计token、百度统计代码获取详细步骤教程。 二、登录到百度统计 1.1 登录到百度统计官网 使用…...

【C++ 学习 ㉘】- 详解 C++11 的列表初始化

目录 一、C11 简介 二、列表初始化 2.1 - 统一初始化 2.2 - 列表初始化的使用细节 2.2.1 - 聚合类型的定义 2.2.2 - 注意事项 2.3 - initializer_list 2.3.1 - 基本使用 2.3.2 - 源码剖析 一、C11 简介 1998 年&#xff0c;C 标准委员会发布了第一版 C 标准&#xff0…...

OpenCV12-图像卷积

OpenCV12-图像卷积 图像卷积 图像卷积 OpenCV中提供了filt2D()函数用于实现图像和卷积模板之间的卷积运算&#xff1a; void filter2D(InputArray src, // 输入图像OutputArray dst, // 输出图像int ddepth, // 输出图像数据类型&#xff08;深度&#xff09;&#xff…...

MVCC与BufferPool缓存机制

MVCC多版本并发控制机制 Mysql在可重复读隔离级别下如何保证事务较高的隔离性&#xff0c;我们上节课给大家演示过&#xff0c;同样的sql查询语句在一个事务里多次执行查询结果相同&#xff0c;就算其它事务对数据有修改也不会影响当前事务sql语句的查询结果。 这个隔离性就是…...

POI、Easy Excel操作Excel

文章目录 1.常用的场景2.基本功能3.Excel在Java中是一个对象4. 简单的写&#xff08;07版本&#xff08;.xlsx&#xff09;Excel&#xff09;大文件写HSSF大文件写XSSF大文件写SXSSF 5. Excel读5.1 读取遇到类型转化问题该怎么解决5.2 遇到Excel公式怎么办 6. Easy Excel6.1简单…...

网络安全(黑客)自学方向

每年报考网络安全专业的人数很多&#xff0c;但不少同学听说千万别学网络安全&#xff0c;害怕网络安全专业很难就业。下面就带大家深入了解一下网络安全专业毕业后可以干什么&#xff0c;包括网络安全专业的就业前景和方向等。 随着信息化时代的到来&#xff0c;网络安全行业…...

react写一个简单的3d滚轮picker组件

1. TreeDPicker.tsx文件 原理就不想赘述了, 想了解的话, 网址在: 使用vue写一个picker插件,使用3d滚轮的原理_vue3中支持3d picker选择器插件-CSDN博客 import React, { useEffect, useRef, Ref, useState } from "react"; import Animate from "../utils/an…...

Compose竖向列表LazyColumn

基础列表一 LazyColumn组件中用items加载数据&#xff0c;rememberLazyListState()结合rememberCoroutineScope()实现返回顶部。 /*** 基础列表一*/ Composable fun Items() {Box(modifier Modifier.fillMaxSize()) {val context LocalContext.currentval dataList arrayLi…...

6.自定义相机控制器

愿你出走半生,归来仍是少年&#xff01; Cesium For Unity自带的Dynamic Camera,拥有优秀的动态展示效果&#xff0c;但是其对于场景的交互方式用起来不是很舒服。 通过模仿Cesium JS 的交互方式&#xff0c;实现在Unity中的交互&#xff1a; 通过鼠标左键拖拽实现场景平移通过…...

一文带你GO语言入门

什么是go语言? Go语言(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go语言的主要特点包括:- 简洁和简单 - 语法简单明快,易于学习和使用 特点 高效 编译速度快,执行效率高 并发支持 原生支持并发,利用goroutine实现高效的并发…...

前后端小项目链接

1.vue的创建 vue的项目创建 1.1 vue create vue_name 1.2 Babel Router(路由) CSS Pre-processors 路由可通过&#xff1a;npm i vue-router3.5.2 -S 下载 1.3less 1.4 In dedicated config files 1.5 启动命令&#xff1a;npm run serve 端口号在vue.config。js中配置 devS…...

编辑器功能:用一个快捷键来【锁定】或【解开】Inspector面板

一、需求 我有一个脚本&#xff0c;上面暴露了许多参数&#xff0c;我要在场景中拖物体给它进行配置。 如果不锁定Inspector面板的话&#xff0c;每次点击物体后&#xff0c;Inspector的内容就是刚点击的物体的内容&#xff0c;而不是挂载脚本的参数面板。 二、 解决 &…...

Vue 网络处理 - axios 异步请求的使用,请求响应拦截器(最佳实践)

目录 一、axiox 1.1、axios 简介 1.2、axios 基本使用 1.2.1、下载核心 js 文件. 1.2.2、发送 GET 异步请求 1.2.3、发送 POST 异步请求 1.2.4、发送 GET、POST 请求最佳实践 1.3、请求响应拦截器 1.3.1、拦截器解释 1.3.2、请求拦截器的使用 1.3.3、响应拦截器的使…...

关于W5500网卡使用过程的部分问题记录

某个项目中用到了W5500这种自带网络协议栈的网卡芯片&#xff0c;由于该项目开发时间很紧&#xff0c;就临时网上买了一些模块拼凑到了一套系统&#xff0c;经过验证果真这种拼积木的方法只能用在学生实验开发中&#xff0c;真不能拿来做工程应用&#xff0c;硬件太不稳定很容易…...

Unity DOTS World Entity ArchType Component EntityManager System概述

最近DOTS终于发布了正式的版本, 我们来分享以下DOTS里面地几个关键概念&#xff0c;方便大家上手学习掌握Unity DOTS开发。 Unity DOTS 中所有的Entities 都是被放到World世界中。每个Entity在它所在的World里面有唯一不同的ID号来区分。DOTS项目中可以同时有多个World。每个W…...

最详细STM32,cubeMX 点亮 led

这篇文章将详细介绍 如何在 stm32103 板子上点亮一个LED. 文章目录 前言一、开发环境搭建。二、LED 原理图解读三、什么是 GPIO四、cubeMX 配置工程五、解读 cubeMX 生成的代码六、延时函数七、控制引脚状态函数点亮 LED 八、GPIO 的工作模式九、为什么使用推挽输出驱动 LED总结…...

论文阅读:Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data

目录 摘要 Motivation 整体架构流程 技术细节 雷达和图像数据的同步 小结 论文地址: [2203.16258] Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data (arxiv.org) 论文代码&#xff1a;GitHub - valeoai/SLidR: Official PyTorch implementati…...

前端版本控制工具,常见的Git 和SVN

目录 前言GitGit简介Git的优势Git常用指令常见的Git服务 SVN (Subversion)SVN简介SVN的优势SVN常用指令SVN与Git的区别 &#x1f44d; 点赞&#xff0c;你的认可是我创作的动力&#xff01; ⭐️ 收藏&#xff0c;你的青睐是我努力的方向&#xff01; ✏️ 评论&#xff0c;你…...

C++ —— Tinyxml2在Vs2017下相关使用2(较文1更复杂,附源码)

相关链接 C —— Tinyxml2在Vs2017下相关使用1&#xff08;附源码&#xff09; tinyxml2简介 TinyXML2是一个简单&#xff0c;小巧&#xff0c;高效&#xff0c;CXML解析器&#xff0c;可以很容易地集成到其他程序中。TinyXML-2解析一个XML文档&#xff0c;并从中构建一个 可以…...

阿里内推强推的并发编程学习笔记,原理+实战+面试题,面面俱到!

并发编程 谈到并发编程&#xff0c;可能很多人都有过经验&#xff0c;甚至比我了解的更多。 那么并发与并行的区别又是什么&#xff1f; 并发编程是编程中的核心问题&#xff0c;实践中&#xff0c;当人们希望利用计算机处理一些现实世界问题&#xff0c;以及希望同时处理多…...

域名注册查询流程

域名注册查询怎么查域名是否被注册?域名注册查询如何查域名的过期时间和注册商?域名注册查询用什么工具?下面是关于域名注册查询流程介绍。 1、域名注册查询可以用什么工具? 这里可以使用聚查工具&#xff0c;聚查包括&#xff1a;whois 查询、建站历史查询、反链查询、P…...

【Linux学习笔记】代码编辑工具vim

1. vim工具基本模式的转换2. vim命令模式下的各种编辑命令2.1. 光标行定位2.2. 光标自由定位2.3. 复制粘贴2.4. 删除2.5. 文本的大小写替换2.6. 文本的替换2.7. 文本的前删后删2.8. 撤销操作 3. vim底行模式下的命令3.1. 设置行号与取消设置行号3.2. 分屏操作3.3. 在不退出vim的…...