游戏测试|超越QA的常规:我们如何自动化回归测试

QA测试工作并不单调乏味,它是一项创造性的工作,蕴含着丰富的机会。公平地说,它也有枯燥乏味的一面--回归(regression)。因此,我们决定将回归测试自动化,具体方法如下。

图片

在IT行业,有一种偏见,认为测试人员的工作既乏味又单调。我们不敢苟同,我们认为,质量保证既是一项创造性工作,也是一项技术性工作,它提供了全方位的研究机会。此外,要做好这项工作,需要沉浸在任务中,了解其所有的微妙之处和复杂性,并具备管理任何潜在陷阱的意识和能力。

auto-battler的机制自动化

首先,让我们介绍一下我们的工作流程所涉及的工作背景。我们负责开发一款名为《Hustle Castle》的游戏,这是一款兼具经济策略和 RPG 元素的移动自动战斗游戏。在这个项目中,Unity 是我们的首选引擎,服务器则是用 Java 编写的。自动战斗(auto-battle)的核心机制如下:玩家和敌方单位发生冲突,所有角色都有赋予能力的特殊装备,战斗自动继续--用户只能施法和使用英雄的天赋。

Hustle Castle 还有一个城堡功能(castle feature),其中包含无数房间,用户可以在这些房间中提取资源、制作物品等。此外,游戏中还有以部落、领地发展、竞技场等为特色的网络机制。所有这些都彼此共存,遵循着共同的逻辑。

完成了对 Hustle Castle 的介绍后,现在我们可以继续讨论更深层次的内容了。游戏玩法与单位的能力相关。从技术角度来看,能力是一种具有多种设置的实体:它如何以及何时被激活,它将影响谁以及如何影响,它还可以激活哪些其他能力等等。

我们以 JSON 对象的形式描述每个能力的行为。举例来说,能力可以是简单的、结构化的——它们也可以顺序或并行激活其他能力。此外,还有不同类型的能力,例如反击(counters)、增益(buffs)、眩晕(stuns)——一般来说,有很多不同的设置需要考虑。

所有这些都被自动战斗算法考虑在内。简而言之,它的工作原理是这样的:有一些数据作为输入——我们的战士的状态、他们拥有的统计数据和能力。我们将这些数据传输到战斗计算器(battle calculator),由它进行所有计算。对于每个计算步骤,它都会报告发生了什么事件、是否激活了某种能力以及是否造成了某些伤害。经过一个完整的循环计算,我们就得到了战斗的结果。

图片

值得注意的是,战斗计算器代码在客户端和服务器端都可用。这对于验证战斗结果是必要的——客户端、服务器和战斗计算器需要查看相同的数据。

为了自动化自动战斗(auto-battle)检查,我们决定制作一个自定义客户端,它可以向服务器生成请求,以根据传入数据接收初始战斗状态。自动测试使用此客户端,接收状态,将其传递给计算器,订阅新计算步骤的事件,然后检查每个步骤的条件。

图片

战斗系统的平均测试

为了检查战斗系统( combat system)的机制,我们使用专门为测试而收集的能力。检查针对的是机制,我们不检查制作过程中的技能。

我们还在名为 Battle Runner 的内部产品中使用了这种方法。我们的游戏设计师需要它来平衡战斗系统。游戏设计师可以从产品中提取任何玩家状态,将其组合成测试组,选择性地用一种能力替换另一种能力,然后在大量战斗中运行游戏。运行后,游戏设计者就能得到所需的战斗统计数据。

这是迈向自动化的第一步。我们的自动测试帮助我们确保战斗计算器的基本逻辑在游戏设计师和开发人员做出一些更改后仍然有效。这是一个复杂的过程,不幸的是,我们没有为此进行单元测试。因此,这些战斗计算器自动测试是我们确保大部分战斗系统稳定的唯一方法。

在服务器和客户端上进行测试

为了解释接下来会发生什么,让我们考虑一些理论--假设你正在观察众所周知的测试金字塔。

图片

金字塔的本质很简单。我们越接近底部,测试就越便宜、越快;越高,测试的时间就越长,成本也越高。

解决方案似乎很明显——我们需要使用最快、最便宜的单元测试。但事情比这要复杂一些。为了让开发人员编写单元测试,应用程序必须具有特定的设计——也就是说,它必须是可测试的。不幸的是,并非所有这些都是可测试的。

服务器逻辑几乎没有单元测试,我们有的只是组件测试,主要包括匹配、模式和功能的基本逻辑。

如果我们单独考虑服务器,那么我们会遇到以下情况:我们的服务器上没有集成测试。理论上我们可以编写 API 测试,因为我们的客户端和服务器使用 protobuf 协议进行通信。因此,有了协议的描述,我们就可以获取客户端并发送请求。但目前,我们保留这个想法。

在客户端,事情就有点悲惨了。没有单元测试,也没有组件测试。因此,我们发现自己位于金字塔的顶端,只需通过 UI 测试我们的应用程序即可。我们的大多数游戏看起来都是这样的:很多按钮、对话框、弹出窗口、更多对话框、更多按钮。几乎所有界面元素都位于 Canvas 上。

作为基本工具,我们使用开源解决方案AltUnityTester(https://alttester.com/tools/),它是一个提供以下功能的驱动程序:

  • 使用x路径搜索对象

  • 场景管理

  • 模拟输入法(点击、滚动、拖放等)

  • 调用方法并获取游戏对象的属性

  • 通过web socket进行交互的协议,允许添加许多其他命令。

图片

因此,我们使用了 Java、Allure、TestNG,并决定应用页面对象模式并开始编写测试。起初,一切都很酷。我们编写了大约 10-15 个基本测试,只是检查界面是否执行了某些操作。

然而,很快我们就发现,我们的代码库包含许多问题,随着项目的不断发展,这些问题对我们的影响会越来越大。第一个问题与选择器(selectors)有关。下面的屏幕截图显示了我们如何使用页面对象的示例。类的字段是选择器,方法包含对驱动程序和附加逻辑的调用。

图片

问题不仅在于其庞大的外观,还在于 AltUnity API 最终出现在我们所有的类中。如果开发人员要在新版本中更改某些内容,那么更新对我们来说将是极其痛苦的。

另一个问题是 Page 对象的责任。首先,在 Page 对象内部,我们调用驱动程序(hello, API!)。其次,对象可能有扭曲的逻辑。第三,我们的 Page 对象了解其他 Page 对象——也就是说,它们参与对象的导航。

图片

我们的页面对象看起来像这样

另一个问题是依赖注入。在类很少的时候,一切都井然有序。但随着测试的复杂化,有必要连接大量的依赖关系,并牢记我们一般有哪些依赖关系。

图片

这就是典型测试的依赖关系

大量的依赖关系会造成不必要的困难:例如,如果一个新人来到公司并尝试编写自动测试,他们将需要研究所有种类的 API,创建我们拥有的类以及它们如何使用的思维导图。是相关的,并付出很大的努力来深入研究这个过程。

图片

测试看起来非常混乱,还很难理解

我们遇到的最后一个问题是代码重复。例如,上图显示了OpenShopAndBuyRoom方法,该方法是这个测试类私有的,所以我们不能在其他地方使用它。但由于我们想要编写更多测试,因此我们希望以某种方式重用此方法,并且它必须属于某个类。

是时候停下来思考了

AltUnityTester 和 Page 对象模式的使用与 Web 应用程序开发中的自动化非常相似。我们的同事使用 Selenium WebDriver。如果我们从网络上获取概念并在我们的主题领域中使用它们,那么我们就会得到以下结果:

1.UnityDriver:与游戏交互。

2.Unity-Object:用于描述对话框、屏幕和场景的结构模式。我们只用它们来描述结构,而 STEPS 则处理逻辑。

3.Unity-Element:按钮、图片、对话框、文本等。一般来说,Unity 中舞台上的一切都是 Unity 元素。

我们研究了 WebDriver 和 HTML Elements 框架的源代码,并设法根据我们的需要调整了代码。我们还使用 STEPS 模式将测试逻辑与 Unity-Objects 分离开来。结果,我们得到了一个框架,使我们能够:

1.将实体分组为单独的类(Button、Label、AbstractDialog 等)。

2.使用 @FindBy 注释设置 UI 元素的 x 路径,并引入新的注释和扩展。

3.创建单独的元素组并通过在另一个对象的上下文中搜索对象来在不同的对话框中重用它们。

4.在测试端在 Unity 中创建组件的表示(因为一个对象中可以有多个组件)。

5.使用 STEPS,根据游戏的业务逻辑编写测试(“开商店”、“购买产品”等)。

6.AltUnity代码深入核心,驱动程序隐藏在界面后面。

关于STEPS的一些信息:它们将我们的测试与 Unity-Objects 连接起来。Unity-Objects 使得点击元素或从游戏中传输一些数据成为可能,并且所有逻辑都在 STEPS 中。这使我们能够根据业务流程编写测试。例如,“在该位置,开设一个兵营”,“在兵营中,升级兵营”,“选取一个单位并将其转移到兵营”。在幕后,是拖放、点击和其他一切。

STEPS的第二个特点是它们可以在未来重复使用;并且不仅仅在功能测试的框架内。例如,最近我们需要在多种不同的玩家状态下实现一种场景的试运行。我们创建了一个新项目,使用 STEPS 激活库,使用几行代码来运行脚本 - 就这样完成了。

下面是 Unity 对象。还记得我们的选择器是什么样子的吗?他们非常丑陋。现在我们只使用注释来规定如何搜索所需的元素 - 就是这样。

图片

类型化元素的示例

这就是我们项目中几乎所有对话的描述方式。同时,STEPS 可以访问可点击的按钮、重复对象的列表,并且 STEPS 还可以从整个对话中接收信息(我们有多少金币,哪些插槽打开或关闭等等)。

Unity 元素加载器(Unity Element Loader)负责初始化类字段 - 它接收特定的类和驱动程序。根据某种逻辑,我们为类中的每个字段创建代理元素。因此,我们可以简单地写成“自按按钮”,虽然实际上系统会先找到这个按钮,然后才会返回有关该按钮的信息,然后才完成“按下”命令。

下面可以看到我们有任务对话框的步骤。这些步骤已经根据游戏本身进行了描述。

图片

测试示例

所有测试都是这样的:我们只使用一次 STEPS 注入。基于此,我们使用业务逻辑术语来描述我们想要做的一切——最终,一切看起来都非常整洁。

未来的计划

未来,我们的主要计划是进行更多测试。所有这些努力都是为了方便、简单且易于理解地扩展我们的代码库;但多线程的问题迫在眉睫。

目前,测试正在一个游戏实例的一个线程中运行。一切都很顺利,但这需要很长时间。

为了解决这个问题,我们可以在远程服务器上创建多个实例。或者我们可以组装一个设备群并连接到它们。但我们的一些功能是全局性的,可能会干扰测试:例如,如果农业门户是开放的,那么它就向所有人开放。在并行运行测试的界面中打开或关闭门户时,可能会出现通知,并且可能会点击此通知,而不是所需的元素。

我们想要实施的下一件事是 back-to-back testing 。这是指使用两个版本的应用程序,运行相同的脚本,在某个时间点截图,然后进行比较。这样,你就可以检查是否有什么地方出错了,是否有什么功能提前出现了等等。

目前,我们正在扩大功能覆盖范围,我们有一个 smoke set ,其中至少有一个针对游戏任何方面的测试,并且我们还开始培训同事编写测试。

测试自动化框架是一种产品。它应该简单、易懂、易于扩展。在设计时,应牢记软件开发的模式和原则,以及与重构相关的模式和原则。否则,摆脱回归将成为令人头疼的维护问题。

 

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/465287.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

群分解(Swarm Decomposition,SWD)

代码原理 群体分解(SWD)是一种用于信号处理和数据分析的新兴方法。它通过将复杂的信号分解为多个群体成分(Swarm Components),每个成分代表信号中的特定特征或模式。SWD的主要目标是提取信号中的不同特征模式&#xf…

flink实战-- flink任务的火焰图如何使用

火焰图 Flame Graphs 是一种有效的可视化工具,可以帮助我们排查如下问题: 目前哪些方法正在消耗 CPU 资源?一个方法的消耗与其他方法相比如何?哪一系列的堆栈调用导致了特定方法的执行?y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的…

CSS基础知识六(浮动的高度塌陷问题及解决方案)

目录 1.浮动高度塌陷概念 2.下面是几种解决高度塌陷的几种方案: 解决方案一: 解决方案二: 解决方案三: 1.浮动高度塌陷概念 在CSS中,高度塌陷问题指的是父元素没有正确地根据其内部的浮动元素或绝对定位元素来计…

拒绝事后背锅:测试项目中的风险管理一定要知道

在博主的公司中,测试经理除了要管理产品线的质量保障和日常部门事务工作外,另一项比较重要的就是测试项目全流程的管理。 今天不聊整体的测试项目流程如何开展,而是想聊一聊在同行中比较高频出现的一个字眼:风险管理。 什么是风…

基础算法——排序算法(冒泡排序,选择排序,堆排序,插入排序,希尔排序,归并排序,快速排序,计数排序,桶排序,基数排序,Java排序)

1.概述 比较排序算法 算法最好最坏平均空间稳定思想注意事项冒泡O(n)O( n 2 n^2 n2)O( n 2 n^2 n2)O(1)Y比较最好情况需要额外判断选择O( n 2 n^2 n2)O( n 2 n^2 n2)O( n 2 n^2 n2)O(1)N比较交换次数一般少于冒泡堆O( n l o g n nlogn nlogn)O( n l o g n nlogn nlogn)O( n l…

利用pythonstudio写的PDF、图片批量水印生成器,可同时为不同读者生成多组水印

现在很多场合需要将PDF或图片加水印,本程序利用pythonstudio编写。 第一步 界面 其中: LstMask:列表框 PopupMenu:PmnMark LstFiles:列表框 PopupMenu:PmnFiles OdFiles:文件选择器 Filter:PDF文件(.PDF)|.PDF|图像文件(.JPG)|.JPG|图像文件(.png…

如何区分实例化网格中的每个实例

1)如何区分实例化网格中的每个实例 2)项目在模拟器上切换程序后有概率画面冻结 3)Unity工程导入团结引擎,GUID会变化,导致引用关系丢失 4)Mask在Android平台下渲染异常 这是第407篇UWA技术知识分享的推送&a…

前端前置——ajax

目标:使用axios库,获取省份列表数据,展示到页面上 axios库地址:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js 省份数据地址:http://hmajax.itheima.net/api/province axios的使用 axios({ url:目标资源地…

oasys系统代码审计

简述: oasys是一个OA办公自动化系统,使用Maven进行项目管理,基于springboot框架开发的项目,mysql底层数据库,前端采用freemarker模板引擎,Bootstrap作为前端UI框架,集成了jpa、mybatis等框架。…

书生大模型第三关Git 基础知识

关卡编号:L0G3000 任务一 破冰行动 fork仓库,注意这里不要勾选Copy branch Only!!!,因为后面课程中会使用到class分支: 克隆仓库: 移动分支: 创建自己的分支: 创建id.md文档,…

在vue3的vite网络请求报错 [vite] http proxy error:

在开发的过程中 代理proxy报错: [vite] http proxy error: /ranking/hostRank?dateType1 Error: connect ETIMEDOUT 43.xxx.xxx.xxx:443 网络请求是http的: // vite.config.ts import { Agent } from node:http;server: {host: 0.0.0.0,port: port,open: true,https: false,…

初识HTML

什么是HTML呢? HTML是超文本标记语言,HTML代码是由“标签”构成的 超文本:文本、声音、图片、视频、表格、链接 标记:由许许多多的标签组成 HTML页面是运行到浏览器上面的 第一个HTML程序 和C语言从hello world开始一样 HTML可…

DevOps-课堂笔记

各种 aaS 类比于计算机网络的 OSI 参考模型,一个软件应用项目需要不同的支撑层,例如从下至上大概需要: 硬件层面的服务器针对硬件做弹性分配的虚拟化机制,例如虚拟机在虚拟化环境内运行的 OS支撑软件应用的中间件,例…

AnatoMask的分层图像编码器-解码器

方法思想 采用多尺度编码器-解码器主干: 在编码器中,把CT图像分解成不同大小的图像块,从这些图像块中提取特征在解码器中,重建被掩盖图像时,考虑图像块的空间关系 输入D(深度Depth)张H&#x…

C++ 之boost/date_time/posix_time高精度计时详细总结

文章目录 概要时间长度类time_duration时间点ptime时间区域time_period时间迭代器实际应用1:(计算加速度)实际应用2:可以支持秒级和微秒/纳秒级计时器 概要 使用date_time库需要在编译时加上"-lboost_date_time"&#x…

小语言模型介绍与LLM的比较

小模型介绍 小语言模型(SLM)与大语言模型(LLM)相比,具有不同的特点和应用场景。大语言模型通常拥有大量的参数(如 GPT-3 拥有 1750 亿个参数),能够处理复杂的自然语言任务&#xff…

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列,是一个实时数据处理系统,可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点: 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的,因…

混合式学习平台:企业培训的新选择

在当前的商业环境中,企业普遍采用在线直播课程进行员工培训。然而,在线学习常常伴随着焦虑、疲劳和效率低下等问题,这些都是企业在进行在线培训时需要面对和解决的挑战。本文将探讨如何通过使用白板协作工具——即时白板,来提高企…

内网项目,maven本地仓库离线打包,解决Cannot access central in offline mode?

背景&#xff1a; 内网项目打包&#xff0c;解决Cannot access central in offline mode? 1、修改maven配置文件&#xff1a; localRepository改为本地仓库位置 <localRepository>D:\WorkSpace\WorkSoft\maven-repository\iwhalecloud-repository\business</loca…

如何用 ChatPaper.ai 打造完美的 AI 课堂笔记系统

作为学生&#xff0c;我们都遇到过这样的困扰&#xff1a;上课时记笔记太投入就听不进讲解&#xff0c;专注听讲又担心错过重要知识点。有了AI助手&#xff0c;这个问题就可以优雅地解决了。今天跟大家分享如何用ChatPaper.ai构建个人的智能课堂笔记系统。 为什么需要AI辅助记笔…