千家信息网

使用Selenium测试时必需知道的7件事分别有哪些

发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,这篇文章给大家介绍使用Selenium测试时必需知道的7件事分别有哪些,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Selenium是一套用于进行浏览器自动化测试的开源工具集,可
千家信息网最后更新 2025年12月02日使用Selenium测试时必需知道的7件事分别有哪些

这篇文章给大家介绍使用Selenium测试时必需知道的7件事分别有哪些,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

Selenium是一套用于进行浏览器自动化测试的开源工具集,可进行Web应用的端到端测试。Selenium主要包括两个工具:一是Selenium IDE,这是一个在Firefox上运行的插件,可对用户的行为进行录制与回放,还可以将录制的内容生成代码后在Selenium Remote Control上运行。二是本文的重点Selenium WebDriver(简称WebDriver),这是一个开源的项目,能够让用户编写在各种主流浏览器上运行的互操作代码。目前已经推出了支持C#、Java等语言的类库。W3C的WebDriver规范也正是在这个开源项目的基础上发展起来的。

WebDriver可谓QA工程师进行UI测试最强大的利器,它提供了丰富的API以实现访问DOM、运行JavaScript、模拟键盘输入等操作。利用WebDriver进行编程可实现UI测试的完全自动化,为回归测试、乃至持续集成流程提供了极大的便利性。尽管如此,但使用WebDriver编写测试需要投入大量的时间,并且由于浏览器行为的多样性,以及UI的易变性,需要进行大量的代码维护工作。与应用程序的代码一样,编写测试代码同样需要遵循良好的代码规范与设计,糟糕的代码结构会很快使得测试代码的维护变成一个无底洞,最终被团队无奈地抛弃。

在今年的OpenWest 2015大会上,来自Lucidchart的Jared Yarn进行了一场关于Selenium WebDriver测试方面的演讲,并随后撰文总结了演讲的内容。他首先谈起了所在的团队在使用WebDriver时所遇到的困境,当时他们维护着由大约40个不同开发者编写的300多个测试用例(该团队没有专职的测试人员,测试代码全部由开发者编写),每天的运行都会产生70个左右的错误,这一情况在分配了专门的维护人员之后也没有多少改善。为了彻底改进测试集的可靠性、可伸缩性以及可维护性,Yarn与整个团队一起对整个测试代码结构进行了重构。经过重构后,误判的失败率降到了1%以下,并且编写测试的时间也大大缩短了。

Yarn将这次重构的成功归结为以下七点。

创建Application User对象

团队首先要解决的问题是编写测试所需投入的精力过大,为了克服这一点,他们设计了一些实体对象。首先创建的是一种Application User对象,它代表了网站的后端功能,并且通过一些辅助方法提供了准备测试场景、或是在测试完成前进行teardown(清理)工作的功能。以下是使用这种对象的一个示例:

class EditorPerformanceTest extends LucidSpec { val user = new ChartUser override def beforeAll() { user.login() user.createDocument() } … override def afterAll() { user.finished() }

通过这种对象的应用,所有的准备工作被简化成两个方法调用(login与createDocument),而teardown中的逻辑则由finished方法实现,因此开发者可以专注于具体的测试逻辑,将精力集中在bug修复或特性的检测。

创建Application Driver对象

WebDriver的API非常丰富,单是定位某个UI元素就有不下20种做法,这种巨大的灵活性也令人望而生畏。有数之不尽的方式可以完成拖放、单击、滚动以及输入等操作。为了简化这一点,Yarn的团队设计了一种Application Driver类,以简化一些最常见的操作。它首先继承自WebDriver类,并引用了Selenium中的Actions类,随后加入了一些方法用于实现最常见的用户操作,例如单击元素与执行脚本等等。可以通过下面这个UML图概括这个类的设计。

其使用方法如下:

def dragAndDrop(cssFrom: String, cssTo: String) { val elem1 = getElementByCss(cssFrom) val elem2 = getElementByCss(cssTo) actions.dragAndDrop(elem1, elem2) } def contextClickByCss(css: String) actions.contextClick(getElementByCss(css)) }
通过ID访问DOM对象

在WebDriver测试过程中,如何定位一个DOM元素是最有挑战性的任务之一。常见的方式包括XPath、CSS路径以及各种复杂的CSS选择器(类似于jQuery),但这些方式在元素移动了位置或改变了CSS类名之后就会失效,不得不重新修改代码。因此,Yarn建议使用DOM元素的ID进行定位,这种方式的好处是不受元素所在位置、以及所应用的样式的影响。Yarn的团队随后对产品的某一重要特性进行了UI改版,而由于页面中的ID保持不变,因此测试代码的改动非常之少。

页面对象模式

页面对象模式(Page Object Pattern)是测试代码可维护性的关键因素,这一模式本身非常简单,它表示每个页面应了解如何执行该页面当中的所有操作。举例来说,登录页面知道应当如何提交用户的认证信息、如何点击"忘记密码链接"等等操作。如果将这些功能转移到一个公用的地方,就可以在所有测试中重用这部分功能。以下代码表示了一个文档页面的功能:

object DocsList extends RetryHelper with MainMenu with Page { val actionsPanel = new ActionsPanel val fileBrowser = new FileBrowser val fileTree = new FileTreeval sharingPanel = new SharingPanel val invitationPanel = new InvitationPanel

这个页面中的操作非常多,因此Yarn将其分解为多个较小的类,每个类都代表了页面中某个块的功能。它们各自包含在这一区域内可执行的操作的相关方法,正如以下代码所示:

def clickCreateDocument(implicit user: LucidUser) { doWithRetry() { user.clickElement("new-document-button") } } def selectDocument(fileNum: Int=0)(implicit user: LucidUser) { doWithRetry() { user.driver.getElements(docIconCss)(fileNum).click() } } def numberOfDocsEquals(numberOfDocs: Int)(implicit user: LucidUser) : Boolean ={ predicateWithRetry(WebUser.longWaitTime *5, WebUser.waitTime) { numberOfDocuments == numberOfDocs } }
行为的重试

在WebDriver测试过程中,最糟糕的问题在于误判的错误,这为自动化构建过程带来了很大的困难。对于Yarn的团队来说,这个问题也是他们所面对的头号大敌。为了克服这一点,他们为测试加入了重试的功能,使得测试结果得到很大的改善。 以下是这个重试方法的代码:

/** * Try and take an action until it returns a value or we timeout * @param maxWaitMillis the maximum amount of time to keep trying for in milliseconds * @param pollIntervalMillis the amount of time to wait between retries in milliseconds * @param callback a function that gets a value * @tparam A the type of the callback * @return whatever the callback returns, or throws an exception */ @annotation.tailrec private def retry[A](maxWaitMillis: Long, pollIntervalMillis: Long)(callback: => A): A = { val start = System.currentTimeMillis Try { callback } match { case Success(value) => value case Failure(thrown) => { val timeForTest = System.currentTimeMillis - start val maxTimeToSleep = Math.min(maxWaitMillis - pollIntervalMillis, pollIntervalMillis) val timeLeftToSleep = maxTimeToSleep - timeForTest if (maxTimeToSleep <= 0) { throw thrown } else { if (timeLeftToSleep > 0) { Thread.sleep(timeLeftToSleep) } retry(maxWaitMillis - pollIntervalMillis, pollIntervalMillis)(callback) } } } }

这段代码的功能是通过一个简单的递归算法执行所传入的实际行为,直到该行为成功,或是运行超时为止。以下是使用这个方法的简单示例:

def numberOfChildren(implicit user: LucidUser): Int = { getWithRetry() { user.driver.getCssElement(visibleCss).children.size } }
测试集重试

Yarn的团队所做的最后一项改善是配置测试集的重试,测试集重试会将失败的测试缓存起来,然后重新运行这些失败的测试。只要在后续的重试中有一次成功,这项测试就会被认为通过。否则将继续重试,直到重试次数达到上限为止。 Yarn的做法是尽量将一些依赖于第三方功能的行为区分开来,特意为这些功能的集成编写非常健壮的代码似乎没有什么意义,因此可以将它们放到一个可重试的测试集中。对于他们来说,重试的目的不是为了修复测试代码中的问题,而是为了消除测试报告中由误判所带来的影响。

创造乐趣

Selenium的开发很容易令人感到疲惫,许多测试会无故地失败,让这些测试得到正确的结果是非常繁琐的工作,重复性的样板代码令人提不起兴致。而在Yarn的团队建立了一个可靠的、可维护以及可伸缩的框架之后,工作就变得有趣起来了。各种有趣的想法层出不穷,有一位开发者实现了对绘画canvas截图并上传至Amazon S3服务的功能,随后又加入了一个截图比较的工具以实现图片比较测试。其它令人印象深刻的测试还包括与Google Drive、Yahoo与Google的单点登录等功能的整合。整个测试工作开始变得生动起来,这也为团队最终实现了重构的目标带来了极大的推动力。

关于使用Selenium测试时必需知道的7件事分别有哪些就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

测试 代码 功能 团队 对象 页面 方法 运行 元素 行为 工作 开发 内容 开发者 方式 用户 问题 应用 设计 重构 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器联网但不能浏览网页 如何学好计算机中的软件开发 怎么查看服务器日志记录入侵 大数据库表delete优化 华为笔记本代理服务器没响应 我为安全献一计网络安全口号 民生山西服务器失败 不动产数据库建库技术方案 易天天软件开发 网络安全法第二十三条规定全文 网络技术与软件工程就业方向 网络技术招聘英语 济南游戏软件开发招聘网 sql指定月所有数据库 西部证券服务器已关闭 互联网银行科技招聘岗位 路由器配置首选dns服务器 工作室怎么做到全服务器都有金币 数据库软件开发设计报告 数据库技术智慧树答案 如何创建vfp数据库 山西定制oa服务器云主机 券商服务器崩溃造成的损失 关于网页和服务器的关系 掼蛋连接服务器失败是为什么 sql建网站数据库 软件开发北方怎么样 数据库修改物理文件名 ping为什么不通服务器ip sql指定月所有数据库
0