selenium2 java自动化测试实战(修正版)12_05


《Selenium2 Java 自动化测试实战(修正版)》 1 作者:虫师 Selenium2 Java 自动化测试项目实战 (修正版) 《Selenium2 Java 自动化测试实战(修正版)》 2 前言 在刚做测试的一年多时间里,笔者对各种测试技术和工具有着强烈的兴趣和学习欲望,再加上工作较为空 闲,所以有幸接触到 QTP、Selenium 等自动化测试工具,由于当时水平有限,学习也只停留在录制与回放的水 平上。再次学习 Selenium 是时隔一年之后,笔者有幸跳槽到一家互联网公司继续做 web 软件测试,发现项目适 合做自动化测试,于是再次捡起 Selenium。随着能力和眼界的开阔,发现单纯的使用工具的录制与回放并不能 解决实际的问题。Selenium 本身支持多种语言编写脚本,这给我提供了丰富的选择余地。在之前有计划要学习 一门脚本语言,在 Python 与 Ruby 之间犹豫不定。刚好项目组用 Python 开发项目,所以很自然的选择了 Python 和 Selenium 的组合。 从 2013 年开始用 Python 和 Selenium 进行自动化测试的实践,其间的过程颇为艰辛,除了官方文档,相关 的资料并不算太多,尤其是中文资料;相比较而言 Java 和 Selenium 网上的资料要更多一些,这其中主要的原因 是 Java 语言更为流行。 后来认识了乙醇和 MarkRabbit,前者的自动化测试文档给了我很大帮助,后者有丰富的 Python Selenium 自 动化测试项目经验,而且耐心的帮助后来者。在些对这两次前辈表示深深的敬意。 起初只是将 WebDriver API(Python 版)对页面一些操作作为博客进行发表。后来积累了十几篇博客,为了 方便阅读,将其整理了成了一个文档供读者免费下载。再后来就是不断的扩充文档的内容,文档命名为《Selenium WebDriver (python)》(其间更新了三个版本)。2013 年的下半年有了出书的念想,当时以为写书并不算困难。 于是,每天都活在兴奋之间,构思书的结构与内容。到 2013 年年底整理出了一个较为完整的自动化测试的知识 体系,内容不再局限于 Selenium 上,加入了大量的 Python 技术的应用。所以重新命名为《Selenium2 Python 自 动化测试实战》,我带着心虚在传播这份文档,因为有文档中有不少技术我并没真正“吃透”,自然讲解的不 够透彻。 与此同时作者和乙醇的合讲的 Python 与 Selenium 网络课程也在同步进行中。《Selenium2 Python 自动化测 试实战》很自然的成为了我上课的教材。其间收到了大量读者的和学生的反馈,笔者不断对这份文档进行更新, 直到 2015 年春节期间,我才对第二版整理完成。 为什么介绍这么多关于《Selenium2 Python 自动化测试实战》这本电子书的产生过程。是因为《Selenium2 Java 自动化测试实战》是在此基础上整理完成的。因为常常会被问到有没有 Java 版的 Selenium 教程,在我看来如果 你已经会使用 Python + Selenium 编写自动化脚本,那么切换到 Java + Selenium2 编写自动化脚本是非常轻松的, 反之也一样。但对于不少人来讲,可能他们所测试的项目就是用 Java 开发的,他们由于这个原因已经接触了一 些 Java 语言,所以,他们更想在此基础上学习使用 Java + Selenium 开展自动化测试,而不是重新再学习一门其 它语言(虽然,在我看来 Python 的学习成本要比 Java 低);另一方面更希望通过学习自动化测试的过程加强对 Java 语言的实践经验,以便于后续进行更偏向于编程的接口测试或单元测试。 所以,再经过了两个月的左右时间,《Selenium2 Java 自动化测试实战》这本电书初步完成,它是在《Selenium2 Python 自动化测试实战》的基础上,替换掉了里面的 Python 代码改为 Java 代码,但部分章节有所调整。 当然,由于时间仓促,没细心考究书中的一些例子是否优雅,只是为实现需求编写。从刚开始测试工作前 后学习过一段时间 Java 语言,后面由换工作和个人技术方面的转变就没再接触 Java 语言,时隔三年,再次使用 Java,未免有些生疏。总之水平有限,请读者提出更多的建议和意见。 《Selenium2 Java 自动化测试实战(修正版)》 3 最后是书中错别字和错误语句的问题,这也是我比较头痛的问题,当一个版本确定之后就会有读者向我反 馈这些错误,我会及时修正;但是在下次更新内容后又会引入新的错误。所以,请你包涵和理解。 全书的结构: 全书共分 14 章,第 1 章为开始自动化测试之前的所要了解的基础知识。从第 2 章到第 10 章,虽然每一章 所讲的知识点都不一样,但他们之间有非常强的连贯性和相互依赖性,只有弄懂了这几章的内容,才能真正的 开展自动化测试工作。从 11、12 章是在前面的基础对自动化测试水平的扩展和增强;第 13、14 章属于扩展知 识,不管讲 Git 版本工具也好,讲 Jenkins 持续集成也好,有意在提升读者的综合开发的水平。 2015.7.12 虫师 (修正版)说明: 根据读者反馈书中的一些错误,以及随着时间的推移,个人对自动化测试也有了新的认识,修正和更 新了书中部分章节的内容。 2015.12.5 虫师 声明 本电子书的著作权归虫师个人所有,禁止一切网络的传播和共享,请尊重作者的劳动成果。 《Selenium2 Java 自动化测试实战(修正版)》 4 目录 Selenium2 Java..................................................................................................................................................... 1 前言.......................................................................................................................................................................2 目录.......................................................................................................................................................................4 第 1 章 自动化测试基础.................................................................................................................................... 8 1.1 软件测试分类..................................................................................................................................... 8 1.2 分层的自动化测试........................................................................................................................... 11 1.3 什么样的项目适合自动化测试.......................................................................................................14 1.4 自动化测试及工具简述................................................................................................................... 15 1.5 Selenium 工具介绍........................................................................................................................... 15 1.6 前端技术介绍................................................................................................................................... 17 1.7 前端工具介绍................................................................................................................................... 19 1.8 开发语言的选择............................................................................................................................... 20 第 2 章 测试环境搭建...................................................................................................................................... 22 2.1 Window 下环境搭建........................................................................................................................ 22 2.4 编写第一个自动化脚本................................................................................................................... 32 2.5 安装浏览器驱动............................................................................................................................... 34 2.5 不同编程语言下使用 WebDriver....................................................................................................35 第 3 章 Java 编程基础..................................................................................................................................... 38 3.1 输出与输入....................................................................................................................................... 38 3.2 分支与循环....................................................................................................................................... 40 3.3 数组与字典....................................................................................................................................... 44 3.4 类与对象........................................................................................................................................... 47 3.5 import 和 package..............................................................................................................................51 3.6 异常....................................................................................................................................................53 第 4 章 WebDriver API.................................................................................................................................... 58 4.1 从定位元素开始............................................................................................................................... 58 4.2 控制浏览器....................................................................................................................................... 68 4.3 简单元素操作................................................................................................................................... 71 4.4 鼠标事件........................................................................................................................................... 74 4.5 键盘事件........................................................................................................................................... 77 4.6 获得验证信息................................................................................................................................... 79 4.7 设置元素等待................................................................................................................................... 80 4.8 定位一组元素................................................................................................................................... 83 4.9 多表单切换....................................................................................................................................... 87 4.10 多窗口切换..................................................................................................................................... 89 4.11 警告框处理..................................................................................................................................... 91 4.12 上传文件......................................................................................................................................... 92 4.14 下载文件......................................................................................................................................... 98 4.15 操作 Cookie...................................................................................................................................100 4.16 调用 JavaScript..............................................................................................................................102 4.17 处理 HTML5 的视频播放............................................................................................................104 4.18 窗口截图....................................................................................................................................... 106 《Selenium2 Java 自动化测试实战(修正版)》 5 4.19 关闭窗口....................................................................................................................................... 107 4.20 验证码的处理............................................................................................................................... 107 4.21 WebDriver 原理............................................................................................................................ 109 本章小结.................................................................................................................................................. 110 第 5 章 图形自动化语言 Sikuli...................................................................................................................111 5.1 sikuli-X 工具介绍........................................................................................................................... 111 5.2 在 Java 中使用 Sikuli......................................................................................................................117 第 6 章 自动化测试模型................................................................................................................................120 6.1 自动化测试模型介绍..................................................................................................................... 120 6.2 模块化实例..................................................................................................................................... 124 6.3 数据驱动实例................................................................................................................................. 128 本章小结.................................................................................................................................................. 137 第 7 章 Selenium IDE.................................................................................................................................... 138 7.1 Selenium IDE 安装......................................................................................................................... 138 7.2 Selenium IDE 界面介绍................................................................................................................. 140 7.3 创建测试用例................................................................................................................................. 141 7.4 Selenium IDE 命令......................................................................................................................... 144 7.5 断言与验证..................................................................................................................................... 147 7.6 等待与变量..................................................................................................................................... 150 本章小结.................................................................................................................................................. 151 第 8 章 Junit 单元测试框架.........................................................................................................................152 8.1 导出 Junit 自动化测试脚本........................................................................................................... 152 8.2 Junit 单元测试框架解析................................................................................................................ 158 8.3 用 Junit 编写 web 自动化...............................................................................................................169 本章小结.................................................................................................................................................. 172 第 9 章 TestNG 单元测试框架.......................................................................................................................173 9.1 Eclipse 中安装 TestNG...................................................................................................................173 9.2 TestNG 注释....................................................................................................................................175 9.3 testng.xml 文件................................................................................................................................176 9.4 运行测试用例................................................................................................................................. 179 9.5 TestNG 测试技巧............................................................................................................................183 9.6 查看测试结果................................................................................................................................. 189 第 10 章 Page Object 设计模式...................................................................................................................191 10.1 认识 Paget Object..........................................................................................................................191 10.2 Paget Object 实例..........................................................................................................................192 第 11 章 Selenium Grid2.............................................................................................................................. 196 11.1 Selenium Server 环境配置............................................................................................................196 11.2 Selenium Grid 工作原理...............................................................................................................198 11.3 Selenium Grid 应用.......................................................................................................................201 11.4 WebDriver 驱动............................................................................................................................ 209 本章小结.................................................................................................................................................. 216 第 12 章 自动化测试项目实战......................................................................................................................218 12.1 自动化测试用例设计................................................................................................................... 218 12.2 126 邮箱项目实战........................................................................................................................ 220 本章小结.................................................................................................................................................. 229 《Selenium2 Java 自动化测试实战(修正版)》 6 第 13 章 Git 管理项目...................................................................................................................................230 13.1 Git/GitCafe 托管测试项目........................................................................................................... 230 13.2 Git/Git Server 搭建....................................................................................................................... 242 第 14 章 Maven 基础.......................................................................................................................................251 14.1 安装与配置................................................................................................................................... 251 14.2 包的管理与更新........................................................................................................................... 255 14.3 安装 Selenium............................................................................................................................... 258 14.4 运行 Junit Selenium 测试............................................................................................................. 259 本章小结.................................................................................................................................................. 262 第 15 章 持续集成 Jenkins 入门..................................................................................................................264 15.1 环境搭建....................................................................................................................................... 264 15.2 创建任务....................................................................................................................................... 267 15.3 运行构建....................................................................................................................................... 270 15.4 定时执行构建............................................................................................................................... 272 本章小结.................................................................................................................................................. 274 附录...................................................................................................................................................................275 XPath 语法............................................................................................................................................... 275 CSS 选择器参考手册.............................................................................................................................. 278 参考...........................................................................................................................................................280 《Selenium2 Java 自动化测试实战(修正版)》 7 《Selenium2 Java 自动化测试实战(修正版)》 8 第1章 自动化测试基础 在正式开始本书的学习之前,我们有必要先来了解什么是软件测试,以及软件自动化测试相关的概念 和工具,这将有助于对本书后面内容的学习。 1.1 软件测试分类 软件测试领域名词颇多,许多测试新手容易混淆概念。因为从不同的角度对软件测试有不同的分类方法, 所以,这里汇总常见软件测试的相关名词,让读者对软件测试领域有个概括性了解。 根据项目流程阶段划分软件测试 图 1.1 是一个典型的“V”模型软件开发流程,各项软件测试工作是在项目开发流程中循序渐进进行的。下 面将介绍各个阶段测试的含义。 1)单元测试:单元测试(或模块测试)是对程序中的单个子程序或具有独立功能的代码段进行测试的过程。 2)集成测试:集成测试是在单元测试的基础上,先通过单元模块组装成系统或子系统,再进行测试。重点 是检查模块之间的接口是否正确。 3)系统测试:系统测试是针对整个产品系统进行的测试,验证系统是否满足需求规格的定义,以及软件系 统的正确性和性能等是否满足其需求规格的要求。 4)验收测试:验收测试是部署软件之前的最后一个测试阶段。验收测试的目的是确保软件准备就绪,向软 件购买者展示该软件系统能够满足用户的需求。 图 1.1 项目流程与对应的测试 白盒测试、黑盒测试、灰盒测试 白盒测试与黑盒测试,主要是根据软件测试工作中对软件代码的可见程度进行的划分。这也是软件测试领 域中最基本的概念之一,如图 1.2 所示 《Selenium2 Java 自动化测试实战(修正版)》 9 图 1.2 黑盒测试与白盒测试 1)黑盒测试。 黑盒测试,指的是把被测的软件看作一个黑盒子,我们不去关心盒子里面的结构是什么样子的,只关心软 件的输入数据和输出结果。 它只检查程序呈现给用户的功能是否按照需求规格说明书的规定正常使用,程序是否能接收输入数据并产 生正确的输出信息。黑盒测试着眼于程序外部结构,不考虑内部逻辑结构,主要针对软件界面和软件功能进行 测试。 2)白盒测试。 白盒测试,指的是把盒子打开,去研究里面的源代码和程序执行结果。 它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进 行,检验程序中的每条逻辑路径是否都能按预定要求正确工作。 3)灰盒测试。 灰盒测试介于黑盒测试与白盒测试之间。 可以这样理解,灰盒测试既关注输出对于输入的正确性,同时也关注内部表现。但这种关注不像白盒测试 那样详细、完整,它只是通过一些表征性的现象、事件、标志来判断内部的运行状态。有时候输出是正确的, 但内部其实已经错误了,这种情况非常多。如果每次都通过白盒测试来操作,效率会很低,因此需要采取灰盒 测试的方法。 功能测试与性能测试 从软件的不同测试面可以划分为功能测试与性能测试。 1)功能测试。 功能测试主要检查实际功能是否符合用户的需求,因此测试的大部分工作也是围绕软件的功能进行。设计 软件的目的就是满足用户对其功能的需求,如果偏离了这个目的,则任何测试工作都是没有意义的。 功能测试又可以细分为很多种:逻辑功能测试、界面测试、易用性测试、安装测试、兼容性测试等。 2)性能测试。 《Selenium2 Java 自动化测试实战(修正版)》 10 性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测 试。 软件的性能包括很多方面,主要有时间性能和空间性能两种。 时间性能:主要是指软件的一个具体的响应时间。例如一个登录所需要的时间,一个商品交易所需要的时 间等。当然,抛开具体的测试环境,来分析一次事务的响应时间是没有任何意义的。需要搭建一个具体且独立 的测试环境下进行。 空间性能:主要指软件运行时所消耗的系统资源,例如硬件资源,CPU、内存,网络带宽消耗等。 手工测试与自动化测试 从对软件测试工作的自动化程度可以划分为手工测试与自动化测试。 1)手工测试。 手工测试就是由测试人员一个一个地去执行测试用例,通过键盘鼠标等输入一些参数,并查看返回结果是 否符合预期结果。 手工测试并非专业术语,它通常是指我们在系统测试阶段所进行的功能测试,为了更明显的与自动化测试 进行区分,所以这里使用了手工测试这种说法。 2)自动化测试。 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。通常,在设计测试用例并通过评审之 后,由测试人员根据测试用例中描述的规则流程一步步执行测试,把得到实际结果与期望结果的比较。在此过 程中,为了节省人力、时间和硬件资源,提高测试效率,便引入了自动化测试的概念。 自动化测试又可分为:功能自动化测试与性能自动化测试。 功能自动化测试:它是把以人为驱动的测试行为转化为机器执行的一种过程。通过测试工具(或框架)录 制/编写测试脚本,对软件的功能进行测试,并验证测试结果是否正确,从而代替部分的手工测试工作,达到节 约人力成本和时间成本的目的。 性能自动化测试:通过性能工具来模拟成千上万的虚拟用户向系统发送请求,从而来验证系统的处理能力。 冒烟测试、回归测试、随机测试、探索性测试和安全测试 这几种测试出现在软件测试的周期中,既不算具体明确的测试阶段,也不是具体的测试方法。 1)冒烟测试。 是指在对一个新版本进行大规模的系统测试之前,先验证一下软件的基本功能是否实现,是否具备可测性。 引入到软件测试中,就是指测试小组在正式测试一个新版本之前,先投入较少的人力和时间验证一个软件 的主要功能,如果主要功能都没有运行通过,则打回开发组重新开发。这样做的好处是可以节省时间和人力投 入到不可测的项目中。 2)回归测试。 回归测试是指修改了旧代码后,重新进行测试以确认修改后没有引入新的错误或导致其他代码产生错误。 回归测试一般是在进行软件的第二轮测试时开始的,验证第一轮中发现的问题是否得到修复。当然,回归 也是一个循环的过程,如果回归的问题通不过,则需要开发人员修改后再次进行回归,直到所有问题回归通过 《Selenium2 Java 自动化测试实战(修正版)》 11 为止。 3)随机测试。 是指测试中的所有输入数据都是随机生成的,其目的是模拟用户的真实操作,并发现一些边缘性的错误。 随机测试可以发现一些隐蔽的错误,但是也有很多缺点,例如测试不系统、无法统计代码覆盖率和需求覆 盖率、发现的问题难以重现等。一般是放在测试的最后执行。其实,随机测试更专业的升级版叫探索性测试 。 4)探索性测试。 探索性测试可以说是一种测试思维技术,它没有很多实际的测试方法、技术和工具,但是却是所有测试人 员都应该掌握的一种测试思维方式。探索性测试强调测试人员的主观能动性,抛弃繁杂的测试计划和测试用例 设计过程,强调在碰到问题时及时改变测试策略。 5)安全测试。 安全测试是在 IT 软件产品的生命周期中,特别是产品开发基本完成到发布阶段,对产品进行检验以验证产 品符合安全需求定义和产品质量标准的过程。 安全测试现在越来越受到企业的关注和重视,因为由于安全性问题造成的后果是不可估量的,尤其是互联 网产品,最容易遭受各种安全攻击。 1.2 分层的自动化测试 测试金字塔的概念由敏捷大师 Mike Cohn 在他的《Succeeding with Agile》一书中首次提出,如图 1.3所示。他的基本观点是:我们应该有更多的低级别的单元测试,而不仅仅是通过用户界面运行的高层 的端到端的测试。 图 1.3 测试金字塔 Martin Fowler 大师在测试金字塔模型的基础上提出分层自动化测试的概念,如图1.4所示。在自动化 测试之前加了一个“分层”的修饰,用来区别于“传统的”自动化测试。那么什么是传统的自动化测试? 《Selenium2 Java 自动化测试实战(修正版)》 12 为何要提倡分层自动化测试的思想呢? 所谓传统的自动化测试我们可以理解为基于产品 UI 层的自动化测试,它是将黑盒功能测试转化为由 程序或工具执行的一种自动化测试。 在目前的大多数研发组织当中,都存在开发与测试团队割裂(部门墙)、质量职责错配(测试主要对 质量负责)的问题,在这种状态下,测试团队的一个“正常”反应就是试图在测试团队能够掌控的黑盒测 试环节进行尽可能全面的覆盖,甚至是尽可能全面的 UI 自动化测试。 这可能会导致两个恶果:一是测试团队规模的急剧膨胀;二是所谓的全面 UI 自动化测试运动。因为 UI 是非常易变的,所以 UI 自动化测试维护成本相对高昂。 分层自动化测试倡导的是从黑盒(UI)单层到黑白盒多层的自动化测试体系,从全面黑盒自动化 测试到对系统的不同层次进行自动化测试,如图 1.4 所示。 图 1.4 分层自动化测试 单元自动化测试 单元测试是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说, 要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数、Java 中单元指一个类、图形化的软件中 单元可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。规范的进行单 元测试就需要借助单元测试框架,如 java 语言的 Junit、TestNG,C#语言的 NUnit,以及 Python 语言的 unittest、pytest 等,目前几乎所有的主流语言都会有其相应的单元测试框架。 Code Review 中文翻译为代码评审或代码审查,是指在软件开发过程中,通过对源代码进行系统性检 查的过程。通常的目的是查找系统缺陷,保证软件总体质量和提高开发者自身水平。与 Code Review 相关 的插件与工具有很多,例如 Java 语言中基于 Eclipse 的 Review Clipse 和 Jupiter、主要针对 Python 语 言的 Review Board 等。 Unit Service UI UI 界面层 业务逻辑层 数据处理层 UI 自动化测试 JS 自动化测试 模块接口测试 web 接口测试 单元测试 Code Review 《Selenium2 Java 自动化测试实战(修正版)》 13 接口自动化测试 根据笔者的理解,Web 应用的接口测试大体分为两类:模块接口测试和 Web 接口测试。 (1)模块接口测试,主要测试模块之间的调用与返回。当然,我们也可以将其看作是单元测试的基 础。它主要强调对一个类方法或函数的调用,并对返回结果的验证,所用到的测试工具与单元测试相同。 (2)Web 接口测试又可分为两类:服务器接口测试和外部接口测试。  服务器接口测试:指测试浏览器与服务器的接口。我们知道 Web 开发一般分前端和后端,前端开 发人员用 HTML/CSS/JavaScript 等技术,后端开发人员用 PHP/Java/C#/Python/Ruby 等各种语言。 用户的操作是在前端页面上,需要后端提供服务器接口,把前端通过调用这些接口来获得需要的 数据,通过 HTTP 协议来实现前后端的数据传递。  外部接口测试:指调用的接口由第三方系统提供。典型的例子就是第三方登录,例如新上线的产 品为了免于新用户注册账号的麻烦会提供第三方登录,那么用户在登录的时候调用的就是第三方 登录的接口,用户登录信息的验证由第三方完成,并返回给当前系统是否验证通过。 当然,接口测试也有相应的类库或工具,例如测试 HTTP 的有 HttpUnit、Postman 等。 UI 自动化测试 UI 层是用户使用该产品的入口,所有功能都通过这一层提供并展示给用户,所以大多测试工作都集中 在这一层进行。为了减轻这一层的测试人力和时间成本,早期的自动化测试工具主要针对该层设计。目前 主流的测试工具有 UFT、Watir、Robot Framework、Selenium 等。 除了 UI 层所展示的功能外,前端代码同样需要进行测试。在前端开发中最主要的莫过于 JavaScript 脚本语言,而 QUnit 就是针对 JavaScript 的一个强大的单元测试框架。 图1.4中的测试金字塔映射了不同测试阶段所投入的自动化测试的比例,UI 层被放到了塔尖,这也说 明 UI 层应该投入较少的自动化比例。如果系统只关注 UI 层的自动化测试并不是一种明智的做法,因为其 很难从本质上保证产品的质量。如果妄图实现全面的 UI 层的自动化测试,那么需要投入大量的人力和时 间,然而,最终获得的收益可能远低于所投入的成本。因为对于一个系统来讲,越接近用户其越容易变化, 为了不断适应这种变化就必然需要投入更多的成本。 既然 UI 层的自动化测试这么劳民伤财,那么我们是不是只做单元测试与接口测试就可以了呢?答案 是否定的,因为不管什么样的产品,最终呈现给用户的是 UI 层的功能,所以产品才需要招聘大量的测试 人员进行 UI 层的功能测试。也正是因为测试人员在 UI 层投入了大量的时间与精力,所以我们才有必要通 过自动化的方式帮助测试人员解放部分重复的工作。所以,笔者更提倡“半自动化”的开展测试工作,把 可以自动化测试的工作交给工具或脚本完成,这样测试人员就可以把更多的精力放在更重要的测试工作 上,例如探索性测试等。 至于在金字塔中每一层测试的投入比例则要根据实际的产品特征来划分。在《Google 测试之道》一书中提 到,Google 对产品测试类型划分为:小测试、中测试和大测试,采用 70%(小)/20%(中)/10%(大)的比例, 大体对应测试金子塔中的 Unit、Service 和 UI 层。 《Selenium2 Java 自动化测试实战(修正版)》 14 在进行自动化测试中最担心的是变化,因为变化会直接导致测试用例的运行失败,所以需要对自动化脚本 进行不断调整。如何控制失败,降低维护成本是对自动化测试工具及人员能力的挑战。反过来讲,一份永远都 运行通过的自动化测试用例已经失去了它存在的价值。 1.3 什么样的项目适合自动化测试 相信在你拿到这本书时已经对要进行自动化的项目做了一些分析和考量,但在这里我们还是有必要说明一 下什么样的项目适合尝试进行自动化测试,以免读者在不太适合自动化测试的项目中痛苦挣扎,既浪费了大量 的人力和时间,又收效甚微。 (1)任务测试明确,不会频繁变动。 (2)每日构建后的测试验证。 (3)比较频繁的回归测试。 (4)软件系统界面稳定,变动少。 (5)需要在多平台上运行的相同测试案例、组合遍历型的测试,大量的重复任务。 (6)软件维护周期长。 (7)项目进度压力不太大。 (8)被测软件系统开发比较规范,能够保证系统的可测试性。 (9)具备大量的自动化测试平台。 (10)测试人员具备较强的编程能力。 当然,并非以上 10 条都具备的情况下才能开展自动化测试工作,因此需要读者做出权衡。在我们普遍的自 动化测试经验中,一般满足以下三个条件就可以对项目开展自动化测试。 1)软件需求变动不频繁。 自动化测试脚本变化的大小与频率决定了自动化测试的维护成本。如果软件需求变动过于频繁,那么测试 人员就需要根据变动的需求来不断地更新自动化测试用例,从而适应新的功能。而脚本的维护本身就是一个开 发代码的过程,需要扩展、修改、调试,有时候还需要对架构做出调整。如果所花费的维护成本高于利用其节 省的测试成本,那么自动化测试就失去了它的价值与意义。 一种折中的做法就是先对系统中相对稳定的模块与功能进行自动化测试,而变动较大的部分用手工测试进 行。 2)项目周期较长。 由于自动化测试需求的确定、自动化测试框架的设计、脚本的开发与调试均需要时间来完成。这个过程本 身就是一个软件的开发过程,如果项目的周期比较短,没有足够的时间去支持这样一个过程的话,那么就不需 要进行自动化测试了。 3)自动化测试脚本可重复使用。 自动化测试脚本的重复使用要从三个方面来考量:一是所测试的项目之间是否存有很大的差异性(如 C/S 系统架构与 B/S 系统架构的差异);二是所选择的测试技术或工具是否适应这种差异;三是测试人员是否有能 力设计开发出适应这种差异的自动化测试框架。 《Selenium2 Java 自动化测试实战(修正版)》 15 1.4 自动化测试及工具简述 自动化测试的概念有广义与狭义之分:广义上来讲,所有借助工具来辅助进行软件测试的方式都可以称为 自动化测试;狭义上来讲,主要指基于 UI 层的功能自动化测试。 注意:如果没有特别说明,则本文所说的“自动化测试”均指“基于 UI 的功能自动化测试”。 目前市面上的自动化测试工具非常多,下面几款是比较常见的自动化测试工具。 1)UFT。 UFT(全称 Unified Functional Testing)由 QTP(Quick Test Professional software)与 ST(Service Test) 合并而来,由 HP 公司开发。它是一种企业级的自动测试工具,提供了强大易用的录制回放功能,同时兼 容对象识别模式与图像识别模式两种识别方式,支持 B/S 与 C/S 两种架构的软件测试,是目前主流的自 动化测试工具。 2)Robot Framework。 Robot Framework 是一款基于 Python 语言编写的自动化测试框架,具备良好的可扩展性,支持关键字驱动, 可以同时测试多种类型的客户端或者接口,可以进行分布式测试。 3)Watir。 Watir 全称是“Web Application Testing in Ruby”,是一种基于 Web 模式的自动化功能测试工具。Watir 是一 个 Ruby 语言库,使用 Ruby 语言进行脚本开发。 4)Selenium。 Selenium 也是一个用于 Web 应用程序测试的工具,支持多平台、多浏览器、多语言去实现自动化测试。目 前在 Web 自动化领域应用越来越广泛。 当然,除上面所列的自动化测试工具外,根据不同的应用还有很多商业的或开源的以及公司自己开发的自 动化测试工具。 1.5 Selenium 工具介绍 什么是 Selenium? Selenium 主要用于 Web 应用程序的自动化测试,但并不局限于此,它还支持所有基于 Web 的管理任务自动 化。 Selenium 的特点如下。  开源,免费;  多浏览器支持:FireFox、Chrome、IE、Opera、Edge;  多平台支持:Linux 、Windows、MAC;  多语言支持:Java、Python、Ruby、C#、JavaScript、C++;  对 Web 页面有良好的支持;  简单(API 简单)、灵活(用开发语言驱动);  支持分布式测试用例执行。 Selenium 经历了两个版本,Selenium 1.0 和 Selenium 2.0 。Selenium 不是由单独一个工具构成的,而是由 《Selenium2 Java 自动化测试实战(修正版)》 16 一些插件、类库组成,每个部分都有其特点和应用场景,Selenium1.0 家谱,如下图 1.5 所示 Selenium 1.0 Selenium IDE Selenium Grid Selenium RC Client Server Http Proxy CoreLauncher 图 1.5 Selenium1.0 家谱 Selenium IDE Selenium IDE 是嵌入到 Firefox 浏览器中的一个插件,实现简单的浏览器操作的录制与回放功能。那么什么 情况下用到它呢?官方给出了它自身作用的定位: 快速地创建 bug 重现脚本,在测试人员测试过程中,发现 bug 之后可以通过 IDE 将重现的步骤录制下来, 以帮助开发人员更容易地重现 bug。 IDE 录制的脚本可以转换成多种语言,从而帮助我们快速地开发脚本。关于这个功能在后面的章节中我们 会着重介绍。 Selenium Grid Selenium Grid 是一种自动化的测试辅助工具,Grid 通过利用现有的计算机基础设施,能加快 Web-App 的功 能测试。利用 Grid 可以很方便地实现在多台机器上和异构环境中运行测试用例。 Selenium RC Selenium RC(Remote Control)是 Selenium 家族的核心部分。Selenium RC 支持多种不同的语言编写自动 化测试脚本,通过 Selenium RC 的服务器作为代理服务器去访问应用,从而达到测试的目的。 Selenium RC 分为 Client Libraries 和 Selenium Server。Client Libraries 库主要用于编写测试脚本,用来控制 Selenium Server 的库。 Selenium Server 负责控制浏览器行为。总的来说,Selenium Server 主要包括三个部分:Launcher、Http Proxy 和 Core。其中,Selenium Core是被Selenium Server嵌入到浏览器页面中的。其实 Selenium Core就是一堆JavaScript 函数的集合,即通过这些 JavaScript 函数,我们才可以实现用程序对浏览器进行操作。Launcher 用于启动浏览器, 把 Selenium Core 加载到浏览器页面当中,并把浏览器的代理设置为 Selenium Server 的 Http Proxy。 Selenium 2.0 搞清了 Selenium 1.0 的家族关系,再来看看 Selenium 2.0。Selenium 2.0 就是把 WebDriver 加入到了这个家 族中,简单用公式表示为: 《Selenium2 Java 自动化测试实战(修正版)》 17 Selenium 2.0 = Selenium 1.0 + WebDriver 需要强调的是,在 Selenium 2.0 中主推的是 WebDriver,可以将其看作 Selenium RC 的替代品。因为 Selenium 为了保持向下的兼容性,所以在 Selenium2.0 中并没有彻底地抛弃 Selenium RC。如果是初次使用 Selenium 开发 一个新的自动化测试项目,那么可以直接使用 WebDriver。Selenium RC 与 WebDriver 有什么区别呢? Selenium RC 是在浏览器中运行 JavaScript 应用,使用浏览器内置的 JavaScript 翻译器来翻译和执行 selenese 命令(selenese 是 Selenium 命令集合)。 WebDriver 是通过原生浏览器支持或者浏览器扩展来直接控制浏览器。WebDriver 针对各个浏览器而开发, 取代了嵌入到被测Web 应用中的JavaScript。与浏览器的紧密集成,因此支持创建更高级的测试,避免了JavaScript 安全模型导致的限制。除了来自浏览器厂商的支持之外,WebDriver 还利用操作系统级的调用,模拟用户输入。 Selenium 与 WebDriver 原先属于两个不同的项目,WebDriver 的创建者 Simon Stewart 早在 2009 年 8 月的一 份邮件中解释了项目合并的原因。 Selenium 与 WebDriver 合并原因:为何把两个项目合并?部分原因是 WebDriver 解决了 Selenium 存在的缺点(例如能够绕过 JavaScript 沙箱,我们有出色的 API),部分原因是 Selenium 解决了 WebDriver 存在的问题(例如支持广泛的浏览器),部分原因是因为 Selenium 的主要贡献者 和我都觉得合并项目是为用户提供最优秀框架的最佳途径。 1.6 前端技术介绍 由于 Selenium 是基于 Web 的自动化测试技术,而我们要操作的对象是 Web 页面,所以有必要对前端 Web 的技术与工具作一个简单介绍。 HTML 简介 HTML(Hyper Text Markup Language)中文为超文本标记语言,是网页的基础。它并不是一种编程语言, 而是一种标记语言(一套标记标签),但我们可以在 HTML 标签中嵌入各种前端脚本语言,如 VBScript、JavaScript 等。下面是一个简单的 HTML 页面: index.html 标题

正文

与 之间的文本用于描述网页。 与之间的用于定义文档的头部,它是所有头部元素的容器。 之间的内容显示在浏览器的标题栏。 与 之间的文本是可见的页面内容。 《Selenium2 Java 自动化测试实战(修正版)》 18

之间的文本被显示为正文,h1 表示为一号字体。 现在我们通过浏览器打开任意一个页面,在页面上的右键菜单中单击“查看网页源代码”,在复杂的前端 代码中依然可以找到 HTML 的身影。 当然,HTML 还定义了其他许多标签,读者可以登录 w3school 网站学习。 JavaScript 简介 JavaScript是一种由Netscape公司的LiveScript发展而来的前端脚本语言(脚本语言是一个种轻量级的语言), 是一种解释性语言(代码执行不需要预编译),被设计用来向 HTML 页面添加交互行为,通常被直接嵌入到 HTML 页面。 如果要在 HTML 页面中使用 JavaScript,则需要添加 通过 就可以告诉浏览器 ,JavaScript 脚本从何处开始,到何处结 束。使用 document.write()可以向文档输出内容。 XML 简介 XML 是指扩展标记语言,是标准通用标记语言的一个子集。与 HTML 类似,但它并非 HTML 的替代品, 它们为不同的目的而设计。HTML 被设计用来显示数据,其焦点是数据的外观;XML 被设计为传输和存储数 据,其焦点是数据的内容。 下面是一个简单的 XML 文件。 xml_file.xml George John Reminder Don't forget the meeting! 一个应该包含 XML 的声明,它定义了 XML 文档的版本号。 定义了文档里的第一个元素,也叫根元素。 、 为根元素的子元素,他们分别包含了发 送者与接收者的信息。这个 XML 文档仅仅是用标签包装了纯粹的信息,我们需要编写软件或程序,才能传送、 接收和显示出这个文档。 XML 允许我们自己定义标签,上例中的标签没在任何 XML 标准中定义过,如,这些标签是 《Selenium2 Java 自动化测试实战(修正版)》 19 由我们自己定义的。 上面只是简单介绍了 HTML、JavaScript 以及 XML 等前端技术,了解这些技术将有助于我们顺利地进行 Web 自动化测试工作进行。 1.7 前端工具介绍 FireBug FireBug 是 FireFox 浏览器下的一套开发类插件,相信很多读者对这款前端工具并不陌生。它集 HTML 查看 和编辑、Javascript 控制台、网络状况监视器、Cookie 查看于一体,是开发 JavaScript、CSS、HTML 和 Ajax 的 得力助手,如图 1.6 所示。 图 1.6 FireBug 我们可以通过它方便地查看页面上的元素,从而根据其属性进行定位。在 Web 自动化测试脚本的编写过程 中,此工具起着至关重要的作用。 FireBug 安装方式:首先在 FireFox 浏览器的菜单栏中单击 tools(工具)—>add-ons Manager(添加组件), 搜索 FireBug。然后对搜索到的插件进行安装,安装完成后重启浏览器,即可在工具栏看到 FireBug 的按钮。 FirePath FirePath 是 FireBug 插件扩展的一个工具,用来编辑、检查和生成的 XPath1.0 表达式、CSS 3 选择器以及 jQuery 选择器。可以快速帮助我们通过 XPath 和 CSS 来定位页面上的元素,如图 1.7 所示。 图 1.7 FirePath 当通过 FireBug 的鼠标箭头选择一个页面元素后,FirePath 输入框将给出 XPath 的表达式,快速的帮我们定 位元素。我们可以点击“XPath: ”按钮切换到 CSS 定位方式,从而获得一个元素的 CSS 定位方式。FirePath 的 安装方式与 FireBug 类似。 Chrome 和 IE 的开发人员工具 Chrome 和 IE 浏览器同样也提供了类似 FireBug 的开发人员工具,可以帮助我们定位页面元素。 Chrome 浏览器默认自带 Chrome 开发人员工具,单击 Chrome 浏览器右上角的菜单按钮,在下拉菜单中选 择“工具”—>“开发人员工具”即可打开,还可以通过快捷键 Ctrl+Shift+I 或 F12 打开,如图 1.8 所示。 《Selenium2 Java 自动化测试实战(修正版)》 20 图 1.8 Chrome 开发人员工具 IE 浏览器从 IE8 版本开始加入了开发人员工具,用起来也非常方便。单击菜单栏“工具”—>“F12 开发人 员工具”或者通过快捷键 F12 即可打开。值得一提的是,它提供了浏览器的兼容模式,我们可以通过选择浏览 器模式切换到不同的 IE 版本。如图 1.9,这将非常方便地帮助我们测试 IE 浏览器的兼容性。 图 1.9 IE 开发人员工具 1.8 开发语言的选择 通过前面的介绍,我们了解到 Selenium WebDriver 支持多种语言的开发,Java、Python、Ruby、PHP、C#、 JavaScript 等,那么我们应该选择哪一种语言结合 Selenium WebDriver 进行开发呢?这里笔者给出一点自己的看 法。 关于 Java 语言我这里就不做过多的介绍,目前大量大型项目都是基于 Java 语言开发的。这里截取了 2015 年 1 月的编程语言排名。 《Selenium2 Java 自动化测试实战(修正版)》 21 图 1.10 编程语言排名 当然,这个排名并不能说明一门编程语言的好坏,但至少可以反映编程语言受关注的程度和使用率。 这也是为什么我编写了《Selenium2 Python 自动化测试实战》后,很多同学问我有没有 Java 版的,什么时 候出 Java,这是因为他们所测试的项目是由 Java 语言开发。学习和使用 Java 语言除了可以完成自动化测试外, 还可以提升 Java 能力,从而更深入的了解所测试的项目,完成接口测试或单元测试等。 所以,这也是我为什么决定再花些时间来做个 Java 版的原因。 《Selenium2 Java 自动化测试实战(修正版)》 22 第2章 测试环境搭建 也许你已经迫不及待地坐在了电脑面前,想要开始自动化测试之旅。不要着急,在此之前,我们需要 先搭建好测试所需的开发环境。如果你选择使用 Java 和 Selenium 来从事自动化测试工作,从这本书开始, 没错的! 2.1 Window 下环境搭建 Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效 性、平台移植性和安全性,广泛应用于 PC、数据中心、游戏控制台、科学超级计算机、移动开奖直播,香港马会王中王资料和互联 网,同时拥有全球最大的开发者专业社群。 2.1.1 安装 Java 访问 Java 官方网站:http://www.java.com/zh_CN/ 在大多 Java 的书都会提到 Java 的跨平台性,为什么 Java 可以跨平台是因为 Java 虚拟机(Java Virtual Machine ----JVM)的存在,Java 的开发都针对不同的平台开发了不同的 Java 虚拟机,Java 程序运行于 Java 虚拟机之上,所以有 Java 虚拟机的地方就能运行 Java 程序。当然,在 Java 虚拟机上不仅仅可以运行 Java 语言, Jython、 JRuby、Groovy、Scala 等语言都可以在 Java 虚拟机上运行。 Java 下载手机最快报码现场直播,4887开奖现场结果:http://www.java.com/zh_CN/download/manual.jsp 小知识: Java 环境分 JDK 和 JRE,JDK 就是 Java Development Kit。简单的说 JDK 是面向开发人员使用的 SDK,它提供了 Java 的开发环境和运行环境。JRE 是 Java Runtime Enviroment 是指 Java 的运行环境, 是面向 Java 程序的使用者。 打开下载链接选择相应的版本进行下载。我们以 Windows 安装 JDK 为例, 《Selenium2 Java 自动化测试实战(修正版)》 23 图 2.1 安装 JDK 双击下载的 JDK,设置安装路径。这里我们选择默认安装在 C:\Program Files\Java\jdk1.7.0_45\ 目录下。 下面设置环境变量: “我的电脑”右键菜单--->属性--->高级--->环境变量--->系统变量-新建.. 变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.7.0_45\ 变量名:CALSS_PATH 变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; 找到 path 变量名—>“编辑”添加: 变量名:PATH 变量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; 在 Windows 命令提示符下验证 Java 是否成功: cmd.exe …… C:\Users\fnngj>java 用法: java [-options] class [args...] (执行类) 或 java [-options] -jar jarfile [args...] (执行 jar 文件) 其中选项包括: 《Selenium2 Java 自动化测试实战(修正版)》 24 -d32 使用 32 位数据模型 (如果可用) -d64 使用 64 位数据模型 (如果可用) -server 选择 "server" VM -hotspot 是 "server" VM 的同义词 [已过时] 默认 VM 是 server. …… C:\Users\fnngj>javac 用法: javac 其中, 可能的选项包括: -g 生成所有调试信息 -g:none 不生成任何调试信息 -g:{lines,vars,source} 只生成某些调试信息 -nowarn 不生成任何警告 -verbose 输出有关编译器正在执行的操作的消息 -deprecation 输出使用已过时的 API 的源位置 -classpath <路径> 指定查找用户类文件和注释处理程序的位置 -cp <路径> 指定查找用户类文件和注释处理程序的位置 …… java 命令可以运行 class 文件字节码。 javac 命令可以将 Java 源文件编译为 class 字节码文件。 可能读者当前下载的 Java 版本与本书不同,但安装方法是一样的。 2.1.2 安装 Eclipse Eclipse:http://www.eclipse.org/downloads/ 开发 Java 者必然会用 Eclipse 工具,Eclipse 是做 Java 开发的不二之选,当然 Java 的 IDE 工具并非只 有 Eclipse,JBuilder 、IntelliJ IDEA 等都是开发 Java 非常优秀的 IDE。而 Eclipse 做为通用语言的 IDE,也 并非只能用于开发 Java 程序。只是因为这两者过于亲密,使我们看到其一会立刻想到另外一个,所以它们 二者是天生一对。 访问上面所提供的链接会看到如下图,选择“Eclipse IDE for Java Developers”进行下载。 《Selenium2 Java 自动化测试实战(修正版)》 25 图 2.2 下载 Eclipse 将下载的目录解压会得到一下 eclipse 目录,目录结构如下: 图 2.3 Eclipse 目录 双击 eclipse.exe 启动程序。如果是首次启动需要你指定 Java 的项目目录。或者你希望 Java 项目创建 于哪个目录下。 图 2.4 指定项目目录 如果是首次启动 Eclipse,因为还没有创建任何项目,默认会打开一个 Welcome 的页面。如下图: 《Selenium2 Java 自动化测试实战(修正版)》 26 图 2.5 首次启动 eclipse 界面 2.1.3 编写第一个 Java 程序 也许你并不是第一次接触 Java,“Hello Word”也写过很多遍,为了保持本书从基础开始的特点,所 有还带领读者写一个“Hello Word!”,有基础的同学直接跳过本节。 以打开的 Eclipse 为例,选择菜单栏 File--->New ---> Java Project 弹出如下窗口。 图 2.6 创建项目 《Selenium2 Java 自动化测试实战(修正版)》 27 在“Project name”选项中输入项目名称,我们这里输入为“mypor”。如果想看看下一步创建项目有 什么选项点击“Next”,想省事直接点击“Finish”创建项目完成。 也许你并没看到创建的项目,把“Welcome”页面关掉就好。 继续在项目上右键 New ---> Package 图 2.7 创建包 包(Package)的概念可以理解为程序的集合。 图 2.8 创建包 在“Name”选项中输入包名,我这里的命名为“com.mypro.jase”,为什么包的名字要取得像倒过来 的域名我也不太清楚,大家都习惯这么命名。 继续在包上右键 New ---> Class 图 2.9 创建类 其实,这个才是我们最终要编写 Java 程序的文件,为什么叫 Class 而不是 File 呢。这是因为 Java 是个 纯的面向对象的编程语言,所以一且皆对象,对象一定是属于某个类的,所以需要创建 class 文件。 《Selenium2 Java 自动化测试实战(修正版)》 28 图 2.10 创建类 在“Name”选项中输入类名,我这里输入的类名为“Hello”,Java 对类的命名一般要求首字母大写。 然后点击“Finish”按钮会创建 Hello.java 文件。 在 Hello.java 编写第一个 Java 程序。 Hello.java package com.mypro.jase; public class Hello { public static void main(String[] args){ System.out.println("hello world"); } } 输入完成,点击工具栏 Run 按钮运行,将会在控制台看到“hello word”的输入。好吧!这在 Python 中只要一行代码“print ‘hello word’”就可完成。如果你不理解这段代码中每个单词的作用和含义,那么你 需要找一本 Java 书从头学起。这不在本书讲解的范围。 2.1.4 安装 Selenium Selenium 这里就不再过多介绍,但其实我们有最终目的是要用 Java 去编写 Selenium 自动化测试脚本。 《Selenium2 Java 自动化测试实战(修正版)》 29 所以我们需要安装 Java 版的 Selenium 包。 下载手机最快报码现场直播,4887开奖现场结果:http://docs.seleniumhq.org/download/ 图 2.11 selenium 下载手机最快报码现场直播,4887开奖现场结果 如上图,点击 Download 进行下载,当然上面链接你可能无法访问,原因你懂的,所以你要具备科学 上网的技能。 这里再提供一下百度网盘下载手机最快报码现场直播,4887开奖现场结果:http://pan.baidu.com/s/1hq6mebE 下载完成 selenium-java-2.45.0.zip 包后,需要将其进行解压,得到如下目录。 图 2.12 selenium 解压目录 在创建的项目上右键 Build Path---->Add Libraries... 图 2.13 eclipse 导入 selenium 《Selenium2 Java 自动化测试实战(修正版)》 30 选择 User Library 选项,点击“Next”。 图 2.14 eclipse 导入 selenium 点击 User Libraries... 图 2.15 eclipse 导入 selenium 创建一个 Library 的目录,名字随便取。 《Selenium2 Java 自动化测试实战(修正版)》 31 图 2.16 eclipse 导入 selenium 选择解压的 selenium-java 目录,添加其下面的所有 jar 文件。(可以通过 Ctrl+a 一次选择一个目录下 的所有文件进行添加。)包括 libs 目录下的所有包也要添加噢! 图 2.17 eclipse 导入 selenium 导入 jar 包完成,如下图: 《Selenium2 Java 自动化测试实战(修正版)》 32 图 2.18 eclipse 导入 selenium 暂时先不要管这些 jar 包都是干嘛用的,先把他们都添加过来,以免报找不到某个类或方法的错误。 ^_^! 2.2 编写第一个自动化脚本 下面创建一个 baidu.java 类,方法与创建 Hello.java 相同,这里就再重复介绍。 Baidu.java package com.mypro.jase; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.*; public class Baidu { public static void main(String[] args){ System.out.println("srart selenium"); WebDriver driver = new FirefoxDriver(); driver.get("http://www.baidu.com/"); 《Selenium2 Java 自动化测试实战(修正版)》 33 driver.findElement(By.id("kw")).sendKeys("selenium java"); driver.findElement(By.id("su")).click(); driver.close(); } } 在敲写这段代码的时候,你心里一定充满了疑问,这段代码到底做了什么事情,下面就来逐行的解释 一下代码的含义。 import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.*; C 语言中叫:导入头文件,Python 中叫导入模组,一般的叫法为“导入包”,“导入类库”。不管叫 什么明白它是对类库的引用即可。因为我们要使用 Selenium(webdriver)所提供方法,所以需要把 Selenium (webdriver)所提供的类或方法导入。Java 语言中用 import...引入库类。 WebDriver driver = new FirefoxDriver(); 用 WebDriver new Firefox 浏览器的驱动给变量 driver,相当于 driver 拿到了 Firefox 浏览器的控制权。 driver.get("http://www.baidu.com/"); 获得浏览器对象后,就可以通过 get()方法向浏览器发送网址(URL)了。 driver.findElement(By.id("kw")).sendKeys("selenium java"); driver.findElement(By.id("su")).click(); 这两步其实是对百度页面的操作,首先通过元素属性 id=kw 找到百度输入框,并向输入框输入 “selenium java”。接着通过元素属性 id=su 找到百度一下搜索按钮,并对按钮进行点击操作。关于元素的 定位与操作,将会在本书第 4 章中详细介绍。 driver.close(); 退出并关闭浏览器驱动程序。 《Selenium2 Java 自动化测试实战(修正版)》 34 图 2.19 自动化脚本启动浏览器 当 Fiefox 浏览器没有默认安装到 C 盘,那么有可以在启动浏览时提示: Exception in thread "main" org.openqa.selenium.WebDriverException: Cannot find firefox binary in PATH. Make sure firefox is installed. OS appears to be: VISTA 这个时候可以使用 System 的 setProperty()方法指定浏览器的路径,用法如下。 …… System.setProperty("webdriver.firefox.bin","D:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"); WebDriver driver = new FirefoxDriver(); …… 2.3 安装浏览器驱动 WebDriver 支持 Firefox (FirefoxDriver)、IE(InternetExplorerDriver)、Opera (OperaDriver) 和 Chrome (ChromeDriver)。对 Safari 的支持由于技术限制在本版本中未包含,但是可以使用 SeleneseCommandExecutor 模拟。它还支持 Android (AndroidDriver)和 iPhone (IPhoneDriver) 的移动应用测试。除此之外它还包括一个 基于 HtmlUnit 的无界面实现,相关驱动为 HtmlUnitDriver。 各个浏览器驱动下载手机最快报码现场直播,4887开奖现场结果: http://www.seleniumhq.org/download/ 百度网盘下载手机最快报码现场直播,4887开奖现场结果: http://pan.baidu.com/s/1jG4Mfzg 安装 Chrome 浏览器驱动,下载 ChromeDriver_win32.zip(根据自己系统下载不同的版本驱动),解压得 到 chromedriver.exe 文件放到系统环境变量 Path 下面。 《Selenium2 Java 自动化测试实战(修正版)》 35 安装 IE 浏览器驱动,下载 IEDriverServer_Win32_x.xx.zip,将解压得到 IEDriverServer.exe,同样放置到 系统环境变量 path 目录下。 在 Liunx 系统下,同样下载系统对应的浏览器驱动,并将浏览器驱动放置到环境变量 Path 所设置的 路径下,不同的 Linux 环境变量的设置也会有所区别,这里不再详细介绍。 安装完成后可以用 IE 和 chrome 来替换 firefox 运行上面的例子。 import org.openqa.selenium.firefox.*; .... WebDriver driver = new ChromeDriver(); .... 替换为: import org.openqa.selenium.chrome.*; .... WebDriver driver = new ChromeDriver(); .... 或 import org.openqa.selenium.ie.*; .... WebDriver driver = new InternetExplorerDriver(); .... 如果程序能调用相应的浏览器运行,说明我们的浏览器驱动安装成功。 2.4 不同编程语言下使用 WebDriver W3C(万维网联盟)对 WebDriver 对做定义和规范。 http://www.w3.org/TR/webdriver/ WebDriver 是一个远程控制界面,支持反省和用户代理的控制权。它提供了一个独立于系统平台和编程语言 的线协议(wire protocol)作为一种远程进程程序指示 web 浏览器的行为。 该 WebDriver API 通过通讯协议和一组接口来发现页面上的 DOM 元素中定义的操作,包括控制浏览器的行 为。 我们可以这样来理解,例如,国标标准定义插板和插头的生产标准。那么所有的电器厂商生产的插头与所 《Selenium2 Java 自动化测试实战(修正版)》 36 有插板厂商生产的插板都按照这套标准来设计与生产。所以,我们拿到任何一个合格的插头和插板都可以匹配 得上。 WebDriver 可以理解成对操作浏览器和页面元素的一套“国标”。那么不同的编程语言都可以按照这套标准 实现自己的语言的 WebDriver 库。 下面展示在不同编程语言下使用 WebDriver 实现百度搜索的例子。 在 C#中引入 Selenium WebDriver 实现自动化测试: baidu.cs //添加 Selenium(webdriver)的引用 using OpenQA.Selenium; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.Support.UI; namespace SeleniumTests { class Baidu { static void Main(string[] args) { driver = new FirefoxDriver(); url = "http://www.baidu.com/"; driver.Navigate().GoToUrl(/pdf/url/index.html) var searchBox = driver.FindElementById("kw"); searchBox.SendKeys("Selenium"); ar btnClick = driver.FindElementById("su"); btnClick.Click(); driver.Quit(); } } } 在 Ruby 中引入 Selenium WebDriver 实现自动化测试: baidu.rb #导入 Selenium(webdriver)包 require 'Selenium-webdriver' driver = Selenium::WebDriver.for:chrome driver.get "http://www.baidu.com" 《Selenium2 Java 自动化测试实战(修正版)》 37 driver.find_element(:id, 'kw').send_keys "Hello WebDriver!" driver.find_element(:id, 'su').click driver.quit 在 Python 中引入 Selenium WebDriver 实现自动化测试: baidu.py #coding=utf-8 from selenium import webdriver browser = webdriver.Firefox() browser.get("http://www.baidu.com") browser.find_element_by_id("kw").send_keys("selenium") browser.find_element_by_id("su").click() browser.quit() 在不同的编程语言中会有语法的差异,我们抛去语法的差异性,在不同的语言中实现百度搜索的自动化实 例都完成了下面几个操作。 (1)首先导入 Selenium(webdriver)相关模块。 (2)调用 Selenium 的浏览器驱动,获取浏览器句柄(driver)并启动浏览器。 (3)通过句柄访问百度 URL。 (4)通过句柄操作页面元素(百度输入框和按钮)。 (5)通过句柄关闭浏览器。 所以,WebDriver 支持多种编程语言,再确切的可以看作是多种语言都支持 WebDriver,唯一的不同 在于不同语言实现的类与方法名的命名差异性。当然,这样做的好处不言而喻,每个人可以根据自己熟悉 的语言来使用 WebDriver 编写自动化测试脚本。 《Selenium2 Java 自动化测试实战(修正版)》 38 第3章 Java编程基础 虽然本书是以自动化测试技术为主线的教程,但本书中所涉及到的所有代码都是由 Java 语言去实现 的,所以,我们需要花点时间来学习和使用 Java 语言,需要说明的是,本章默认你具备了一定编程的基础, 我不会花费时间来告诉你什么是常量、变量,什么是运算符等基础的概念;你可以找一本 Java 基础教程或 一套 Java 视频教程来学习这些知识。 当然,Java 语言作为当下最流行的编程语言之一,网络上有着极其丰富的资料可以供你学习。你需要 做的就是付出一些时间来学习使用它。如果你已经完全掌握了 Java 的使用,那么本章你可以直接跳过。 我们在上一章中已经介绍了 Eecipse 的安装与基本使用,那么本章中的所有练习也将会在这个 IDE 下 完成。 3.1 输出与输入 在上一章中我们已经通过 Java 打印了“Hello World!”,这一节将会学到更多关于打印的知识。 3.1.1 输出 Java 提供 print()方法来打印信息,下面打开 Eclipse 来打印一些信息。 PrintTest.java package com.java.base; public class PrintTest { public static void main(String[] args){ String name = "张三"; int age = 26; System.out.print("name:" +name+"; age:"+age); System.out.printf("name: %s ; age: %d" ,name ,age); } } 输出结果: ----------- name:张三; age:26 name: 张三 ; age: 26 Java 是一个强类型的语言,定义的变量一定要声明它是什么类型(String 或 int )。其实上面的例 子是将字符串与变量之间用“+”进行了拼接,这用法将非常有用。 为什么经常看到别人用println()而不是print()方法?其实它们的区分在于println()在输出的结尾 《Selenium2 Java 自动化测试实战(修正版)》 39 为加一个换行。为方便,一般都习惯用 println()方法。而 printf()函数是格式化输出函数, 一般用于向 标准输出设备按规定格式输出信息。 3.1.2 输入 用户与程序最简单的交互方式就是输入,程序对输入内容进行处理,并输出处理结果。 当在文字模式下要输入数据到程序中时,你可以使用标准输入流对象 System.in,然而我们很少直接 使用它,因为 System.in 对象所提供的 read()方法,是从输入串流取得一个字节的数据,并传回该字节的 整数值。 在文字模式下的输入是以字符的方式传送给程序,所以直接使用 read()方法取得的是字符的 ASCII 编 码整数,通常要取得的使用者输入会是一个字符串,或是一组数字,所以 System.in 对象的 read()方法一 次只读入一个字节数据的方式并不适用。 在 J2SE 5.0 以上版本中,你可以使用 java.util.Scanner 取得用户的输入。 InputTest.java package com.java.base; import java.util.Scanner; public class InputTest { private static Scanner input; public static void main(String[] args){ input = new Scanner(System.in); System.out.print("你刚才输入了:"+input.nextLine()); } } 输出结果: ----------- hello world 你刚才输入了:hello world 运行上面的一段程序,在 console 输入一行字符串-回车,然后将看到打印结果。 《Selenium2 Java 自动化测试实战(修正版)》 40 图 3.1 Console 输入 其实,这里牵扯到了 Java 中的另一个更重要的概念“new”。在 java 中,new 用来开辟堆内存,又叫 初始化,一般情况下,对象创建好后,都需要用 new 进行实例化。这里先不过多解释,等学到 Java 的类 时再来理解“new”的作用。 3.1.3 单、双引号 在 Java 当中,区分单引号('')与双引号(""),单引号表示一个字符、双引表示一个字符串。 PrintTest.java package com.java.base; public class PrintTest { public static void main(String[] args){ String name = "隔壁老王"; char sex = '男'; System.out.println("name:" +name+"; sex:"+sex); } } 字符与字符串的类型声明也不一样,字符用 char 类型声明;而字符串用 String 类型声明。 3.2 分支与循环 结构化程序实质上是由有限个顺序、分支和循环三种基本结构排列、 嵌套而成。下面来学习 Java 如何实 现分支与循环。 3.2.1 if 语句 来个写个无聊有 if...else...语句: 《Selenium2 Java 自动化测试实战(修正版)》 41 IfTest.java package com.java.base; public class IfTest { public static void main(String[] args){ int a=1,b=2; if (a>b){ System.out.printf("%d big", a); }else{ System.out.printf("%d big", b); } } } 如果 a 大于 b 打印 a,否则打印 b。果然很无聊,那么下面练习一个不那么无聊的例子,多分支语句。 IfTest.py package com.java.base; public class IfTest { public static void main(String[] args){ int result=61; if(result>=90){System.out.println("优秀");} else if(result>=70){System.out.println("良好");} else if(result>=60){System.out.println("及格");} else {System.out.println("不极格");} } } 根据分数把学生成绩划分为四个级别“优秀”、“良好”、“及格”、“不及格”,那么 61 分属于 哪个级别,练习一下吧。 《Selenium2 Java 自动化测试实战(修正版)》 42 3.2.2 for 语句 循环从 1 到 10,并且打印这 10 个数。 ForTest.java package com.java.base; public class ForTest { public static void main(String[] args){ for (int i=1;i<=10;i++){ System.out.println(i); } } } 打印结果: >>> 1 2 3 4 5 6 7 8 9 10 有时候我们希望每次循环的步长不为 1,那么可以修改 i 的步长。 ForTest.java package com.java.base; public class ForTest { public static void main(String[] args){ for (int i=1;i<=10;i=i+2){ System.out.println(i); } } 《Selenium2 Java 自动化测试实战(修正版)》 43 } 打印结果: >>> ================================ RESTART ================================ >>> 1 3 5 7 9 或者来个复杂一些的循环嵌套,来打印一个由星号“*”组成的三角形。 ForTest.java package com.java.base; public class ForTest { public static void main(String[] args){ for(int i=1;i<=5;i++){ for(int j=5-i;j>0;j--){ System.out.print(""); } for(int k=1;k<=2*i-1;k++){ System.out.print("*"); } System.out.println(""); } } } 打印结果: >>> * *** ***** ******* ********* 《Selenium2 Java 自动化测试实战(修正版)》 44 3.3 数组与字典 数组与字典是非常重要的两种用于存放数据的形式。所以需要学习和掌握这两种数据类型。 3.3.1 数组 数组实质上是一组相同类型的数据的集合。 ListTest.java package com.java.base; public class ListTest { public static void main(String[] args){ int[] data = new int[5] ; for(int i = 0 ; i < 5 ; i++) { data[i] = i ; System.out.println(data[i]); } } } 在创建数组的时候需要为其分配空间大小,在本例子中,通过循环将 0~4 之间的 5 个数放到的数组 data[]中。 当然,有时候我们想往数组里放字符串,而不是数字,那么可以通过下面的方式。 ListTest.java package com.java.base; public class ListTest { public static void main(String[] args){ String[] str = new String[5]; str[0] = "小明"; str[1] = "老师"; str[2] = "老王"; str[3] = "张三"; str[4] = "李四"; for(int i=0;i<5;i++){ System.out.println(str[i]); 《Selenium2 Java 自动化测试实战(修正版)》 45 } } } 同样通过一个 for 循环将数组中的内容打印输出。 其实,直接为定义的数组分配元素的方式更为简便。实现代码如下: ListTest.java package com.java.base; public class ListTest { public static void main(String[] args){ String[] fruits = {"bananas","apples","pears","oranges"}; for(int i=0;i hm = new HashMap(); //添加字典 《Selenium2 Java 自动化测试实战(修正版)》 46 hm.put("username","password"); hm.put("Jim","1155689"); hm.put("Jane","1255669"); hm.put("Kevin","1165669"); //测试 key 是否包含 username,返回值为 ture/false System.out.println(hm.containsKey("username")); System.out.println("===================>"); //获取 key 所对应的 vlaue System.out.println(hm.get("Jim")); System.out.println("===================>"); //获取整个字典数据 System.out.println(hm.entrySet()); System.out.println("===================>"); //循环打印每一对 key=value Iterator it=hm.entrySet().iterator(); while(it.hasNext()) { System.out.println(it.next()); } System.out.println("===================>"); //分别获取 key 的值,和 value 的值。 Iterator it2 = hm.keySet().iterator(); while(it2.hasNext()) { //获得字典的 key(username) String username = (String)it2.next(); System.out.println(username); //获得字典的 value(节点) String password = hm.get(username); System.out.println(password); } } } 打印结果: >>> true ===================> 1155689 ===================> 《Selenium2 Java 自动化测试实战(修正版)》 47 [Kevin=1165669, Jane=1255669, username=password, Jim=1155689] ===================> Kevin=1165669 Jane=1255669 username=password Jim=1155689 ===================> Kevin 1165669 Jane 1255669 username password Jim 1155689 3.4 类与对象 在 Java 语言中经常被提到的两个词就是类与对象。实质上可以把类看作是对象的载体,它定义了对 象所具有的功能。对象是类的一个具体的实例。如果把“电脑”看作一个类的话,那作者面前的这台笔记 本电脑就是一个具体对象。 3.4.1 类的主方法 主方法是类的入口点,它定义了程序从何处开始;Java 编译器通过 main()方法来执行程序。 xx.java …… public static void main(String[] args){ //方法体 } …… 从主方法的定义可以看到主方法具有以下特性:  主方法是静态的。  主方法没有返回值。  主方法的形参为数组。 《Selenium2 Java 自动化测试实战(修正版)》 48 3.4.2 成员变量 在 Java 语言中对象的属性称为成员变量,也可以称为属性。 classTest.java package com.java.base; public class classTest { private static int id; private static String name; private static String author; public static void main(String[] args){ id = 1001; name = "selenium2 java 自动化测试实战"; author = "虫师"; System.out.println("书号:"+id+";书名:"+name+";作者:"+author); } } 3.4.3 方法 方法就是类下面实现具体功能的一个整体。 funcTest.java package com.java.base; public class funTest { public static void start(){ System.out.println("start=======>"); } public static void end(){ System.out.println("end=======>"); } public static void main(String[] args){ //调用 start 方法 start(); 《Selenium2 Java 自动化测试实战(修正版)》 49 System.out.println("run----->"); //调用 end 方法 end(); } } 运行结果: >>> start=======> run-----> end=======> 当然,我们可以为方法设置入参和返回值。 funTest.java package com.java.base; public class funTest { public static int add(int a,int b){ return a+b; } public static void main(String[] args){ int resule = add(4,7); System.out.println(resule); } } 运行结果: >>> 11 3.4.4 new 关键字 这也是 Java 中非常特色的一个概念。New 到底是什么?为什么要 new? 《Selenium2 Java 自动化测试实战(修正版)》 50 使用 new 关键字实际上做了三件事情: 1. 与堆栈(栈)处分配一个存储空间保存引用(固定的指针)。 2. 与堆区分配一片内存空间保存相应类的对象(引用数据类型的对象,如:数组、对象等)。 3. 将堆区对象的首手机最快报码现场直播,4887开奖现场结果赋予栈区引用。 newTest.java package com.java.base; class Count{ public int add(int a,int b){ int c; c = a + b; return c; }; } public class newTest{ public static void main(String[] args){ //使用 count 这个类,必须先 new Count j = new Count(); //不 new 是无法调用到 Count 类的 add()方法的。 System.out.println(j.add(2,5)); } } 3.4.5 类的继承 Java 中用 extends 关键字来做类的继承。 创建 A 类,实现 add()方法做整数加法运算。 A.java package com.java.base; public class A{ public int add(int a,int b){ return a+b; } } 《Selenium2 Java 自动化测试实战(修正版)》 51 创建 B 类,继承 A 类,并实现 sub()方法做整数减法运算。 B.java package com.java.base; public class B extends A{ public static int sub(int a,int b){ return a-b; } } 继续创建 C 类,调用 B 类中继承的 A 类的 add()方法。 C.java package com.java.base; public class C{ public static void main(String[] args){ //实例化 B 类一个对象 j B j = new B(); //虽然 B 类中没有 add()方法,B 类继承了 A 类,A 类有 add()方法。 int resul = j.add(5, 9); System.out.println(resul); } } 3.5 import 和 package Python 语言中叫引入模组或模块,在 C/C++语言中叫“头文件”,在 Java 中叫导入支持类。 3.5.1 package 其实,package 名称就像是我们的姓,而 class 名称就像是我们的名字。package 名称有很多点号 “.”,就好像是复姓。比如说 java.lang.String,就是复姓 java.lang,名字为 String 的类别。 Java 会使用 package 这种机制的原因也非常明显,就像我们取姓名一样,光是一间学校的同一届同 《Selenium2 Java 自动化测试实战(修正版)》 52 学中,就有可能会出现不少同名的同学,如果不取姓的话,那学校在处理学生资料,或是同学彼此之间的 称呼,就会发生很大的困扰。幸运的是,Java 的套件名称我们可以自己取,不像人的姓没有太大的选择, 如果依照 Sun 的规范来取套件名称,那理论上不同人所取的套件名称不会相同 ( 请参阅 "命名惯例" 的相关文章 ),也就不会发生名称冲突的情况。 如,我们可以用下面的方法使用 Selenium 的相关包。 selTest.java package testpackage; public class selTest { public static void main(String[] args){ org.openqa.selenium.WebDriver driver = new org.openqa.selenium.chrome.ChromeDriver(); } } 3.5.2 import 显然上面的例子使编程变得很麻烦,我想使用某个类或方法,就不得写又臭又长的“复姓”。于是, Sun 想到了一个方法用 import 来优雅的解决这个问题。 这个 import 就是在程式一开头的时候,先说明程式中会用到那些类别的简称,也就是只称呼名字, 不称呼他的姓。姓在程序开头声明。 selTest.java package testpackage; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class selTest { public static void main(String[] args){ WebDriver driver = new ChromeDriver(); } 《Selenium2 Java 自动化测试实战(修正版)》 53 } 3.6 异常 在程序的开发过程中,可能存在各种错误,有些错误是可以避免的,而有些错误却是意想不到的,在 Java 中把这些可能发生的错误称为异常。 在 Java 中可以捕捉的异常(即 Exception 类的子类)分为可控式异常和运行时异常两种类型。 3.6.1 可控式异常 在 Java 中把那些可以预知的错误,例如从文件中读取数据、对数据库进行操作等,在程序编译时就 能对程序中可能存在的错误进行处理,并给出具体的错误信息,我们把这些错误称为可控式异常。 常用可控式异常及说明: 异常 描述 IOException 当发生某种 I/O 异常时,抛出此异常 SQLException 提供关于数据库访问错误或其它错误信息的异常 ClassNotFoundException 类没有找到异常 NoSuchFieldException 类不包含指定名称的字段时产生的信号 NoSuchMethodException 无法找到某一特定方法时,抛出该异常 TryTest.java package com.java.base; public class TryTest { public static void main(String[] args) { try{ Class.forName("com.Test"); }catch(ClassNotFoundException e){ e.printStackTrace(); } } } 打印结果: 《Selenium2 Java 自动化测试实战(修正版)》 54 >>> java.lang.ClassNotFoundException: com.Test at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at com.java.base.TryTest.main(TryTest.java:8) 由于在 main()方法中加载 com 包中的 Test 类时,Java 的虚拟机没有找到 Test 类,从而引发了 ClassNotFoundException 异常。 3.6.2 运行时异常 在 Java 中有些错误是不能被编译器检测到的,例如,在进行除法运算时,除数为零;试图把一个不是 由数字组成的字符串使用 Integer 类的 parseInt()方法转换为整数等。Java 的编译器是检测不到这些错误的, 因而能够正常编译,但是在运行时就会发生异常,我们把这些异常称为运行时异常。 常用到的运行时异常及说明: 异常 描述 IndexOutOfBoundsExceptin 指示某集合或数组的索引值超出范围时抛出该异常 NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 ArithmeticException 当出现异常的运算条件时,抛出此异常 IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数 ClassCastException 当试图将对象强制转换为不是实例的子类时,抛出该异常 TryTest02.java package com.java.base; public class TryTest02 { int[] number = {100,80,50,70,20,60}; public void setNum(int index,int value){ number [index] = value; } 《Selenium2 Java 自动化测试实战(修正版)》 55 public int getNum(int index){ return number[index]; } public static void main(String[] args){ TryTest02 ex = new TryTest02(); int value = ex.getNum(0); System.out.println(value); value = ex.getNum(6); System.out.println(value); value = ex.getNum(5); System.out.println(value); } } 打印结果: >>> 100 60 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6 at com.java.base.TryTest02.getNum(TryTest02.java:12) at com.java.base.TryTest02.main(TryTest02.java:25) 从输出结果可以看出,程序发生了 ArrayIndexOutOfBoundsException 异 常 , 该 异 常 是 IndexOutOfBoundsException 异常的子异常。当程序执行到语句“value = ex.getNum(6);”时发生了 异常,因为数组下标是从 0 开始的,所以找不到第 7 个元素。从而引发了错误,导致下面的语句没有被执 行。 3.6.3 获取异常信息 在 Java 中 java.lang.Throwable 类是所有异常类的超类,该类提供了获得异常信息的方法。 获取异常信息的方法及说明: 方法 说明 String getLocalizedMessage() 获得此 Throwable 的本地化描述 String getMessage() 获得些 Throwable 的详细消息字符串 《Selenium2 Java 自动化测试实战(修正版)》 56 void printStackTrace() 将些 Throwable 及其栈踪迹输出至标准错误流 String toString() 获得些 Throwable 的简短描述 TryTest03.java package com.java.base; public class TryTest03 { public void printBugInfo(){ try{ int x = 100; int y = 0; int z = x/y; System.out.println(x+"乘以"+y+"的商是:"+z); }catch(Exception ex){ //输出异常到标准错误流 ex.printStackTrace(); //使用 getMessage()方法输出异常信息 System.out.println("getMessage 方法:"+ex.getMessage()); //使用 getLocalizedMessage()方法输出异常信息 System.out.println("getLocalizedMessage 方法: "+ex.getLocalizedMessage()); //使用 toString()方法输出异常信息 System.out.println("toString 方法:"+ex.toString()); } } public static void main(String[] args){ TryTest03 ex = new TryTest03(); ex.printBugInfo(); } } 打印结果: >>> java.lang.ArithmeticException:/ by zero 《Selenium2 Java 自动化测试实战(修正版)》 57 getMessage 方法:/ by zero getLocalizedMessage 方法:/ by zero toString 方法:java.lang.ArithmeticException:/ by zero at com.java.base.TryTest03.printBugInfo(TryTest03.java:9) at com.java.base.TryTest03.main(TryTest03.java:32) 3.6.4 异常处理 在 Java 语言中程序发生异常时,有三种处理异常方式。 try...catch... try...catch...finally... try...finally... TryType.java …… try{ //需要进行异常捕捉的语句 }catch(Exception ex){ //对异常进行处理的语句 }finally{ //不管是否异常都会被执行的语句 } …… 《Selenium2 Java 自动化测试实战(修正版)》 58 第4章 WebDriver API 从本章正式开始学习 Selenium ,对于本章标题的命名比较纠结,要想起一个确切的符合主题的名字 并不太容易。WebDriver 属于 Selenium 体系中设计出来操作浏览器的一套 API,它支持多种编程语言,这 个我们前面已经介绍过。那么站在编程语言的角度来看,Selenium WebDriver 只是 Java 的一个第三方框架, 和 Spring web 开发框架属于同一性质,只是 Spring 只在 Java 语言中存在,其它语言也有用于 web 开发框 架,但不叫 Spring。而 Selenium WebDriver 框架针对不同语言分别开发了该框架,所以,在不同的编程语 言里它都叫 Selenium WebDriver。那么本章,我们将详细介绍这个框架所提供的操作 web 页面的各种常用 方法。 4.1 从定位元素开始 在本章学习开始之前,我们先来看一张 Web 页面,如图 4.1 所示。 这其实就是百度的首页,在这张页面上有输入框、按钮和文字链接,当然还有图片,页面底部有的文字, 以及左侧的下拉框等。自动化要做的就是模拟鼠标和键盘来操作这些元素,或单击,或输入,或鼠标悬停等。 那操作这些元素的前提是需要找到它们,自动化工具无法像测试人员一样可以通过肉眼来分辨页面上的元 素,并且知道是它们是做什么用的,那么如何找到它们呢?下面来看看这些元素的真实面目。 图 4.1 Web 页面 《Selenium2 Java 自动化测试实战(修正版)》 59 图 4.2 通过 FireBug 查看页面元素 图 4.2,通过前端工具,我们看可以看到,页面上的元素都是由一行行的代码组成的,它们之间有层级地组 织起来,每个元素有不同的标签名和属性值。WebDriver 就是通过这信息来找到不同的元素的。 WebDriver 提供了八种元素定位方法:  id  name  class name  tag name  link text  partial link text  xpath  css selector 在 Java 语言中对应的定位方法如下: import org.openqa.selenium.By; ... findElement(By.id()) findElement(By.name()) findElement(By.className()) findElement(By.tagName()) findElement(By.linkText()) findElement(By.partialLinkText()) findElement(By.xpath()) findElement(By.cssSelector()) 下面我们就逐一来介绍这些定位方法的使用。在此之前,我们复制百度首页的前端代码,并以此为例 来讲解定位页面上元素的定位方法。 baidu.html 《Selenium2 Java 自动化测试实战(修正版)》 60

checkbox

这里手动创建一个 checkbox.html 页面,为了使页面更美观,在代码中添加了 bootstrap 样式的引用。用浏 览器打开后,效果如图 4.10 所示。 图 4.10 复选框 下面就通过例子来操作页面上的这一组复选框。 《Selenium2 Java 自动化测试实战(修正版)》 85 selements.java package com.mypro.jase; import java.io.File; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class elements { public static void main(String[] args) throws InterruptedException { WebDriver driver = new ChromeDriver(); File file = new File("E:/jase/checkbox.html"); String filePath = file.getAbsolutePath(); driver.get(filePath); List inputs = driver.findElements(By.tagName("input")); for(WebElement checkbox : inputs){ String type = new String(checkbox.getAttribute("type")); if (type.equals("checkbox")){ checkbox.click(); Thread.sleep(2000); } } driver.quit(); } } 前面提到,通过 tag name 的定位方式很难定位到单个元素,因为元素标签名重复的概率很高。那么在定位 一组元素时,这种方式就派上用场了。在上面的例子中先通过 findElements(By.className())找到一组标签名为 input 的元素。然后通过 for 循环进行遍历,在遍历过程中,通过 getAttribute()方法获取元素的 type 属性是否为 “checkbox”,如果为“checkbox”,那么就认为这个元素是一个复选框,对其进行勾选操作。 需要注意的是,在上面的例子中,通过浏览器打开的是一个本地的 html 文件,所以需要用到 Java 的 File() 方法本地路径下的文件。 除此之外,我们还可以使用 XPath 或 CSS 来直接判断属性值,从而进行单击操作。 selements.java package com.mypro.jase; import java.io.File; 《Selenium2 Java 自动化测试实战(修正版)》 86 import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; public class elements { public static void main(String[] args) throws InterruptedException { WebDriver driver = new ChromeDriver(); File file = new File("E:/jase/checkbox.html"); String filePath = file.getAbsolutePath(); driver.get(filePath); //通过 css 找到一组元素 //List checkboxes = driver.findElements(By.cssSelector("input[type=checkbox]")); //通过 xpath 找到一组元素 List checkboxes = driver.findElements(By.xpath("//input[@type='checkbox']")); for(WebElement checkbox : checkboxes){ checkbox.click(); } Thread.sleep(3000); //刷新 driver.navigate().refresh(); //把页面上最后 1 个 checkbox 的勾给去掉 List allCheckboxes = driver.findElements(By.cssSelector("input[type=checkbox]")); System.out.println(allCheckboxes.size()); allCheckboxes.get(allCheckboxes.size() - 1).click(); Thread.sleep(5000); driver.quit(); } } 通过 XPath 或 CSS 来查找一组元素时,省去了判断步骤。因为定位方法已经做了判断,只需循环对这一组 《Selenium2 Java 自动化测试实战(修正版)》 87 元素进行勾选即可。 除此之外例子中还用到了其它有趣的方法。 driver.navigate().refresh(); 这个方法用于刷新页面。 allCheckboxes.size() size()方法可以计算获得元素的个数。这里获得的结果为 3。3 减 1 为 2。 allCheckboxes.get().click() get()指定得到元素组中的第几个元素,并对其时行 click()操作。 4.9 多表单切换 在 Web 应用中经常会遇到 frame/iframe 表单嵌套页面的应用,WebDriver 只能在一个页面上对元素识别与 定位,对于 frame/iframe 表单内嵌页面上的元素无法直接定位。这时就需要通过 switchTo().frame()方法将当前定 位的主体切换为 frame/iframe 表单的内嵌页面中。 frame.html

frame

在上面的 html 代码中,通过 iframe 表单嵌入一个百度页面,用浏览器打开后如图 4.11 所示。 《Selenium2 Java 自动化测试实战(修正版)》 88 图 4.11 iframe 嵌入百度首页 这个时候直接定位页面上的百度的输入框一定会报找不到元素的错误,因此可以使 用 switchTo().frame()先找到 frame.html 中的