【软件测试】学习笔记-脚本与数据的解耦 + Page Object模型

        本篇文章介绍GUI测试中两个非常重要的概念:测试脚本和数据的解耦,以及页面对象(Page Object)模型。

测试脚本和数据的解耦

        GUI自动化测试适用的场景,尤其适用于需要回归测试页面功能的场景。如果在测试脚本中硬编码(hardcode)测试数据的话,测试脚本灵活性会非常低。而且,对于那些具有相同页面操作,而只是测试输入数据不同的用例来说,就会存在大量重复的代码。

        举个最简单的例子,上一篇文章中实现的百度搜索的测试用例,当时用例中搜索的关键词是“极客时间”,假设我们还需要测试搜索关键词是“极客邦”和“InfoQ”的场景, 如果不做任何处理,那我们就可能需要将之前的代码复制3份,每份代码的主体完全一致,只是其中的搜索关键词和断言(Assert)的预期结果不同。

        显然,这样的做法是低效的。

        更糟糕的是,界面有任何的变更需要修改自动化脚本时,你之前复制出来的三个脚本都需要做相应的修改。比如,搜索输入框的名字发生了变化,你就需要修改所有脚本中findElement方法的by.name属性。

        而这里只有三个脚本还好,如果有30个或者更多的脚本呢,你会发现脚本的维护成本实在是太高了。那么,这种情况应该怎么处理呢?

        相信你现在已经想到了,把测试数据和测试脚本分离。也就是说测试脚本只有一份,其中需要输入数据的地方会用变量来代替,然后把测试输入数据单独放在一个文件中。这个存放测试输入数据的文件,通常是表格的形式,也就是最常见的CSV文件。

        然后,在测试脚本中通过data provider去CSV文件中读取一行数据,赋值给相应的变量,执行测试用例。接着再去CSV文件中读取下一行数据,读取完所有的数据后,测试结束。CSV文件中有几行数据,测试用例就会被执行几次。具体流程如图1所示。

图1 数据驱动测试的基本概念

        这也就是典型的数据驱动(Data-driven)测试了。

  1. 数据驱动很好地解决了大量重复脚本的问题,实现了“测试脚本和数据的解耦”。 目 前几乎所有成熟的自动化测试工具和框架,都支持数据驱动的测试,而且除了支持CSV这种最常见的数据源外,还支持xls文件、JSON文件,YAML文件,甚至还有直接以数据库中的表作为数据源的,比如QTP就支持以数据库中的表作为数据驱动的数据源。
  2. 数据驱动测试的数据文件中不仅可以包含测试输入数据,还可以包含测试验证结果数据,甚至可以包含测试逻辑分支的控制变量。 图1中的 “Result_LoginSuccess_Flag”变量其实就是用户分支控制变量。
  3. 数据驱动测试的思想不仅适用于GUI测试,还可以用于API测试、接口测试、单元测试等。 所以,很多API测试工具(比如SoapUI),以及单元测试框架都支持数据驱动测试,它们往往都是通过Test Data Provider模块将外部测试数据源逐条“喂”给测试脚本。

页面对象(Page Object)模型

        为了让你了解“页面对象(Page Object)模型”这个概念的来龙去脉,并能够深入理解这个概念的核心思想,我会先从早期的GUI自动化测试开始讲起。

        早期的GUI自动化测试脚本,无论是用开源的Selenium开发,还是用商用的QTP(Quick Test Professional,现在已经改名为Unified Functional Testing)开发,脚本通常是由一系列的页面控件的顺序操作组成的,如图2所示的伪代码展示了一个典型的早期GUI测试脚本的结构。

图2 早期的GUI测试脚本伪代码示例

        先来简单介绍一下这个脚本实现的功能。

  • 第1-4行,输入用户名和密码并点击“登录”按钮,登录完成后页面将跳转至新页面;
  • 第5行,在新页面找到“图书”链接,然后点击链接跳转至图书的页面;
  • 第7-10行,在图书搜索框输入需要查找的书名,点击“搜索”按钮,然后通过assert验证搜索结果;
  • 第11-12行,用户登出。

        看完这段伪代码,是不是觉得脚本有点像操作级别的“流水账”,而且可读性也比较差,这主要体现在以下几个方面:

  • 脚本逻辑层次不够清晰,属于All-in-one的风格,既有页面元素的定位查找,又有对元素的操作。
  • 脚本的可读性差。 为了方便你理解,示例中的代码用了比较直观的findElementByName,你可以很方便地从name的取值,比如“username”和“password”,猜出脚本所执行的操作。- 但在实际代码中,很多元素的定位都会采用Xpath、ID等方法,此时你就很难从代码中直观看出到底脚本在操作哪个控件了。也就是说代码的可读性会更差,带来的直接后果就是后期脚本的维护难度增大。- 有些公司自动化测试脚本的开发和维护是两拨人,脚本开发并调试完以后,开发人员就会把脚本移交给自动化测试执行团队使用并维护,这种情况下脚本的可读性就至关重要了。但即使是同一拨人维护,一段时间后,当时的开发人员也会遗忘某些甚至是大部分的开发步骤。
  • 由于脚本的每一行都直接描述各个页面上的元素操作,你很难一眼看出脚本更高层的业务测试流程。 比如图2的业务测试流程其实就三大步:用户登录、搜索书籍和用户登出,但是通过阅读代码很难一下看出来。
  • 通用步骤会在大量测试脚本中重复出现。 脚本中的某些操作集合在业务上是属于通用步骤,比如上面伪代码的第1-4行完成的是用户登录操作,第11-12行完成的是用户的登出操作。

        这些通用的操作,会在其他测试用例的脚本中被多次重复。无论操作发生变动,还是页面控件的定位发生变化时,都需要同时修改大量的脚本。

        其实,上面说到的这四点正是早期GUI自动化测试的主要问题,这也是一直说“开发几个GUI自动化测试玩玩会觉得很高效,但是当你开发成百上千个GUI自动化测试的时候,你会很痛苦”的本质含义。

        那怎么解决这个问题呢?你可能已经想到了软件设计中模块化设计的思想。

        没错,就是利用模块化思想,把一些通用的操作集合打包成一个个名字有意义的函数,然后GUI自动化脚本直接去调用这些操作函数来构成整个测试用例,这样GUI自动化测试脚本就从原本的“流水账”过渡到了“可重用脚本片段”。

        如图3所示,就是利用了模块化思想的伪代码。

图3 基于模块化的GUI测试用例伪代码示例

        第1-6行就是测试用例,非常简单直接,一眼就可以看出测试用例具体在执行什么操作,而各个操作函数的具体内部实现还是之前那些“流水账”。当然这里对于测试输入数据完全可以采用测试驱动方法,这里为了直观我就直接硬编码了测试示例数据。

        实际工程应用中,第1-6行的测试用例和第8-30行的操作函数通常不会放在一个文件中,因为操作函数往往会被很多测试用例共享。这种模块化的设计思想,带来的好处包括:

  1. 解决了脚本可读性差的问题,脚本的逻辑层次也更清晰了;
  2. 解决了通用步骤会在大量测试脚本中重复出现的问题, 现在操作函数可以被多个测试用例共享,当某个步骤的操作或者界面控件发生变化时,只要一次性修改相关的操作函数就可以了,而不需要去每个测试用例中逐个修改。

        但是,这样的设计并没有完全解决早期GUI自动化测试的主要问题,比如每个操作函数内部的脚本可读性问题依然存在,而且还引入了新的问题,即如何把控操作函数的粒度,以及如何衔接两个操作函数之间的页面。

        现在,操作函数的内部实现还只是停留在“既有页面元素的定位查找,又有对元素的操作”的阶段,当业务操作本身比较复杂或者需要跨多个页面时,“可读性差、难以维护”的问题就会暴露得更加明显了。

        那么,有什么更好的办法来解决这个问题吗?答案就是,我要分享的GUI自动化测试的第二个概念:页面对象(Page Object)模型。

        页面对象模型的核心理念是,以页面(Web Page 或者Native App Page)为单位来封装页面上的控件以及控件的部分操作。而测试用例,更确切地说是操作函数,基于页面封装对象来完成具体的界面操作,最典型的模式是“XXXPage.YYYComponent.ZZZOperation”。

        基于这个思想,上述用例的伪代码可以进化成如图4所示的结构。这里,我只给出了login函数的伪代码,建议你按照这种思路,自己去实现一下search和logout的代码,这样可以帮你更好的体会页面对象模型带来的变化。

图4 基于页面对象模型的伪代码示例

        通过这样的代码结构,你可以清楚地看到是在什么页面执行什么操作,代码的可读性以及可维护性大幅度提高,也可以更容易地将具体的测试步骤转换成测试脚本。

总结

       这篇文章介绍了什么是数据驱动的测试,让你明白了“测试脚本和数据解耦”的实现方式以及应用场景。接着从GUI自动化测试历史发展演变的角度引出了GUI测试中的“页面对象模型”的概念。

        “测试脚本和数据解耦”的本质是实现了数据驱动的测试,让操作相同但是数据不同的测试可以通过同一套自动化测试脚本来实现,只是在每次测试执行时提供不同的测试输入数据。

        “页面对象模型”的核心理念是,以页面为单位来封装页面上的控件以及控件的部分操作。而测试用例使用页面对象来完成具体的界面操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源的RNA-Seq分析软件Trinity的详细介绍和使用方法

介绍 GitHub - trinityrnaseq/trinityrnaseq: Trinity RNA-Seq de novo transcriptome assembly Trinity是一种开源的RNA-Seq分析软件,用于转录组的de novo组装。转录组de novo组装是通过将RNA-Seq数据中的短序列片段(reads)重新组装成完整的…

Java8 Stream集合的筛选、归约、分组、聚合讲解

目录 1 Stream概述 2 Stream的创建 3 Stream的使用 3.1 Optional 3.2 案例 3.2.1 遍历/匹配(foreach/find/match) 3.2.2 筛选(filter) 3.2.3 聚合(max/min/count) 3.2.4 映射(map/flatMap) 3.2.5 归约(reduce…

仿stackoverflow名片与b站名片实现(HTML、CSS)

目录 前言一、仿stackoverflow名片HTMLCSS 二、仿b站名片HTMLCSS 素材 前言 学习自ACwing - Web应用课 一、仿stackoverflow名片 HTML <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport&…

【实用技巧】Windows 电脑向iPhone或iPad传输视频方法1:无线传输

一、内容简介 本文介绍如何使用 Windows 电脑向 iPhone 或 iPad 传输视频&#xff0c;以 iPhone 为例&#xff0c;iPad的操作方法类似&#xff0c;本文不作赘述。 二、所需原材料 Windows 电脑&#xff08;桌面或其它文件夹中存有要导入的视频&#xff09;、iPhone 14。 待…

双向孟德尔随机化 | 基础代谢率与心血管疾病因果关系研究发表医学一区文章...

欢迎报名2024年孟德尔随机化方法高级班课程&#xff01; 郑老师团队开设的孟德尔随机化高级班2024年1月20-21日开课&#xff0c;欢迎报名 2023年12月29日&#xff0c;一篇题为Causal Effects of Basal Metabolic Rate on Cardiovascular Disease: A Bidirectional Mendelian Ra…

期货日数据维护与使用_日数据维护_主力合约计算逻辑

目录 主力合约换月规则&#xff08;文化财经&#xff09; 主力合约计算逻辑 数据准备 代码 ​下载 主力合约换月规则&#xff08;文化财经&#xff09; 主力合约计算逻辑 数据准备 本文以沪银为例&#xff0c;将沪银所有日数据文件放入一个文件夹中&#xff0c;文件名命…

Git删除远程仓库某次提交记录后的所有提交

1、鼠标右键->git bash here&#xff0c;然后cd切换到代码目录&#xff1b; 2、git log查看提交记录&#xff0c;获取commit id 3、git reset commit id&#xff08;commit id指要保留的最新的提交记录id&#xff09; 4、git push --force&#xff0c;强制push 如果出现…

TypeScript基础(五)泛型

✨ 专栏介绍 TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript的超集&#xff0c;意味着任何有效的JavaScript代码都是有效的TypeScript代码。TypeScript通过添加静态类型和其他特性来增强JavaScript&#xff0c;使其更适合大型项目和团队开发。 在TypeS…

【机器学习】模型参数优化工具:Optuna使用分步指南(附XGB/LGBM调优代码)

常用的调参方式和工具包 常用的调参方式包括网格搜索(Grid Search)、**随机搜索(Random Search)和贝叶斯优化(Bayesian Optimization)**等。 工具包方面&#xff0c;Scikit-learn提供了GridSearchCV和RandomizedSearchCV等用于网格搜索和随机搜索的工具。另外&#xff0c;有一…

CodeWave智能开发平台--03--目标:应用创建--08联系人管理

摘要 本文是网易数帆CodeWave智能开发平台系列的第11篇&#xff0c;主要介绍了基于CodeWave平台文档的新手入门进行学习&#xff0c;实现一个完整的应用&#xff0c;本文主要完成08联系人管理 CodeWave智能开发平台的11次接触 CodeWave参考资源 网易数帆CodeWave开发者社区…

Linux第21步_取消鼠标中键的复制粘贴功能

在ubuntu18.04操作系统中&#xff0c;选中文本后&#xff0c;若按下鼠标中键&#xff0c;就可以执行复制粘贴&#xff0c;相当于 CtrlshiftC 后又按了 CtrlshiftV。在Linux系统中&#xff0c;基本上都是这么配置的。在windows系统中&#xff0c;我们习惯用Ctrl-C复制&#xff0…

intellij idea导入别人项目版本问题解决方案

当导入别人的项目太慢,原因是gradle版本不一致,这时android studio自动下载匹配的gradle版本导致长时间下载的问题。原因主要还是&#xff1a;这个下载地址是国外的&#xff0c;需要翻墙&#xff0c;否则会特别慢。 1.一般下载下来的项目都有这些文件夹&#xff0c;在导入项目…

51单片机介绍

1 单片机简介 单片机&#xff0c;英文Micro Controller Unit&#xff0c;简称MCU 内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能 单片机的任务是信息采集&#xff08;依靠传感器&#xff09;、处理&#xff08;依靠CPU&#xff09;和硬件设…

uniapp 创建组件

组件&#xff1a;用于将某个功能的 HTML、CSS、JS 封装到一个文件中&#xff0c;提高代码的复用性和可维护性。 创建组件 一、在根目录中创建 components 文件夹&#xff0c;右键点击新建组件。 二、输入组件名称、选择默认模板、点击创建组件。 三、在组件中正常编写内容即可…

AcWing 203. 同余方程(扩展欧几里得算法)

题目链接 203. 同余方程 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/205/ 来源 《算法竞赛进阶指南》, NOIP2012提高组 题解 本题中的同余方程可以转化为ax by 1的形式&#xff0c;利用扩展欧几里得算法可以求得特解为&#xff0c;则通解为。 代…

Linux系统使用超详细(九)~用户和组管理

本篇将要梳理有关用户和用户组的学习笔记&#xff0c;内容主要是基本的概念理解和常用命令的使用方法 &#xff01; 目录 一、用户和用户组认识 1.1用户说明 1.1.1查看用户信息 ①id命令&#xff1a; ②whoami 命令 ③cat /etc/passwd 命令 ④getent passwd 命令 ⑤仅显…

Python轴承故障诊断 (十)基于VMD+CNN-Transfromer的故障分类

目录 1 变分模态分解VMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 故障VMD分解可视化 3 基于VMDCNN-Transformer的轴承故障诊断分类 3.1 定义VMD-CNN-Transformer分类网络模型 3.2 设置参数&#xff0c;训练模型 3.3 模型评估 代码、数据如下&#xff1a…

​如何在iOS手机上查看应用日志

引言 在开发iOS应用过程中&#xff0c;查看应用日志是非常重要的一项工作。通过查看日志&#xff0c;我们可以了解应用程序运行时的状态和错误信息&#xff0c;帮助我们进行调试和排查问题。本文将介绍两种方法来查看iOS手机上的应用日志&#xff0c;并提供相应的操作步骤。 …

vercel部署twikoo后评论收不到通知邮件问题解决方法

&#x1f4cc; 前言&#xff1a;本文主要是总结一下在vercel部署twikoo后收不到评论邮件通知问题的解决方法&#xff0c;本人在各种查资料无果后最终去twioo的git官方项目的issue中找到某位大佬给出的原因以及解决方案&#xff0c;故做此记录&#xff0c;希望对遇到此问题的同学…

Nodejs 第三十一章(响应头和请求头)

响应头 HTTP响应头&#xff08;HTTP response headers&#xff09;是在HTTP响应中发送的元数据信息&#xff0c;用于描述响应的特性、内容和行为。它们以键值对的形式出现&#xff0c;每个键值对由一个标头字段&#xff08;header field&#xff09;和一个相应的值组成。 例如…