机器人框架测试自动化-全-

机器人框架测试自动化(全)

原文:zh.annas-archive.org/md5/d8b8c3d4466ab9b01ee259d2be645f18

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

测试对于任何活动的成功至关重要;这一点同样适用于软件。它不仅涵盖验证,还包括软件的验证。常用的测试实践包括单元测试和功能测试,这些测试验证所需的功能。然而,测试人员或利益相关者的手动努力是必要的,以确保正在测试的软件按预期工作,这是软件验收过程的一部分。

随着软件在规模和数量上的逐年增长,验收测试过程已经实现自动化,留下了大量以测试审计跟踪形式的信息,这些信息需要立即提供给用户,否则接受测试自动化的目的就会落空。

Robot 框架提供了这个缺失的环节,它集成了用于对软件或“测试系统”进行验收测试的测试工具,并将这种执行结构化为按适当层次排列的离散测试结构;这不仅实现了预期的执行方式,还生成了有序的报告。

作为开源框架,这个工具不仅允许您以层次结构执行接受测试并生成自动化报告,还允许您对其进行自定义,创建自己的工具,甚至将其与其他工具一起使用,作为为团队所需的定制测试环境设置的一部分。

本书涵盖的内容

第一章,使用 Robot Framework 入门,解释了接受测试驱动开发的需求,提供了一个高级概述,并介绍了安装 Robot Framework 工具的不同方法。它还讨论了用户与框架交互的各种命令,并向用户演示了简单测试项目的创建和执行。

第二章,配置测试项目,解释了测试层次结构,并涵盖了框架中使用的不同文件和表格,以及编写测试文件的不同语法选项。它解释了常用的测试实践,并说明了如何在测试中重用信息。

第三章,进一步测试定制,涵盖了测试重用、连接到外部数据源和测试模板,以及用户定义的关键字。它还提供了不同的测试编写风格,并与一些其他著名的行为驱动测试工具进行了比较。

第四章,扩展框架,展示了现实世界的测试挑战,并提供了使用各种内置和外部库来解决这些挑战的实际方法。它涵盖了基于 Web 和桌面测试,包括面向对象和基于图像的测试。在没有兼容的测试库的情况下,它还展示了创建和集成自定义编写的库。

第五章,生成报告,详细介绍了工具的生成输出,并提供了不同的方法来自定义报告以及通过内置和自定义机制生成的日志。它还鼓励用户利用源代码在现有框架中创建自定义的报表机制。

你需要这本书的内容

为了使用 Robot Framework,您首先需要安装 Python(示例已在 2.7 版本上测试过,但您可以使用 Python 2.7 或更高版本中的任何版本),如果您使用的是流行的 Linux 发行版或 Mac OS X 作为操作系统,它可能已经安装。除了 Python 之外,您还可以安装 Jython 和 IronPython,它们可以用于在 JDK 或.NET Framework 运行时上运行基于 Python 的应用程序和工具,如 Robot Framework。一些示例确实需要显式使用 Jython,但其余的可用环境可以使用任何基于 Python 的运行时。为了安装第三方工具或便于安装,建议使用 easy_install Python 模块。在必要时,提供与 Robot Framework 测试一起需要的工具/框架的安装。

这本书面向的对象

由于这本书专注于测试工具,它主要面向测试人员。然而,鉴于创建内部灵活测试工具的需求,还需要动手进行 Python 开发以修改和开发一个适合个人需求的测试框架。类似于 DevOps 运动,今天的开发者正在寻求超越测试和行为驱动开发的方法,测试人员也需要通过自动化手段提高生产率。在这本书中,您将需要在各种情况下扮演开发者和测试者的角色,以便从两个角度了解这个工具的工作原理。

惯例

在这本书中,您将找到许多不同风格的文本,以区分不同类型的信息。以下是一些这些风格的示例及其含义的解释。

文本中的代码词如下所示:"我们可以通过使用include指令来包含其他上下文。"

代码块如下设置:

# This code block runs 5 times for values of x between 11 and 15
|  | :FOR | ${x} | IN RANGE | 11 | 16 | 
# This code block runs 5 times for x = 10, 12, 14, 16,18
|  | :FOR | ${x} | IN RANGE | 10  |  20 |  2  |
|  |      |  Log  |  ${x} |

当我们希望您注意代码块中的特定部分时,相关的行或项目将以粗体显示:

           '<div id="top-right-header">' + 
             '<div id="report-or-log-link"><a href="#"></a></div>' + 
 '<div id="my_custom_image"><img src="img/github-icon.jpg" /></div>'+ 
           '</div>', { 
        generated: window.output.generatedTimestamp, 

任何命令行输入或输出都如下所示:

pybot --randomize tests all_tests

新术语重要词汇将以粗体显示。您在屏幕上看到的词汇,例如在菜单或对话框中,将以这种方式显示:“在指定失败选项后,用户将要求输入失败信息,然后再进行测试。”

注意

警告或重要提示将以这样的框显示。

小贴士

小技巧和窍门将像这样显示。

读者反馈

我们始终欢迎读者的反馈。请告诉我们您对这本书的看法——您喜欢什么或可能不喜欢什么。读者的反馈对我们开发您真正能从中获得最大收益的标题非常重要。

要向我们发送一般反馈,只需发送电子邮件到<feedback@packtpub.com>,并在邮件主题中提及书籍标题。

如果您在某个主题上具有专业知识,并且您对撰写或为书籍做出贡献感兴趣,请参阅我们的作者指南www.packtpub.com/authors

客户支持

现在,您已经成为 Packt 书籍的骄傲拥有者,我们有一些事情可以帮助您从您的购买中获得最大收益。

下载示例代码

您可以从您在www.packtpub.com的账户下载您购买的所有 Packt 书籍的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给您。

所有章节的代码文件也存在于 GitHub 上github.com/SumitBisht/RobotFrameworkTestAutomation,您可以下载、分叉和修改,并可以在此处发送任何建议或更正。

错误清单

尽管我们已经尽最大努力确保内容的准确性,但错误仍然可能发生。如果您在我们的书中发现错误——可能是文本或代码中的错误——如果您能向我们报告这一点,我们将不胜感激。通过这样做,您可以避免其他读者的挫败感,并帮助我们改进本书的后续版本。如果您发现任何错误清单,请通过访问www.packtpub.com/support,选择您的书籍,点击错误提交表单链接,并输入您的错误详细信息来报告它们。一旦您的错误得到验证,您的提交将被接受,错误将被上传到我们的网站,或添加到该标题的错误清单部分。

侵权

在互联网上侵犯版权材料是一个跨所有媒体持续存在的问题。在 Packt,我们非常重视我们版权和许可证的保护。如果您在互联网上发现我们作品的任何非法副本,无论形式如何,请立即提供位置地址或网站名称,以便我们可以追究补救措施。

请通过 <copyright@packtpub.com> 联系我们,并提供涉嫌盗版材料的链接。

我们感谢您在保护我们作者以及为我们提供有价值内容方面的帮助。

问题

如果你在本书的任何方面遇到问题,可以通过 <questions@packtpub.com> 联系我们,我们将尽力解决。

第一章:Robot Framework 入门

在本章中,我们将涵盖以下主题:

  • 接受测试的定义和需求

  • Robot Framework 的介绍和简要历史

  • Robot Framework 的组件

  • 不同的安装方法

  • 不同的安装环境

  • 示例项目的创建和执行

  • 生成文件的简要描述

这本书向您介绍了 Robot Framework,这是一个基于 Python、以关键字驱动的、接受测试自动化框架。它非常灵活,易于使用和扩展,以满足您的需求。它旨在提供无论平台大小和待测试软件范围(也称为系统测试对象,SUT)如何的接受测试,是一个理想的软件工具,用于构建和管理不同测试,作为综合测试套件的一部分。由于此工具利用和管理测试,同时处理待测试的软件,因此对测试人员和开发人员都有益。如今,随着多功能软件工具的兴起和对测试驱动开发的重视,测试人员和开发者之间的界限已经变得模糊。为了有效地学习和使用此工具,您必须站在测试人员和开发人员的角度。还需要 Python 以及将其导入 Java 和.NET 框架(如 Jython 和 Ironpython)。

就像任何其他物理创造一样,软件的构建旨在直接或间接地改变我们的生活,以解决某人的任务或需求。然而,编程是一种抽象的科学,它不依赖于其最终用户的愿望,通常被称为垃圾输入-垃圾输出。创建的软件与其用户期望的行为之间的差异决定了用户对其的实现。因此,最终用户必须接受打算卖给他/她的软件。然而,用户通常不希望参与细节,只需要按照软件的每次迭代所设想的方式完成任务。为了执行此操作,需要验证最终用户与软件的交互,这导致了专门用于执行此测试和验证过程的测试的创建。这个过程被称为接受测试。然而,随着软件的增长,越来越多的接受测试出现,导致在测试失败时,无法轻易识别出正确的上下文。

随着软件规模和复杂性的增长,对其质量保证的需求也在增加。手动测试通常很容易设置,但它们在规模上的回报却在减少,并且只有在一定程度上可行,即测试人员可以手动处理不同的场景,及时识别出错误和缺陷,而不会影响最终产品的交付时间表。

接受测试的需求

对于大型或复杂的测试,采用结构化方法可以帮助您在系统测试接受阶段精确地定位错误。同时,提高开发速度和效率以及为软件的各种特性创造问责制也被考虑在内。这些好处可以总结如下:

  • 精确定位应用程序故障

  • 降低错误率

  • 提供自动化和可重用性

  • 创建测试审计跟踪

精确定位应用程序故障

通过测试,您可以识别出完全或部分故障,以及识别出在开发过程中或其他测试形式中可能出现的性能瓶颈。

降低错误率

通过自动化,可以精确地执行运行程序所需的预定步骤,没有任何干扰以及没有额外的或错误的用户交互。这与接受测试中的猴子测试不同;只需处理快乐路径场景。

提供自动化和重用

测试人员或其他人力资源比计算周期更昂贵。因此,最好自动化重复性任务,这将减少测试用户在输入、点击和消化用户界面时通常花费的时间。此外,测试可以重用或迭代,这减少了测试数量,同时确保完整的接受测试仍然存在,您可以专注于其他问题。

创建测试审计跟踪

通过记录各种测试结果,您可以收集有关接受测试的有趣事实,例如测试覆盖了多少系统,以及报告了多少次故障。这可以在管理变更以及现有软件的重构/现代化中非常有用。

什么是 Robot Framework?

Robot Framework 是一个开源的通用测试自动化框架,用于接受测试,并将其简化为主流开发,从而产生了接受测试驱动开发ATDD)的概念。虽然商业和内部自动化测试工具传统上被用来提供这种类型的测试自动化,但它存在重新发明轮子和供应商锁定以及缺乏在不同软件和不同情况下使用测试的灵活性的问题。它通过易于使用的表格测试文件脱颖而出,这些文件提供了不同的测试创建方法。由于不同的项目以不同的方式需要接受测试,因此需要使测试灵活,因为 Robot Framework 足够灵活和可扩展,可以处理这些场景。

正是工具的可扩展性使其如此多功能,可以调整到不同的场景,并与不同的软件后端一起使用。虽然它最常与 selenium 作为网站自动化工具一起使用,但它也可以与基于图像的测试软件如sikuli一起使用,还可以与需要通过多台机器远程访问的软件一起使用,而只需在给定的机器上运行测试。所有这些都可以通过创建自定义库轻松实现,这些库将机器人框架配置代码关键字与机器人框架使用的相关任务链接起来。另一方面,框架产生的输出也可以以多种方式使用,首先是 HTML 报告和日志文件,它不仅产生 XUnit 样式的输出,而且还包含详细的测试操作,同时表示整个测试的执行顺序和测试层次结构。这与可选的.xml生成形成对比,后者在进一步处理过程中可能很有用。一个这样的例子是创建自定义程序,这些程序使用运行测试获得的信息来创建各种结果。另一个例子是日志文件在持续交付环境中的后续使用,这可以使构建根据所有正在使用的单个验收测试继续或失败。

它是由佩卡·克拉克在他的硕士论文中创建的,作为其论文的一部分(eliga.fi/Thesis-Pekka-Laukkanen.pdf),并于 2005 年在诺基亚西门子网络公司内部开发。自 2008 年以来,其第二个版本已在 Apache 许可证 2.0 下开源,并拥有一个活跃的志愿者社区。它可在code.google.com/p/robotframework找到。

机器人框架生态系统

下图展示了框架的概念性、高级概述,并提供了对涉及的各种组件的深入了解:

机器人框架生态系统

这可以广泛解释如下:

  • 测试与测试数据:这是测试的配置,对于框架的大多数测试人员来说是最接近的。它包括测试和数据文件以及文件夹,以及那些指导测试执行的内容。

  • 测试结果:这是测试的最终产品,用于确定测试结果以及可以用来评估测试各个部分的日志。

  • 机器人框架:这是执行实际繁重工作的核心框架。

  • 测试工具驱动程序:它提供了框架与实际工具之间的通信。它可以根据现有测试工具的具体要求进行定制,以满足特定需求。

  • 测试工具:这是用于执行验收测试的实际软件。

  • 结束应用程序(待测试的系统):这是实际要测试其可用性以便客户或最终用户接受的实际软件。

安装和设置 Robot Framework

Robot Framework 的当前版本需要 Python 2.7 来进行设置。

目前,只有从 Python 环境创建 pybot 脚本。在其他环境中,仅创建相应的执行脚本。如果您有多个环境,则也可以安装不同的脚本。这与之前的版本不同,在安装时,pybot 和 jybot 脚本都会被安装。

对于自定义安装,您需要预先安装 Python、Jython 或 Ironpython;并且正确设置环境 PATH 变量,因为 Robot Framework 将使用 PATH 上可用的第一个 Python 二进制文件或如果通过 python 命令提供,则使用确切的库。您可以从命令行验证此信息:

sumit@darkstar066:~$ python --version 
Python 2.7.4 
sumit@darkstar066:~$ jython --version 
Jython 2.5.2 
sumit@darkstar066:~$ 

在项目下载页面,有各种选项,以下列出了以下自解释的标题。

源安装

要使用源代码,您可以下载包含源代码的 zip 文件,或使用 mercurial hg clone:code.google.com/p/robotframework 进行项目克隆。

这将在当前目录中克隆项目,然后您可以直接安装项目,或者进行一些修改以自定义框架。

现在转到已检出/解压源代码的文件夹,根据现有环境执行以下命令:

python setup.py install

上述命令安装了基于 Python 的版本,包括 pybot 和 rebot 运行脚本。

jython setup.py install

上述命令安装了基于 Jython 的版本,包括 jybot 和 jyrebot 脚本。

ipy setup.py install

上述命令安装了基于 Ironpython 的运行时,包括 ipybot 和 ipyrebot 脚本。

如果您看到此文件夹,以及标准的 setup.py,还有一个名为 install.py 的文件,可以用来安装(它与从 setup.py 安装类似),重新安装或卸载框架,可以使用以下方式:

python install.py in    [Installation]
python install.py un    [Uninstallation]
python install.py re    [Re-Installation]

要使用 Jython 或 IronPython 安装,请在命令中将 python 替换为 jythonipy。如果您遇到任何认证错误,可能需要使用 sudo/run 控制台作为管理员运行,具体取决于用户权限。

源安装

使用 Python 从源安装

一键图形安装程序

如果您正在运行 Windows XP(32 位),则可能希望使用一键安装程序,该安装程序将安装 Robot Framework 以及 Python 和可选的 Jython,并设置路径而无需任何干预。Windows 的其他图形安装程序也存在 32 位和 64 位版本。

Java 环境安装

您可以使用包含捆绑 Jython 以及框架的独立 jar 文件。您只需在系统上安装 Java,即可执行可运行的 jar 文件以进行安装。

在此方法中,不是命令,而是执行 jar 文件:

java -jar robotframework.jar run [options] data_sources

Python 包安装

pip 安装机制仅要求你在计算机上安装 Python 和包管理器,如easy_installpip。要安装此软件,你只需在命令提示符下输入pip install robotframeworkeasy_install robotframework,然后基于 Python 的 Robot Framework 就会安装。

注意,为了 Python 能够正确运行,你需要elementtree模块,因为默认的模块已经损坏。

用户可以在计算机上同时安装多个环境,并分别使用指定的命令,而不会影响任何安装。

支持不同的运行时

Robot Framework 不仅可以在原生 Python(CPython/pypy)安装上运行,还可以通过 Jython 和 ironpython 分别支持基于 Java 和.NET 的运行时。虽然有一些功能仅限于原生 Python 或基于 Jython 的 Robot Framework 安装,但大多数功能在所有运行时上都是等效的。由于人们可能拥有不同的操作系统和应用软件,因此可以根据他们的需求或愿望设置一个堆栈,这样他们就可以在不需要单独运行时的情况下将此工具集成到现有的运行时中。

根据使用的安装程序环境,Robot Framework 将创建适当的启动和后处理脚本:

环境 启动命令 后处理命令
Python pybot rebot
Jython jybot jyrebot
Iron Python ipybot ipyrebot

除了这些用于启动执行的命令外,如果安装了标准 Robot Framework,可以直接通过robot.run模块本身启动 Robot Framework。这也可以用作标准命令的替代,因为命令也内部调用模块。如果使用的 Python 命令是安装了 Robot Framework 的命令,则可以调用该模块:

python -m robot.run
jython .../run.py
ipy -m robot.run

如果 Robot Framework 被某个 Python 脚本调用,这很有用。你不需要分别执行脚本,可以轻松地从同一程序内部调用框架。

后处理命令对于长期重新创建测试执行很有用。测试执行后,你可以保存生成的 XML 文件作为输出,而不需要保存任何其他文件。为了将来再次重新创建报告和日志文件,可以使用rebot命令,该命令将 XML 文件作为参数,并生成日志和报告文件,而无需重新调用或运行实际的测试。

命令详情

Pybot命令提供了以下主要选项:

选项 描述
-N --name <name> 设置测试层次结构中最顶层测试套件的名称——从而有效地自定义这些区域。
-D --doc <documentation> 设置顶级测试套件的文档。
-M --metadata [name:value] 设置顶级测试套件的元数据。
-G --settag <tagname> 将给定的标签设置到所有执行的测试用例。
-t --test name 通过对它们执行模式匹配来选择可用的测试用例。
-s --suite name 通过其名称选择指定的测试套件,并允许测试报告具有所需的名称,而不是由文件/文件夹名称选择的名称。
-i --include tag 根据其标签名称选择要执行的测试。
-e --exclude tag 与包含标签相反。
-R --runfailed output 选择之前测试运行中失败的测试有另一个目标。
-c --critical tag 具有此标签的测试被认为是关键的(所有测试的默认值)。
-n --noncritical tag 具有此标签的测试被覆盖为非关键类型。
-v --variable name:value 在测试中设置变量,仅支持标量变量(${})。
-V --variablefile path 明确指定包含变量的文件。
-d --output dir 指定结果文件放置的期望目录。
-o --output file 生成的 XML 输出文件。
-l --log file 生成的 HTML 日志文件。
-r --report file 生成的 HTML 日志文件。
-x --xunit file 与 xUnit 兼容的结果文件(默认不创建)。
-b --debugginge rake 执行过程中写入的调试文件(默认不创建)。
-T --timestampoutputs 为所有输出文件添加时间戳并提供自定义标题。
-L --Loglevel 日志和日志测试顺序自定义的阈值级别。
-W --monitorwidth 指定监视输出宽度。
-C --monitotcolors 指定是否在控制台使用颜色。
-K --monitormarkers 为每个通过测试指定在控制台上的测试成功。
-P --pythonpath path 搜索测试库的附加位置。
-E -escape what 使用常见表示指定控制台中的转义字符。
-A --argumentfile path 指定一个文本文件以在测试中读取更多参数。
-h -? --help 打印命令的详细帮助。
--version 打印已安装的 Robot Framework 的版本。

一个小练习

为了演示 Robot Framework,我们将创建一个简单的虚拟应用程序,如下所示:

  1. 创建一个名为 simpleapp 的文件夹,这将成为应用程序的根文件夹。

  2. 在其中创建一个名为 testsuites 的文件夹,这将包含所有测试配置文件。

  3. testsuites 文件夹中创建一个名为 Test_Case_1.txt 的文件,内容如下:

    ***Test Cases***
    
    First Test Action  log  this is a basic test
    

    注意

    注意日志关键字前后有两个空格。

  4. 现在通过调用 Pybot 脚本并传递 testsuites 文件夹作为参数来运行项目。你应该得到以下截图类似的结果:一个小练习

这确认了项目已成功运行。你可以通过生成的 HTML 页面查看结果和日志,并使用 XML 文件对数据进行未来的计算。

由于我们使用了简单的日志语句,你会在输出日志中看到日志消息,如下截图所示:

一个小练习

生成的 XML 也易于阅读(如下截图所示),然后可以被任何其他外部工具作为输入参数使用——如果这个过程也被自动化,那么可以减少测试不同阶段之间的人工干预。

一个小练习

摘要

在本章中,我们研究了接受测试驱动开发的需求以及我们如何使用 Robot Framework 来实现它。讨论了在支持的平台上(即 Python 及其以 Jython 和 Ironpython 形式移植的等效版本)的安装方法。然后我们继续探索可用于执行各种任务的各种命令及其可能性。后来我们创建并运行了一个基本的测试,以验证我们设置的准确性。最后,我们检查了生成的输出文件,以了解框架的外观和感觉。

现在基础知识已经覆盖,是我们学习 Robot Framework 项目的语法、不同可用的操作以及涉及的不同文件的时候了;这将使我们能够以各种格式编写测试,并了解测试中允许的各种选项。

第二章 配置测试项目

在本章中,我们将专注于测试的结构和包含的文件。这个主题已经在第一章中简要提及,但更深入地了解它们将有助于为进一步的探索奠定基础,因为测试是 Robot Framework 最重要的特性。本章将涵盖以下主要内容:

  • 创建 Robot Framework 测试文件和测试套件。

  • 理解在不同文件格式配置中的语法差异。了解不同的配置文件。

  • 理解和利用设置和清理操作

  • 通过测试重用提高自动化程度

我们将首先解释什么是测试以及如何定义它。接下来将解释不同类型的测试和常见的命名规范,并附上示例。到本章结束时,我们将理解测试文件的结构和它们支持的格式。

一旦项目被正确设置,Robot Framework 使得更改项目中使用的测试配置变得非常容易。然而,在深入具体实现之前,最好理解测试到底是什么,以及应该如何组织它们。

与传统软件开发类似,测试可以以自顶向下的方式创建,先有整体视图,或者以自底向上的方式创建,先创建测试,然后集成。

在 Robot Framework 中,鼓励遵循自顶向下的方法,即首先创建测试结构,然后再创建和记录实际的实现。虽然这不是强制性的,但对于编写大型且可持续的测试很有用,并且是创建测试的推荐方式。

测试以树状结构组织,包括测试套件、测试用例和测试操作。这种规范在大多数结构化测试中都被遵循,并且是一个广泛遵循的规范。测试套件是一组不同的测试和其他测试套件,为执行测试提供逻辑单元。测试用例是对特定任务的完整测试。测试操作是任何测试中最小的元素,在本质上具有原子性,它仅验证给定条件。

测试命名规范

测试命名规范对于测试的标准化和一致性至关重要。它也反映了测试的质量,因为测试的命名和位置;以及用例场景表明了它们的顺序和相关性,这在未来维护测试时非常有用。

创建执行顺序

为了命名测试,Robot Framework 非常独特;它使用配置文件和文件夹名称来确定执行顺序和测试命名。

例如,考虑以下在文件系统中测试项目中不同测试文件和文件夹的排列:

application/

tests/

Test1.txt

Other tests/

Another test.txt

在应用程序文件夹中运行 pybot 将根据它们在文件系统中的存在顺序在报告中创建不同的测试套件。以下屏幕截图显示了 Robot Framework 测试的文件结构:

创建执行顺序

运行后,tree 命令列出文件/文件夹层次结构。在这里,Robot Framework 将推断测试层次结构,将测试分组,并以文件和文件夹的形式嵌套测试套件。从这个例子中,你可以观察到以下内容:

  • testsuites 文件夹将是根测试套件。

  • testsuites 文件夹下如 1__first_test 这样的文件夹将作为嵌套测试套件。

  • 这些文件夹中包含的测试文件将是进一步嵌套的测试套件。

例如,包含在 testsuites/2__different_file_formats/2__a_tsv_file_test.txt 中的测试将被嵌套,这可以从以下屏幕截图中得到更好的解释:

创建执行顺序

  • 测试套件层次结构在日志文件中详细说明。为了组织结果,确保适当的命名很重要。因此,而不是使用空格,应使用下划线 "_"(如前例所示)。

  • 为了在不考虑测试名称的情况下获得正确的顺序,可以在测试配置前加上数字。

测试随机化

有时,可能需要明确忽略执行顺序并随机运行测试。在这种情况下,可以在 pybot 命令中使用随机化选项。此选项有以下几种:

  • 要随机化所有测试套件以及它们包含的测试:

    pybot --randomize All all_tests
    
    
  • 要随机化套件而不影响最低级套件中包含的测试:

    pybot --randomize suites all_tests
    
    
  • 要仅随机化套件中的测试,套件执行顺序保持不变:

    pybot --randomize tests all_tests
    
    
  • 如果在命令行中设置,要移除任何随机化:

    pybot --randomize none all_tests
    
    

    注意

    命令参数从左到右读取,随机化选项可以多次出现。

如果应用适当的命名约定,如以下示例所示,示例的测试层次结构将导致更易于理解的测试,并且测试的执行顺序可以轻松预知。现在你可以轻松推断出以下顺序的执行顺序和层次结构:

application/

testsuites/

1__Software_initialization.txt

2__main_screen_checks.txt

3__test_aux_controls/

1__check_user_details.txt

2__check_aux_control.txt

4__check_values/

1__primary_values.txt

2__footer.txt

3__links_to_other_controls.txt

....

值得注意的是,此命名规则的唯一例外是初始化文件,其命名方式为 __init__ 后跟其他测试文件中使用的扩展名。由于每个文件夹只有一个 init 文件,因此可以清楚地看出此类文件包含有关其文件夹的信息,以及其中包含的信息与测试套件本身相关。

测试文件结构

到目前为止,已经证明空白字符在配置文件中起着重要的作用。测试配置以表格格式编写,每个列包含不同的元素,例如测试元素。Robot Framework 允许在测试文件中指定不同列之间的分隔具有灵活性,同时也支持不同的测试文件格式,您可以根据自己的意愿选择。请注意,根据文件扩展名,在运行时选择合适的解析器。以下是一些支持的格式:

  • HTML

  • TSV

  • 纯文本

  • 管道文本

  • RestructuredText

HTML 格式

在 HTML 格式中,读取 HTML,它包含不同部分的测试配置的不同表格。对于每个表格,读取第一个标题元素,并根据此信息理解表格的其余部分。请注意!任何位于已识别表格之外的数据都将被丢弃。您可以通过以下示例更好地理解这一点:

<table>
  <th>Test Case</th>
  <th>Action</th>
  <th>Argument</th>
  <th>Argument</th>
  <tr>
    <td>First Test Action</td>
    <td>Log</td>
    <td>This is a test written in HTML</td>
  </tr>
</table>

小贴士

下载示例代码

您可以从您在www.packtpub.com的账户下载您购买的所有 Packt 书籍的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support,并注册以直接将文件通过电子邮件发送给您。

注意,在表格标题的第一列表示表名,它决定了该表中包含的所有元素的后续执行。随后是其他标题,表示其他数据的位量和顺序。表格的其余内容按照指定顺序填充所需信息。在这里,数据不是通过两个空格分隔,而是存在于表格的不同列中。这种方法需要最多的开销和冗长的元数据,但测试非常易于查看,并且减少了关于保持多少空格的混淆,因为您可以在网页浏览器中轻松查看这些文件,也可以在 HTML 编辑器中编辑。

TSV 格式

在制表符分隔值格式中,可以通过传递由单个制表符分隔的值来指定不同的列。这种格式的令人惊叹的特性之一是它可以在任何电子表格应用程序中打开,这为您和其他用户提供了对测试配置文件的更大控制。如果正在使用的文本编辑器支持查看空白(空格和制表符),那么启用它是一个好主意,以便在没有错误的情况下保持制表符分隔的测试,因为用户不可避免地会混合两者,导致测试出现故障。创建和维护这些测试的另一种适当方法是仅使用电子表格应用程序,这会降低损坏测试的机会。在电子表格中(如下面的截图所示),测试文件的使用更加自然和直观,因为列被正确区分。如果您在开发电子表格解决方案方面有经验,但对 Robot Framework 却很陌生,那么您的学习曲线将大大降低,您在编写和维护电子表格中的测试时可能会感到更加自在,这些测试也可以格式化以增强可见性和易用性。

TSV 格式

明文格式

如果测试配置文件显示不是问题,那么明文文件是最佳选择,因为它最易读,并且包含的元数据很少,这使得版本控制更容易。这种方法在此框架中应用最广泛。然而,你必须注意确保元素被正确分隔,并且列元素由两个空白字符分隔。如果测试中使用的参数数量少且列数有限,那么这是合适的显示格式。以这种方式排列元素的语言和位置首先需要一些适应,但随着你对这种格式的使用,创建和修改测试用例会变得更容易,因为你不需要除了文本编辑器之外的其他东西来创建和更新测试。由于空白至少需要两个或更多,因此不可能留下多于一个空列。这看起来可能不是问题,但实际上非常方便,尤其是在需要为多个列提供显式空白分隔的情况下。

管道分隔格式

与之前的格式非常相似的是管道分隔格式,它在文档中使用管道字符来分隔不同的列。这用于不同行包含不同数量参数的情况,这些参数难以识别。考虑以下测试片段:

A Custom test  [Documentation]  this test is done to ensure product quality matches the requirements
    Log  Starting the product quality test
    Verify the initial condition exists  Should Be Equal  ${Product}  Drill Machine

在这种情况下,测试的冗长性使得阅读和理解测试变得更加困难。更糟糕的是,如果有人正在修改它,他可能会意外地引入错误。例如,文档已按以下方式更新:

A Custom test  [Documentation] The test ensures that product quality matches federal requirements

如果您观察[Documentation]末尾的空白,只有一个空格,这会将Documentation关键字及其参数合并为一个,Robot Framework 无法理解这一点,导致其失败。

为了在同一个文本文件中纠正这个问题,Robot Framework 提供了使用管道符号(|)而不是两个空格的灵活性。除了行的第一个字符外,此符号在两侧都由空格包围,因此前面的测试变为:

| A Custom test | [Documentation] | this test is done to ensure product quality matches the requirements |
|  | Log | Starting the product quality test |
|  | Verify the initial condition exists | Should Be Equal | ${Product} | Drill Machine 

由于列现在由管道符号分隔,因此这种格式更易于阅读。请注意,第三行的结束管道符号不存在,因为在任何行的最后一列的管道符号位置是可选的。如果需要在任何列中作为普通文本,可以使用退格字符来转义管道符号。转义字符串为(\|)。此格式相对于纯文本格式提供的另一个优点是,可以明确声明多个列为空,并且测试仍然可以正确运行。这与在特定列中精确放置文本相结合,导致创建具有非常特定结构的测试。在测试中存在循环的情况下,还需要管道符号来嵌套测试结构,这与 Python 编程中发现的缩进类似,但在 Robot Framework 中不可能,因为超过两个空格不构成空列或缩进(关于测试中的迭代将在稍后讨论)。

重新结构化文本格式

ReStructuredTextreST)文本格式对任何 Python 开发者来说都很熟悉,因为它用于 Python 文档。它是一种基于纯文本的标记,可以使用简单的文本文件和预定义的标记集轻松创建高度格式化的文档、表格等。它提供的优势是使用的元数据非常少,文件包含大部分文本,可以轻松地进行版本控制、编辑、区分以及搜索。rest 标记提供了 HTML 和纯文本文件的优势。

与 HTML 格式类似,测试数据是在表格中定义的,Robot Framework 会查找表格的第一个元素以确定该表格是否为有效的测试表格,如果是正确的,则确定其类型,并相应地处理其余元素。在此格式中,第一列中的空单元格需要有一个\或一个..符号。

========  ===========  ==========  ========= =======
 Test Case        Action                     Argument            Argument          Argument
========  ===========  ==========  ========= =======
Custom check   [Documentation]    custom checks
\                         Log                        Starting checks
\
\                         Another Test          Should Be Equal${Existing}     15.45
========  ===========  ==========  ========= =======

由于处理 rest 标记的工具是 docutils 项目的一部分,因此您需要在执行测试的 Python 实例中安装 Python docutils 模块。Robot Framework 内部将 rest 文件转换为 HTML 文档,如果此格式存在问题,则可以使用其他工具将 rest 结构化文档转换为 HTML,这可以用于运行测试。

这是 Robot Framework 的灵活性,允许您拥有不同的文件格式和结构。在测试编写风格方面的这种灵活性还有更多内容,将在后续章节中介绍。

测试配置文件

如前所述,测试存储在文件中,并组合在文件夹中,这些文件夹充当测试套件。一个测试文件可以包含不同的部分,这些部分可以可选地移动到其他文件中,专门针对该特定部分的工作。这样,可以减少实际测试文件的长度和复杂性,这对于测试大小非常大时非常有帮助。

除了实际的测试文件和文件夹之外,测试配置文件还包括:

套件初始化文件

Robot Framework 中的一个文件夹表示包含其所有文件和子文件夹的测试套件。由于除了文件夹名称外没有其他方式可以指定测试套件的元数据,因此为放置在其中的文件夹提供了特殊文件。与将目录指定为 Python 模块一样,初始化文件必须命名为__init__,并且它们的扩展名可以是 Robot Framework 允许的任何有效扩展名。这些文件的格式与测试用例文件相同,但除了少数例外,不允许使用测试用例选项。

在定义标签、设置、清理操作以及测试用例超时的情况下,这里指定的配置与测试用例文件中允许的配置重叠。然而,这些文件中覆盖的更改适用于包含此初始化文件的整个测试套件。

值得注意的是,套件setupteardown的存在。这些只在给定测试套件以及任何子测试套件中的所有测试执行之前和之后执行一次。此外,如果测试套件中有任何子测试套件,则这些初始化文件也将以同样的方式运行。以下是一个示例:

| 设置 | 值 | 值 |

| 文档 | 套件初始化文件 |

| 套件设置 | 记录 | 这是整个套件的设置方法 |

| 强制标签 | example |

| 套件清理 | 记录 | 此套件已结束 |

外部变量文件

这些文件包含测试用例中使用的变量。在外部文件中指定变量的主要目的是遵循DRY不要重复自己)原则,以最小化重复,并可以在不更改测试其余部分的情况下,在单个位置更改变量。这些文件提供的变量被创建为其他需要变量信息的文件,这与测试的变量部分不同,或者与仅适用于定义的测试用例的变量表不同。

注意

注意,变量名是区分大小写的。为了区分变量和其他关键字,请记住,通常变量使用大写字母,但并没有这样的规则。

变量定义为 ${变量名} 用于普通、单值变量,以及定义为 @{变量名} 用于包含不同值列表的变量。

在测试配置文件中,当只指定变量表时,测试文件变为变量文件,并且在其使用时,只有以变量开始的表将被考虑。

结构

变量文件通常可以存储大量和不同类型的变量。例如,变量文件可以具有以下结构,声明各种类型的变量:

*** Variables *** 
${Weather}  London  Cloudy  25 
${humidity}  75 
${MARKS}  65.5 
@{DAYS}  Monday  Wednesday  Friday  Sunday

包含变量的 Python/Java 文件

变量也可以在 Python 或 Java 文件中创建,因为在某些情况下,Python 或 Java 类可能需要在运行时保存一些动态数据值,这些值可以传递给需要测试的测试。唯一限制性的是,Python 类名应与其模块相同,Java 类不得在任何类型的包中。最简单的方法是将 Python/Java 源文件放置在与测试文件相同的目录中(但如果您有一个独立的应用程序或大量测试/脚本,则不建议这样做)。如果您需要从外部服务或应用程序引用某些值,则可以引用用于填充其变量的源文件,这些变量可以在测试中使用。

例如,在 Python 文件中,哈希可以设置为/修改为变量,如下所示:

person = { 'name' : 'John Doe','age' : '26', 'grade' : 'A', 'gpa' : 8.9 }

在 Java 文件中,它也可以被修改如下:

public String name = "Robot Framework";

此外,它也可以在测试中使用,例如:

*** Setting ***
Variables  python_file.py
Variables  JavaFile.java
....
*** Test Cases ***
...
  Log  For ${person['name']}, the grade obtained was ${person['grade']}
  Log  You are using ${name}

就像在测试本身中定义的任何其他变量一样,这些程序中指定的变量也可以使用。

以类似的方式,Python/Java 代码中的特殊函数提供了从 get_variables/getVariables 获取变量的功能。变量必须以 LIST 关键字为前缀,否则它们将被假定是标量,并且只能有一个值。

小贴士

如果变量及其设置这些变量的函数在类中有默认或更高的作用域,它们对 Robot Framework 测试是可见的。

虽然 Java 中定义的变量只能与 Jython 运行时一起使用,但可以使用 Python 文件在任何 Robot Framework 运行时中,因为所有运行时基本上都源自 Python。

要将资源文件中存在的变量用于测试用例,可以给出变量关键字后跟变量文件的绝对或相对路径(根据情况,可以是 .class.py 文件),并且可以在文件本身内部的变量表中像定义变量一样使用这些变量,如下所示:

*** Setting ***
Variables  path/to/variablefile.py
Variables path/to/java_file.class

资源文件

当需要保存变量数据以及高级用户关键字时,资源文件是必需的。用户关键字的术语将在本书后面解释,但可以说,用户关键字基本上是一个不在任何库中而是在同一文件或外部资源文件中的关键字。

结构

资源文件不能包含测试用例。除此之外,它与测试用例文件相同。在实际的测试用例文件中,此文件必须通过设置表中的“资源”名称导入。指定资源后,必须提交文件路径,可以是相对于测试用例的绝对路径或相对路径。

如前所述,资源文件指定了变量和自定义用户关键字,因此它包含变量定义表和关键字定义表,以及可以允许导入某些外部库的设置表,因为用户关键字可能作为某些外部库的别名。以下是一个资源文件的示例:

*** Settings ***
Resource  Path/to/another_resource

*** Variable ***
${USER}  Test user

*** Keyword ***
Print welcome message for  [Arguments]  ${USER}
    Log  Welcome ${USER}!

关键字的创建增加了测试中可用的语法,并在测试文件内部可以轻松使用。

*** Settings ***
Resource  path/to/resource_file.txt

*** Test Cases ***
Test user defined keyword loaded from resource file
  Print welcome message for  Mister President

测试设置和拆卸

在测试过程中,需要在测试执行期间特定时间执行某些任务。这些操作通常在测试前后进行。这些被称为测试设置和拆卸(通常称为前置条件和后置条件),它们在结构化测试中普遍存在,例如单元测试、功能测试,甚至是验收测试。

测试设置发生在测试开始之前,测试拆卸发生在测试执行之后。值得注意的是,无论测试成功还是失败,测试拆卸都会在测试之后运行。唯一不会执行的条件是测试的无条件终止,这发生在测试错误期间。这些测试部分包含测试所需的预条件,例如打开特定网页的网页浏览器、设置数据库连接等。当测试完成后,关闭打开的连接、浏览器或资源,并确保任何后续操作都不会带来测试期间采取行动的任何后果。

设置/拆卸在自动化测试中的作用如下:

  • 设置测试环境

  • 创建测试环境

  • 加载初始测试数据

  • 对每个测试重复

    • 设置单个测试要求

    • 执行操作并断言条件

    • 清理用于测试的资源

  • 总结/保存有用信息

  • 恢复环境状态到初始条件

  • 测试执行分析

设置和销毁操作可以应用于测试以及测试套件级别。它不适用于测试内部。如果需要在测试中的不同语句之间插入它,那么可能意味着测试编写不正确,并且需要重新审视和重构测试结构,将其分解成更小的测试,并根据与单个测试相关的需求进行参数化。

作为自身的一个强大框架,Robot Framework 提供了在测试套件以及单个测试中使用这些操作的能力。对于测试套件,可以使用初始化文件;对于单个测试,可以利用测试文件本身的设置表,其中可以包含设置和销毁设置,甚至可以在测试用例本身中以设置和销毁操作的形式存在。指定条件后使用None表示该特定操作不可行。以下是一些功能的简要概述:

*** Settings ***
Test Setup  Open database connection
.....
*** Test Case ***
Some test case  [teardown]  Close connection

Case without teardown  [teardown]  NONE

Alternative names  [Precondition]  some conditions
    [Postcondition]  Cleanup this mess

因此,测试设置和销毁提供了一种方法,使我们能够将测试的重复部分集中在一个地方,从而避免在各个地方重复相同的指令集,为通过测试参数化实现测试自动化和重用创造了条件。

摘要

在本章中,讨论了涉及 Robot Framework 测试创建和配置的各种文件,以及不同组件(如测试套件、测试用例和测试操作)的测试命名约定。同时详细介绍了执行顺序管理。由于测试文件格式与其他任何测试都相当不同,因此也进行了详尽的讨论。还讨论了变量的使用以及额外文件的使用,因为这些可以促进测试代码的重用并分离测试内容。最后,讨论了通过设置和销毁操作进行测试环境管理,这对于测试需要任何先决依赖项是必不可少的。

这为在框架上进一步工作奠定了基础,并且随着这里提到的基本语法的覆盖,下一章将讨论测试自动化和重用,该章节将继续在这里所涵盖的工作,以自动化和重用现有测试。

第三章。进一步测试定制

本章涵盖了创建可复用测试组件所需的语法和样式,以便进行自动化测试。除了以 Robot Framework 为中心的测试外,它还介绍了行为驱动开发,并涵盖了以下主要主题:

  • 测试复用的必要性

  • 内部和外部复用

  • 将数据输入到测试脚本中

  • 高阶测试复用

  • 不同风格的测试编写

自动化和敏捷

敏捷宣言非常重视可用的代码而非传统文档。它鼓励诸如极限编程等实践,这是一种敏捷软件开发实践,可以提高软件质量,并使软件开发更能响应不断变化的客户需求。该实践的其他重要原则之一是自动化的验收测试。验收测试简单来说是一些可以运行并捕捉系统功能某个方面的代码。其理念是开发者和利益相关者共同编写此测试,以将需求体现在代码中,当测试通过时,形成某种形式的批准印章。这些测试与单元测试和集成测试不同,因为它们主要是由开发者为开发者编写的,有助于他们出现、验证设计和防止错误。验收测试是由利益相关者和开发者编写的,为利益相关者和开发者而写。敏捷方法将重要性放在测试上,因为测试本身成为规范而不是业务报告或文档。

一个常用的说法是,单元测试和验收测试之间的区别在于,单元测试帮助你正确构建事物,而验收测试帮助你构建正确的事物。

如前所述,Robot Framework 作为一个自动化的验收测试驱动开发工具,提供了各种开箱即用的功能,并允许用户有足够的灵活性来进行自动化,以确保所讨论的软件始终具备其基本功能。

在编写测试之前,有必要了解如何实现一个设计,该设计将有助于扩展和维护测试以适应未来的需求。与其他任何软件的创建类似,以模块化方式编写的测试可以通过选择不同的测试模块来实现复用。以下图表可以更好地解释这一点:

自动化和敏捷

在这里,很明显,将测试1分离到一个独特的模块中,使我们能够在三个其他测试的部分中使用相同的测试集,从而减少了手动创建测试时的重复量。

然而,通常在验收测试期间,有一些部分是特定于测试执行情况的。考虑以下需要为包含数百页面的大型网站执行验收测试的示例。

测试网站模块功能:

  1. 打开浏览器。

  2. 前往特定的页面 URL。

  3. 确保它不是一个空页面/无效的URL

  4. 检查网站头部和尾部是否存在并且显示正确。

  5. 确认实际页面内容(不包括头部和尾部)不为空。

  6. 搜索并验证页面中是否存在特定元素。

  7. 关闭浏览器。

即使在这个简短的测试中,也有无数的可能性,单个测试无法涵盖所有这些。因此,测试人员会复制此类测试,并在进行更改后将其放置在其他地方以满足其他要求。然而,复制会导致存在难以更改的重复测试,因为环境的变化需要在不同的测试中进行更改。另一方面,如果存在测试复用,那么在某个地方对复用测试的更改可以反映到不同的测试中。为了解决不同场景中独特性的问题,可以对相同的测试进行参数化。在前面的示例中,可能的参数化可以是以下这样。

测试网站模块功能(浏览器、URL 和内容):

  1. 打开浏览器(选择指定的浏览器)。

  2. 前往特定的页面URL(如参数中指定)。

  3. 确保它不是一个空页面/无效的URL

  4. 检查网站头部和尾部是否存在并且显示正确。

  5. 确认实际页面内容(不包括参数中指定的头部和尾部)不为空。

  6. 搜索并验证页面中是否存在参数化的内容

  7. 关闭浏览器。

现在,相同的测试可以在广泛的场景(阅读页面)中使用,并且可以使用相同的测试来测试整个网站的不同部分的内容。

如此所述,创建可复用测试的相同参数化方法可以通过使用变量应用于 Robot Framework。变量可以用作从给定信息源(与测试和测试执行无关)的输入机制,测试执行取决于获得的数据。由于测试操作的重复是测试复用的基石,因此即使在测试内部也有可能重复测试操作。在这样做的时候,单个测试或用例可以再次内部重复相同的指令,通常伴随着一些特定重复的独特变量数据。这些内容将在以下章节中详细说明。

内部复用

如前所述,单个测试内的重复构成内部测试复用。请注意,涉及不同迭代实例的数据(如果有的话)可能来自外部,但重复仅发生在测试操作内部。

循环和流程控制

在掌握了编写测试的语法背景之后,现在是时候转向最常见且方便的迭代方式了,那就是循环。Robot Framework 通过使用 Python 风格的for循环来解决这一问题,但对于初学者来说也容易理解。

它遵循直接的语法,循环以特殊关键词FOR开始。接下来是一个存在于循环内的变量。这个变量后面跟着一个强制性的IN语句。然后是for循环要运行的变量或集合。与 Python 循环一样,后续语句缩进一个空格。一旦缩进停止,就假定循环体已经完成。

所有这些都看起来像是任何编程语言的迭代结构,但在 Robot Framework 中存在一些例外,例如:

  • for循环可以使用多个变量进行迭代。

  • 循环不能在其内部直接嵌套循环,但可以在循环中使用自定义关键词,这些关键词可以包含嵌套循环。

  • 循环迭代的标量变量集合可以指定为不同的参数

注意,for循环需要显式地定义空白,以清楚地划分不同的列,因为简单的文本文件使用空格/制表符作为分隔符是不够的。如果尝试运行,它将打印出错误信息“FOR loop contains no keywords”。这是因为循环体需要(额外的)缩进,而在简单的空白中这是不可能的,因为两个或两个以上的空格只能作为一个分隔符。

for循环有一个变体,允许遍历一系列值。这是 Python 的惯用法,但有时非常方便。其语法是:FOR关键词后跟一个变量。接下来是In Range关键词,它通过参数提供各种范围限制。以下是如何演示的:

# This code block runs 5 times for values of x between 0 and 4
|  | :FOR | ${x} | IN RANGE | 5
# This code block runs 5 times for values of x between 11 and 15
|  | :FOR | ${x} | IN RANGE | 11 | 16 | 
# This code block runs 5 times for x = 10, 12, 14, 16,18
|  | :FOR | ${x} | IN RANGE | 10  |  20 |  2  |
|  |    |  Log  |  ${x} |

流程控制

在循环迭代过程中,有时需要改变执行方式,这可以是跳过当前迭代并继续下一个迭代,或者完全终止循环。

有时,循环内容需要以非迭代的方式进行处理。在这种情况下,我们需要发出特殊的命令,允许我们根据迭代状态来操作循环内容流中的内容。在大多数传统编程语言中,这通过continuebreak结构来实现。Robot Framework 通过在其默认库中提供一些特殊关键词来实现类似的方法。

在完成前中断

通过使用内置关键词Exit For LoopExit For Loop If,可以终止循环并继续执行后续语句:

|  |  | Run Keyword If | ${val} > 10 | Exit For Loop

在前面的例子中,使用了Run Keyword if,这是内置库中的一个功能。一旦其条件评估为真,它就会被执行,并且Exit for Loop关键字会导致循环终止。如果测试用例在循环之后有任何其他语句,那么它们将正常执行。

可以通过使用Exit For Loop If关键字来简化,因为它作为 break 操作的处理器,而不需要单独的if条件,因此前面的命令可以重写为:

|  |  | Exit For Loop If | ${val} > 10 |

继续进行下一个迭代,类似于中断循环,有时在当前迭代完成之前,需要继续进行循环的下一个迭代,这时会有一些特殊情况:

|  |  | Continue Keyword If | ${val} > 10 | Exit For Loop

注意各种命令上If后缀的使用。If语句不是一个特定的关键字,但许多语句,如Exit For Loopcontinue关键字,在特定条件下有条件性的替代定义。

提供外部数据

测试可以从任何外部数据存储中获取数据,例如数据库、Excel 或 CSV 文件,或者某些返回动态值的外部应用程序,然后可以在相同的数据上执行。为了进一步演示测试重用的概念,我们将进行另一个练习,该练习侧重于重复执行相同的任务。为了方便读者,我们现在将这些概念抽象化,因为它们可以用任何可能的方式实现。

基本上,如果我们有一组在值集合中指定的可重复任务,那么我们可以以两种不同的方式执行它们:

  • 在测试中对每个值重复执行任务集

  • 对这些值重复执行整个测试

在测试中重复执行一系列任务

在这种情况下,我们创建一个测试,它接受一个参数或使用包含元素列表的变量,并遍历它。作为这个过程的先导,首先让我们创建包含动态变量的文件。在这里,被测试的系统是一个 Python 脚本,它从当前时间中选取数组中的值,而我们无法预先确定这些值:

import time 
var = [] 
while(time.time()%10 <8): 
  var.append(int(time.time()%10)) 
  time.sleep(1)

前面的脚本首先导入了time模块,因为它将在程序后面使用。接下来创建var数组。然后是一个while循环,它检查当前已过时间的最后一位小数,并检查它是否小于8。如果是,则将这个最后值作为一个整数添加到数组中,并暂停一秒钟以获取另一个值。尽管var数组不是随机的,但它的尺寸和内容在事先是未知的,这使得var数组在运行时是动态的。

这让我们有了变量var,它可以具有未指定的值量。现在我们可以利用它更好地利用测试中的值集合。在测试中,首先加载这个 Python 变量文件,然后迭代其内容:

| *Setting* | *Value* | 
| Variables | ./dynamic_variables.py | 
| *Test Cases* | *Action* | *Argument* | 
| List should exist | Variable Should Exist | @{var} | 
| Variable not declared should not be there | Variable Should Not Exist | ${val} | 
| Iterate over Dynamic variables | :FOR | ${val} | IN | @{var} | 
|                |         | Log      | ${val} | 
|                | Log  | finished iteration |

这将加载脚本中的内容,并对值集合进行迭代,对每个值执行一个样本任务。

在测试自动化中的应用

通过使用自定义用户关键词和通过外部程序加载测试数据(该程序可以利用任何可用的数据介质来加载测试系统的数据),可以将概述的循环概念应用于测试自动化。如前所述,这有助于实现测试重用,并确保我们作为测试人员遵循不要重复自己DRY)的原则。

高阶重用

通过创建和使用包含各种测试命令甚至整个测试的高阶结构,可以在测试套件中重复测试。这使得测试人员可以将类似或等效的用户故事或用例组合成一个单独的测试,并根据情况提供不同的输入。测试重用提供的另一个显著优势是项目的整体清晰度。如果重用测试,则必须从各个地方调用它们,从而带来 DRY 的好处。

用户关键词

如前所述,用户关键词可以用来将测试的一部分嵌入到一个单独的自定义关键词中。这些可以重用,它们还可以在其定义中指定参数,这些参数可以通过这些测试的调用者传递测试数据参数。

测试模板

测试模板用于在测试中创建可以接受不同运行时参数的组件。这与用户关键词不同,因为用户关键词必须通过调用者以它们的名称和参数来调用,但模板只提供要处理的数据。可以从以下示例模板中获得更好的图片,该模板只是将提供的数据记录到其中:

Template to print params  [Template]  Log
                                      Alpha
                                      Beta
                                      Gamma
                                      Delta

此示例按顺序向模板传递参数,以便自身被处理。在这里,测试重复执行模板指定的操作,并且测试实际上变成了以下实际测试的简短版本:

A normal test to print param
                Log  Alpha
                Log  Beta
                Log  Gamma
                Log  Delta

注意,这是一个简单的模板示例,仅在测试用例表中可见。还有其他创建模板的可能性,可以在不同的测试中重用。通过使用模板,测试变得更加面向数据,Robot Framework 官方文档指出,通过模板,关键字驱动测试可以转换为数据驱动测试。

用户库

用户库为将功能实现到 Robot Framework 中提供了包装器。通过使用用户库,我们能够扩展框架以提供特定任务,或者更重要的是,扩展工具的能力以在其他工具上工作。相反,要使用自定义库,Robot Framework 测试必须遵循该库提供的关键字,并提供必要参数的数据,从而满足导致测试正确执行的关键字格式合约。这种创建自定义库并在各种测试中使用的技巧将在下一章中详细讨论。

编写测试的方法

测试涉及多种方法,通常不同测试编写风格的不同性质将测试与其他软件开发形式区分开来。编写验收测试可以通过直接使用之前提到的标准库和外部库关键字来完成,或者通过使用某种机制简化测试文本,使其对非技术人员更具可读性。这在敏捷软件开发中至关重要,因为利益相关者在软件设计早期就参与其中,可能不具备技术倾向或需要像程序员一样理解测试的语法。然而,他们可以提供关于应用程序应该如何工作或表现的观点;他们的输入和反馈很重要。

Robot Framework 主要支持三种编写测试的风格。虽然测试的执行和输出没有区别,但测试语法的本质正是将其与不同风格编写的类似测试区分开来。这些内容将在以下部分详细解释:

键盘驱动测试

键盘驱动测试是最常用的技术,其中测试被分解为称为关键字的不同部分,这些关键字决定了测试的内容。这些关键字可以进一步包含其他关键字或测试,这些关键字或测试可以在需要的地方重用和提取。通过使用关键字,测试结构可以变得抽象和多样化,并且可以在单个关键字下添加多个和/或复杂的语句,从而使测试更容易理解,其功能也容易理解。

为了更好地理解这种方法,考虑以下测试代码,它使用进程库以google.com作为打开的页面打开 Firefox 浏览器:

Start Process  firefox  google.com

现在考虑关键字方法:

Open google.com homepage in firefox browser

这段代码与之前的代码完全相同,但在测试中提供了更清晰的视图。其实现细节可以像以下这样隐藏在Keyword表中:

 Open ${url} homepage on ${prog} browser  Start Process  ${prog}  ${url}

数据驱动测试

数据驱动测试在进行参数化时很有用,因为相同的测试可以用包含不同值的不同的数据重新使用。这使得这些测试具有多功能性,并且在不执行相同的一组操作的情况下,可以轻松地拥有各种测试案例,其中要执行的任务在很大程度上保持不变,只需更改输入和输出即可。这与关键字驱动测试不同,因为这些测试更粗糙、更细粒度,并且依赖于测试模板来提供必要的测试,正如在之前的测试模板部分所解释的那样。

行为驱动测试

最近增长迅速的流行风格之一是行为驱动开发。创建覆盖软件行为的测试,并根据这些测试编写实际的软件,这被称为行为驱动开发BDD)。然而,到目前为止,这本书主要处理的是基于关键字的验收测试,其结构相当僵化。为了处理自动化,可以使用外部数据流,并根据数据将测试信息输入到测试中。然而,测试也可以根据面向行为的业务用户需求进行结构化。但是,在我们将 BDD 应用到测试之前,首先需要理解 BDD。

行为驱动开发

尽管自动化验收测试具有明显的优势,但在实践中,即使在经验丰富的 XP 和 TDD 团队中,也很少这样做,或者做得不好。其中一个原因是很难找到一个具有技术能力、兴趣和耐心坐在电脑前编写纯代码的利益相关者,即使是像 gerkin 或 RSpec 这样的 DSL。考虑以下存在于 WEBrick(Ruby 中常用的 HTTP 服务器)中的rspec测试:

  should "be a WEBrick" do 
    GET("/test") 
    status.should.equal 200 
    response["SERVER_SOFTWARE"].should =~ /WEBrick/ 
    response["HTTP_VERSION"].should.equal "HTTP/1.1" 
    response["SERVER_PROTOCOL"].should.equal "HTTP/1.1" 
    response["SERVER_PORT"].should.equal "9202" 
    response["SERVER_NAME"].should.equal "127.0.0.1" 
  end

此示例观察基于服务器响应的行为,由此可以得出结论,该服务器是 WEBrick 服务器或不是。

然而,有时这可能会深度集成到代码中,并要求测试代码能够访问被测系统的内部结构。这是因为开发者需要将实际的方法调用/接口或软件的代码模拟或存根直接集成到rspec测试中,这在涉及开发者的项目中可能没问题,但在需要黑盒测试,如验收测试的情况下则不可行。

使用 Robot Framework 进行 BDD

Robot Framework 不仅提供了一个 DSL 或平台,可以轻松以人类可读的格式编写代码,而且它还与理解相关软件的内部结构分离,因为它只为给定的行为执行验收测试。这些测试仅在用户关键字如何接收参数的方式上有所不同,这是在关键字内部完成的。在这里,这些关键字由多个字母组成,描述了要执行的具体操作。

标准库

机器人框架提供了各种关键字,到目前为止已经讨论过。这些关键字包含在builtIn库中,并且默认情况下对任何测试都是可用的。除了这些之外,还有一些额外的关键字是框架的一部分,作为单独的库捆绑在一起,要使用它们,需要提供显式的引用,无需安装。以下是一些库:

  • 集合

  • 对话框

  • 操作系统

  • 进程

  • 截图

  • 字符串

  • Telnet

  • XML

集合

这个库使用从外部 Python 文件提供的列表和字典,并对其进行各种操作,如比较和修改。builtin库中的一些操作列表和字典的关键字也可以与这个库一起使用。例如,考虑以下示例,其中 Python 文件定义了以下变量:

details = [1,'ssh', .034, 'main-repository']
user = {'name':'john doe', 'age': 21, 'account':'basic'}

这些变量可以在测试中按以下方式操作:

*** Setting ***

Library  Collections
Variables  filename.py

*** Test Cases ***

Lists  Should not be empty  ${details}
       Append to List  ${details}  12500
       ${custom}  Create List  1  ssh  .34  main-repository  12500
       Lists should be equal  ${details}  ${custom}

Dicts  Should not be empty  ${user}
       Dictionary should contain key  ${user}  name
       Dictionary should contain value  ${user}  21
       Dictionary should contain value  ${user}  basic

类似地,集合库中的其他关键字也可以与其他库一起使用。

对话框

对话框提供了一种在测试执行期间让用户输入数据的方式。尽管这与自动化测试的原则相悖,但在某些情况下却是所需的。

注意

注意,目前,这个库在 IronPython 运行时不可用。

例如,以下命令允许用户通过或失败一个给定的步骤:

Execute Manual Step  Perform manual operation and continue

这提供了以下对话框,等待用户输入以继续:

对话框

在指定失败选项后,用户在测试失败之前会被进一步要求输入失败信息。

类似地,这个库中指定的其他关键字也可以使用。

操作系统

这个库提供了机器人框架与操作系统环境的交互,例如文件和文件夹、环境变量,以及调用各种进程的能力。这个库中声明的多数方法都是自解释的。然而,管理进程的关键字已被弃用,现在也存在于进程库中。

进程

这个库允许测试运行外部程序。它使用 Python 中的子进程模块来生成外部进程,连接输入/错误/输出消息管道,并获取返回代码。它可以运行进程并等待其终止,或者以在后台运行进程。为了更好地管理,它还可以终止由测试启动的一个或所有进程。

截图

这个库允许在 Robot Framework 测试执行期间捕获屏幕,如果测试环境中存在屏幕,则允许详细地报告项目。如果与 Python 运行时一起使用,这需要额外的库,如 wxPythonpygtk。其他运行时提供开箱即用的屏幕捕获支持。take 截图将屏幕截图保存到日志文件或 XML 输出生成的位置,如果没有指定设置或文件位置。如果没有给出名称,则将 Screenshot_number.jpg 保存到每次执行后数字递增的位置以创建一个唯一的保存图像。同样,宽度参数指定了在日志文件中分配给图像的区域大小。

以下指定了屏幕截图图像的文件名和大小:

  Take Screenshot  screenpic.jpg  width=500 px

这将保存以下图像并将其嵌入到日志文件中:

截图

字符串

这提供了正常的字符串操作,如子字符串、替换和字符串分割,以及生成随机字符串的专用函数。这还包含操作跨多行字符串的实用方法。

Telnet

这个库允许 Robot Framework 测试连接到 Telnet 服务器并传递在服务器上运行的命令。测试这个功能的最简单方法是设置一个本机的测试服务器。假设你在机器上正确设置了 Telnet 服务器,用户名和密码都设置为 test,那么以下代码将按预期执行:

*** Setting ***
Library  Telnet
*** Test Cases ***
Telnet Session  Close All Connections
    Open Connection  127.0.0.1  prompt=test
    Login  test  test  login_prompt=login:  password_prompt=password:
    ${details}  Execute Command  ls-l
    Log  ${details}

注意

注意,在 Open Connection 命令中设置提示不是强制性的,但对于某些命令(如 execute 命令)是必需的。这个库足以打开、关闭以及在不同 Telnet 连接之间切换,并涵盖了大多数 Telnet 功能。

XML

这是框架提供的 XML 解析器,可以用来搜索和验证提供的 XML 文件或文本。它内部使用 ElementTree 库,并提供了解析和查找不同元素、属性、值的能力,并支持 Xpath 风格的查找。

远程测试执行

Robot Framework 也支持远程库的使用,其中测试的一部分可以作为服务器托管,并且可以被其他远程测试使用。这在将测试的一部分集中在一个地方非常有用,并且所有客户端测试都可以根据该测试本身获取信息。

它使用 XML-RPC 协议进行远程交互,并提供各种分布式测试功能,例如远程提供不同的关键字,这些关键字可以由不同的测试在远程服务器上执行某些操作。因此,远程库中的一个方法可以用来执行一些任务,这些任务可以在测试中以库关键字的形式调用,从而实现代码在不同测试中的可重用性。

要开始远程测试,在测试中只需指定远程测试的位置:

Library  Remote  http://localhost:8567

在服务器端,可以指定以下内容:

def strings_should_be_equal(self, str1, str2):
  print "Comparing '%s' to '%s'" % (str1, str2)
  if str1 != str2
    raise AssertionError("Given strings are not equal")
  else:
    return "Given Strings are not equal"
  if name == '__main__':
    from robotremoteserver import RobotRemoteServer
    RobotRemoteServer(ExampleRemoteLibrary(), *sys.argv[1:])

在这里,可以从 Python 命令行运行此文件以设置 Robot 远程服务器,并且这里定义的方法可以用作关键字,例如字符串应该相等。如果你想知道代码是否需要更多,那么你需要单独下载提供的RobotRemoteServer脚本文件并将其放置在此脚本旁边。目前,有 Python 和 Ruby 的服务器,但也可以创建其他服务器。因此,在 Robot Framework 中编写分布式测试是微不足道的,并且可以通过 HTTP 轻松使用。

摘要

本章讨论了测试的哲学和风格。由于测试应该考虑到自动化,因此涵盖了通过迭代和参数化测试用例的内部和外部重用,以及将数据引入测试的情况,因为这些是在进行自动化时需要考虑的重要事项。接下来,本章涵盖了三种不同的编写风格,包括关键字、数据和行为驱动测试,随后对行为驱动开发的重要性进行了简要讨论,并与当前流行的其他开发工具进行了比较。本章提供了 Robot Framework 库的所有剩余部分,你现在可以自信地开始编写可自动化的测试,通过框架本身提供的广泛工具和支持,为从小型企业软件系统到大型企业软件系统提供测试。为了扩展框架的功能并使其能够与各种软件一起使用,下一章将重点介绍用户库。

第四章:扩展框架

本章与所有前面的章节都略有不同,因为它侧重于提供 Robot Framework 与 Robot Framework 运行的其他软件之间交互的外部库。这对于与其他领先软件的集成是这个框架的基石。因此,我们需要了解现有的各种库,以及如果不存在任何库,如何为框架创建自定义库。

到目前为止,所有示例都只使用了内置库中的 log 函数,因为这是最容易演示框架运行时输出的方式。虽然这很容易理解,但它并没有解释在现实世界场景中验收测试应该如何工作。

在本章中,将介绍各种第三方库,这些库以多种方式扩展了 Robot Framework。简而言之,本章将涵盖以下内容:

  • 通过 Selenium 进行 Web 应用程序测试

  • 通过 REPL shell 调试基于 Selenium 的 Robot Framework 代码

  • 通过 Swing 库测试基于 Java 的桌面应用程序

  • 通过 Sikuli 介绍基于图像的自动化

  • 为 Sikuli 创建自定义 Robot Framework 库

  • 其他辅助编写验收测试的库概述

为了演示与第三方库的集成,我们最终将使用 Sikuli 工具来捕获和回放鼠标和键盘操作,并使用基于图像的计算机视觉来创建一个完整的验收测试解决方案。

测试 Web 应用程序

现在,大多数常用的软件都以网络形式存在,因为网络已成为与全球大量用户互动的通用媒介。创建基于网络的解决方案不仅越来越容易(随着新技术的发展,旧技术逐渐成熟、优化和过时),而且网络应用程序客户端的连通性、易用性和复杂性也在增加。因此,今天与世界互动的网络应用程序在开发和最终用户互动之间几乎没有可忽略的领先时间。因此,验收测试变得至关重要,因为软件的变化必须迅速得到验证,以确保在它们投入生产之前基本正确性和基本功能的存在。

Selenium

Selenium 是一个网页浏览器自动化工具,它提供了录制和回放功能。它可以用来创建简单的脚本,通过使用浏览器中的各种对象来自动化浏览器和网页上的操作。作为领先的网页浏览自动化工具,它有许多资源可用。作为浏览器运行器,各种浏览器都有 Selenium 作为插件/扩展,并且可以在浏览器内部安装。然而,在运行自定义示例时,需要一个基于 Selenium 的服务器,它存在于一个嵌入的 JAR 文件中,可以直接调用。最初,它附带了一个远程控制器,需要一个 Selenium 远程控制服务器来管理来自浏览器的浏览器请求。然而,由于简化开发需求的普遍请求,Selenium2 被创建出来,它使用 WebDriver 直接管理浏览器并执行操作,如文件上传和弹出窗口管理,直接从浏览器执行。通过使用 WebDriver,Selenium 测试可以变得更加灵活,并且可以在 Selenium 之前无法使用的浏览器中运行。

Robot Framework Selenium 库

此库在 Robot Framework 和 Selenium WebDriver 引擎之间提供了一个桥梁。通过它,可以直接从 Robot Framework 测试文件中发出各种 Selenium 命令。也存在针对 Selenium1 和 Selenium2 的单独库,根据 Selenium 的版本,可以选择合适的库。不过,无需绝望,因为 Selenium2 库在很大程度上是基于 Selenium 库的内容构建的。需要注意的是,如果 Selenium 与一个单独的服务器(一个嵌入的 Jetty 服务器)一起运行,则需要远程控制驱动器,否则 WebDriver 可以轻松选择。

要安装此库,可以使用pip,并且根据设置,可能需要 sudo/admin 权限:

pip install robotframework-selenium2library

详细文档位于rtomac.github.io/robotframework-selenium2library/doc/Selenium2Library.html,在开发这些应用程序时非常有用。

运行基于 Web 的测试

在示例中,使用基于 Python 的微框架 Flask 创建了一个小型网站,这是一个用于创建动态网站的框架。要运行示例,需要在本地 Python 设置中安装 Flask,可以按照以下方式安装:

pip install flask

安装 Flask 后,通过命令行切换到flaskApp目录,并通过运行其主控制器文件来运行演示网站:

python hello.py

这将在localhost:5000上启动 Flask,并显示以下窗口:

运行基于 Web 的测试

当输入错误的用户名/密码时,同一页面上会显示错误信息。在这里,表单的内容不会被保留,只有错误信息的出现才表明之前尝试过错误的用户名/密码组合。

以下截图显示了尝试错误用户名/密码组合时的错误:

运行基于 Web 的测试

如果登录成功,应用程序将重定向到相应的页面,该页面还提供了一条确认文本,说明登录成功,并提供了一个 URL,以便在需要再次登录时使用,如下面的截图所示:

运行基于 Web 的测试

使用 Selenium2Library

要通过 Robot Framework 执行相同任务,可以使用之前讨论过的 robotframework-selenium2 library 编写以下测试:

| Perform correct credentials | go to | ${LOGIN URL}
|  | Title Should Be | My Application
|  | Page Should Contain TextField | username
|  | Input Text | username | ${VALID USER} 
|  | Input Password | password | ${VALID PASSWD}
|  | Click Button | Login 
|  | Location Should be | ${SUCCESS URL}

此测试假设 Selenium 浏览器已经设置好。使用了一些变量,其名称非常明显。以下是测试代码的解释:

  1. 在测试用例开始时,转到指定的 URL。

  2. 断言页面标题为 My Application.

  3. 断言页面包含所需的元素。

  4. 名称文本框中输入有效的用户名。

  5. 密码文本框中输入有效的密码。

  6. 指示 Selenium 点击 提交 按钮,浏览器随后发出表单操作。

  7. 因此,浏览器被重定向到另一个页面,检查该页面的 URL。

要查看和运行此完整测试,建议查看测试代码以及查看 Selenium 库。同样,您也可以使用 page should contain 关键字来测试各个页面中的特定文本内容。

通过 REPL shell 进行调试

如果你刚开始使用 Selenium 库,你会在设置整个 Selenium 环境时遇到问题。幸运的是,有一个工具可以帮助你一次运行一个测试操作。这个工具被称为 debug-library,它是一个 REPL shell。REPL读取-评估-打印循环)就像任何其他控制台一样,只接受一行输入,并在要求输入下一行之前显示其输出。这与其他语言的 shell 非常相似。它的源代码位于:

github.com/xyb/robotframework-debuglibrary

要在运行 Python 且具有其包管理器的机器上安装此工具,请使用以下命令:

pip install robotframework-debuglibrary

或者:

easy_install robotframework-debuglibrary

安装此工具后,将可用一个命令 rfshell。您可以使用它执行基本操作和 Selenium 特定任务。以下截图显示了示例:

通过 REPL shell 进行调试

一旦在 shell 中输入 exit,它就会退出,并在用户的 home 文件夹中生成一个报告 HTML 文件。

注意

注意,此操作不会在任何地方生成日志或 XML 文件。

测试桌面应用程序

接受测试也可以在基于桌面的应用程序中实现,这使得 Robot Framework 测试不仅适用于解决某些特定问题,而且更加适用。

通过对象进行测试 – Java Swing

Swing 库是一个功能齐全的库,可用于测试基于 Java Swing 的应用程序。由于它运行在 Java 平台上,因此需要 Jython 运行时。要对 Swing 应用程序进行验收测试,classpath中需要两个东西:

  • Swing 库 JAR

  • 实际捆绑为 JAR 的 Swing 应用程序

在拥有必要的文件后,可以使用测试。可以在 Jython 命令之前设置 classpath,或者像以下示例那样将其作为命令的前缀:

CLASSPATH=swinglibrary-1.6.0.jar:myApp.jar jybot testsuites

在这里,swinglibrary的版本是 1.6.0,而系统测试捆绑为myApp.jar,Robot Framework 文件位于testsuites文件夹中。然后,应用程序对 Robot Framework 测试文件可见,可以通过其完全打包的 Java Swing 名称访问。测试脚本的设置表需要加载swinglibrary,以便提供所有 Swing 库特定的关键字。

一个 Swing 测试

给定以下应用程序,测试将涵盖向给定的待办事项列表添加和删除项目:

一个 Swing 测试

仅通过查看此 Swing 应用程序,无法区分所讨论的是哪个文本字段、表格或任何其他 UI 元素,因此在这种情况下黑盒测试不会成功,我们需要一些内部信息,例如各种组件名称来与之交互。这可能会让人联想到 Selenium,因为这两个库都提供基于对象的测试,测试本身需要了解被测系统的内部结构。

下面的测试是覆盖此 UI 提供的各种用例所需的:

| Start test | Start Application | fully qualified name of theapplication
|  | Select Window | Todo List
|  | Button Should Be Enabled | Add Todo item
|  | Type Into Text Field | description | Get this swingapplication tested.
|  | Push Button | Add Todo item
|  | ${itemCount}= | Get List Item Count | todolist
|  | Should Be Equal As Integers | 1 | ${itemCount}

这可以简要解释如下:

  • 使用 Java 应用程序的完全限定名称(即包和类名)通过Start Application关键字运行 Java 应用程序,这是从 JAR 文件运行应用程序所需的

  • 选择正确的窗口,这也确保了应用程序具有所需的窗口

  • 检查其他基本假设,例如各种元素的状态

  • 通过直观命名的关键字执行各种 UI 操作

  • 在输入文本并点击添加待办事项按钮后,todolist的大小应该增加

类似地,可以执行其他 UI 操作。像其他外部库一样,在编写测试时旁边有它的库文档是有帮助的。

通过图像进行测试

本节涵盖基于图像的测试,这与迄今为止所涵盖的内容不同。在基于图像的测试中,用户界面被视为黑盒,不暴露应用程序的对象内部结构。

Sikuli

Sikuli 是一个领先的通过计算机视觉进行自动化的工具,即识别屏幕上的图像。作为人类,我们可以通过观察来区分一个对象的属性,但在计算机的情况下并不简单,因为计算机只能匹配二进制或文本信息。因此,需要计算机视觉或知道给定的图像是否出现在更大的屏幕上。简单来说,Sikuli 使用用户提供的截图图像来执行对各种项目的操作,并在 Sikuli IDE 中以可视化的方式显示生成的脚本。以下是一个进行搜索的脚本示例:

Sikuli

如图像所示,脚本执行以下操作:

  • 检查屏幕上是否存在 Chrome 浏览器图标

  • 点击 Chrome 浏览器以打开它

  • 等待浏览器窗口打开并显示 URL

  • 在 URL 栏中转到google.com,这将打开 Google 首页

  • 等待 Google 搜索按钮出现

  • 在适当的文本字段中执行所需的查询

  • 验证获得的结果

  • Sikuli 页面应出现在结果的第一页

然而,在幕后,以下 Python 脚本在保存此 Sikuli 脚本的文件夹中生成:

exists("1377428833316.png")
click("1377428844996.png")
wait("1377428859228.png")
type("1377428922965.png", 'google.com')
wait("1377428949234.png")
type("1377429289183.png", 'sikuli test automation')
exists("1377429031446.png")

除了这个 Python 脚本(或其 HTML 等价物)之外,测试中还引用了各种图像。重要的是,在运行时,Sikuli 在其核心运行计算机视觉软件,以确定屏幕上是否存在与图像匹配的内容,并据此采取行动。完全没有必要了解正在测试的软件的内部结构。虽然一开始这可能看起来有些反直觉,但通过基于图像的测试来弥补对组件和对象的控制不足,从而将测试从测试系统中解放出来,因此测试可以在各种软件平台上运行,从不同的桌面应用程序、移动模拟器、主机终端、基于 Web 的应用程序和远程应用程序,只需将屏幕上显示的内容作为其输入和决策能力的依据,就像进行手动自动化验收测试的人类一样。

创建自定义 Sikuli 库

一开始,Robot Framework 看起来像是一个复杂的框架,而创建外部用户库似乎是一项繁琐的任务。然而,有时需求会要求为这种需求提供验收测试解决方案。幸运的是,像 Sikuli 这样的开源解决方案有一个可扩展的应用平台,并且文档也非常完善。Sikuli 与 Robot Framework 的定制集成是由Mykhailo Moroz创建并展示的(blog.mykhailo.com/2011/02/how-to-sikuli-and-robot-framework.html)。该方法中使用的策略将在下一节中讨论。

为了将 Sikuli 作为测试验证引擎使用,必须首先公开其 API (doc.sikuli.org/javadoc),这可以通过使用 Sikuli 内部使用的 Python 类的巧妙技巧来完成。由于这将工作在 Jython 环境中,因此需要在类路径中包含 sikuli-script.jar 并创建一个围绕 Sikuli API 的包装器,以便使用各种方法。Sikuli API 包含一个具有各种方法的 Screen 类。

要使这些方法在 Screen 类中全局可用,这些方法被手动推入内部全局目录,并由自定义的单独方法覆盖:

def sikuli_method(name, *args, **kwargs):

    return sys.modules['sikuli.Sikuli'].__dict__name

此查找随后用于将自定义方法中的值传递到 Sikuli 引擎内部存在的本地代码。例如,click 方法可以如下实现:

def click(target, modifiers=0):

    try:

        return sikuli_method('click', target, modifiers)

    except FindFailed, e:

        raise e

此包装器允许创建简单的 Python 脚本,这些脚本可以在 Jython 环境中运行,而无需 Sikuli X 测试运行器。由于类路径中已经存在 sikuli-script.jar,因此创建的测试可以在没有 Sikuli IDE 或在无头模式下运行。

由于这些脚本可以在 Jython 环境中独立运行,因此可以通过 Jybot 运行它们,Jybot 可以使用各种 Robot Framework 脚本调用这些脚本函数。这创建了一个解决方案,通过收集不同的小型脚本执行大量任务,以这种方式驱动多个 Sikuli 脚本作为测试用例:

要运行此示例,我们需要以下先决条件:

  • Robot Framework 正确安装,并带有 Jython 运行时

  • Sikuli 已正确安装,并且 sikuli-home 环境变量指向其根文件夹

批处理文件中的以下命令通过设置所有涉及软件所需的环境来运行应用程序:

set sikuli_jar=%sikuli_home%sikuli-script.jar
set CLASSPATH=%sikuli_jar%
set JYTHONPATH=%sikuli_jar%/Lib
call jybot --pythonpath=TestLib ^
      --outputdir=results ^
      --loglevel=TRACE ^
      --output "%~d0%~p0results\output.xml" ^
      --log "%~d0%~p0results\log.html" ^
      --report "%~d0%~p0results\report.html" ^
      testsuite

由于我们使用不同的 Sikuli 脚本作为不同的测试用例,因此我们将这些脚本作为自定义测试导入我们的 Robot Framework 测试文件中,这些文件保存在 testlib 文件夹中,以使示例中的事情保持简单:

***Settings***
Library  TestAction1.XTest  WITH NAME  TestAction1
Library  2ndcase1staction.XTest  WITH NAME  2ndcase1staction
Library  anotheraction.XTest  WITH NAME  anotheraction
***Test Cases***
Test Case 1
  TestAction1.Execute
Test Case 2
  2ndcase1staction.Execute
  anotheraction.Execute

实际上,library 文件是一个用 Python 编写的自定义 Sikuli 脚本,它调用 Sikuli API 以作为无头 Sikuli 实例运行:

from __future__ import with_statement
from sikuliwrapper import *
addImagePath(common.cfgImageLibrary) #uses the values supplied by the robot framework.
Settings.MinSimilarity = 0.9  # Image present on the screen should match 90% or more than the provided image.

class XTest(BaseLogger):
    ROBOT_LIBRARY_SCOPE = 'TEST SUITE'

    def __init__(self):
        None
    def Execute(self, *args):
        type("this is a reference test example")
        wait(0.485)
        ...

要使这些测试基于图像,你可以调用 clickvalidatetype 等函数,并将用于输入参数的样本图像文件的路径作为其输入参数:

除了 testlibrary 文件外,还有一个 sikuliwrapper.py 文件,它将这些 Sikuli 方法提供到库文件调用中:

from logger import *
from sikuli.Sikuli import Region as SikuliRegion
from sikuli.Sikuli import Screen as SikuliScreen
log = RobotLogger()
class VerifyException(RuntimeError):
    ROBOT_CONTINUE_ON_FAILURE = True
# function for calling native sikuli methods
def sikuli_method(name, *args, **kwargs):
    return sys.modules['sikuli.Sikuli'].__dict__name

# overwritten Screen.exists method
def exists(target, timeout=0):
    addFoundImage(getFilename(target))
    return sikuli_method('exists', target, float(timeout))
…

类似地,其他 Sikuli API 调用也可以被包装起来,为库文件提供一个易于使用的接口,反过来,库文件又被 Robot Framework 测试调用:

然而,在基于图像的测试中,失败应该是有描述性的。为此,可以在失败或成功发生的实例时截取屏幕截图,这需要你创建一个自定义记录器:

import logging
import datetime
import shutil
from sikuli.Sikuli import *

# Properly set the logging mechanism
logging.addLevelName(logging.WARNING, 'WARN')
HTML = logging.INFO + 5
logging.addLevelName(HTML, 'HTML')

class RobotLogger(logging.Logger):
    def __init__(self, name='robot', level=logging.INFO):
        level = logging.DEBUG
        logging.Logger.__init__(self, name, level)
        self.addHandler(RobotHandler())

    def _get_unique_name(self, prefix="", suffix=""):
        now = datetime.datetime.now()
        return prefix + now.strftime('%Y-%m-%d_%H-%M-%S') + suffix

    def screenshot(self, msg='', folder='results/screenshots/', region=(0,0,1440,900)):
        name = self._get_unique_name(suffix=".png")
        img_src = capture(*region)    # Actual call to capture the entire screen
        shutil.copy(img_src, folder + name)
        self.html_img(msg, folder + name)

    def passed(self, msg, *args, **kwargs):
        self.info('PASS: ' + msg, *args, **kwargs)

    def failed(self, msg, *args, **kwargs):
        if self.isEnabledFor(logging.DEBUG):
            if len(getLastFoundImages()) != 0:
                self.html_img("Source Image",  'images/' + getLastFoundImage())
            self.screenshot()
        raise common.VerificationFailed(msg)

    def html(self, msg, *args, **kwargs):
        self.log(HTML, msg, *args, **kwargs)

    def html_img(self, msg, image):
        self.html('%s <img src="img/%s" />' % (msg, image))
…

这些是运行和记录基于 Sikuli 的应用程序所需的必要文件,可以轻松地使用 Robot Framework。输出可以在以下示例中查看,通过打开记事本并运行应用程序:

创建自定义 Sikuli 库

其他值得注意的库

存在着许多其他库,它们扩展了 Robot Framework 在通常不被视为验收测试候选区域的功能。如果以正确的方式进行,这些库将受益于测试自动化。以下是一些这些库的例子。

测试网络协议

Rambock 是一个测试库,它提供了一种简单的方式来测试各种网络数据包、协议和消息模板:

Robotframework Rammbock 库

它允许你指定自定义协议、其客户端和服务器;消息,以及传统和自定义协议都可以进行测试。

测试网络服务

Suds 是一个轻量级但动态的 SOAP Python 客户端,用于消费网络服务:

Robotframework Suds 库

测试数据库

可以通过 robotframework-databaselibrary 测试数据库的持久性和内容。在这里,数据库被查询以找出其状态并执行一些操作,例如运行 SQL 脚本:

Robotframework 数据库库

存在着一个类似的库,用于通过 JDBC 进行交互,这对于不支持测试的数据库来说特别有用:

Robotframework 数据库库

摘要

在本章中,讨论了许多外部工具和库,它们扩展了 Robot Framework 的功能。首先,通过 Selenium 和其方便的 REPL shell 展示了网络应用程序测试,该 shell 用于调试应用程序。接下来,通过使用基于对象的测试展示了基于 Java 的桌面应用程序测试。解释了 Sikuli 应用程序和基于图像的测试,以及一个深入案例研究,该研究进一步探讨了其 API 的可扩展性,以创建一个对 Robot Framework 友好的解决方案。最后,列出了一些其他流行的库。

在下一章中,我们将探讨测试报告操作,以了解生成的不同输出以及如何使用生成的报告执行各种所需的操作,并自定义测试输出。

第五章:生成报告

虽然创建和执行测试确实提供了许多好处,但有必要有效地传达测试结果给任何测试的观看者,因为验收测试可以提供给定软件可以以提供的方式执行的事实,但不能保留这个假设。在本章中,将详细讨论 Robot Framework 中的测试报告概念,这包括通过提供的选项理解和自定义生成的报告,包括手动和自动更改。由于报告内部讨论得非常详细,因此可以更有信心地进行报告定制。

报告的需求

除了在用户显示结果的控制台上出现的事件和动作之外,还需要在测试执行过程中创建测试报告文件,因为它提供了许多好处,其中一些将在以下内容中概述:

快速测试运行评估

如果有一个标准化的格式可以清楚地识别测试的成功或失败,以及轻松确定单个测试的详细信息,则可以快速查看测试结果。

结果比较

可以对同一验收测试的结果进行并排比较,这些结果可以在同一测试的不同状态、不同外部变量或不同时间进行测试。

单个结果详细说明

测试报告可以以有序的方式详细说明环境、测试执行步骤和其他数据,这对于确定测试执行的成功至关重要。

智能评估

通过使用报告和日志,人们分析测试执行变得容易得多。当涉及到自动化测试时,这非常有用,因为测试运行后分析失败的原因可能会很繁琐。填充的数据也可以用来获取必要的指标以及推断次要数据,例如测试在一段时间内的性能,以及根据需要推断其他细节。

生成的文件

如前所述,Robot Framework 生成两个 HTML 文件,即日志和报告文件。它们是互补的,在分析任何项目时,你会发现自己正在使用这两个文件。除了这些文件之外,默认情况下还会生成一个 XML 文件,其中包含所有测试结果输出的元数据。这在许多方面都有帮助,这些帮助在本章中进行了详细讨论。

日志文件以分层的方式呈现详细的执行报告,基于不同的测试套件。它还包括测试统计信息,但测试的高级概述在报告文件中。报告以多种方式呈现结果,以下章节将详细说明。

输出结构

测试报告包含以下标题下测试执行的结果,以下将进行解释。

标题

标题是页面上的第一个元素,包含测试名称和生成时间。它还显示自生成以来的经过时间。

摘要信息

这包含测试摘要、测试的开始和结束时间以及测试执行的总时间。

测试统计信息

这些是在测试中存在的测试数量;各种测试根据其关键性、标签和套件进行分组。默认情况下,所有测试都是关键的,但您可以通过在 pybot/jybot 命令中传递--critical--noncritical后跟测试名称来明确指定测试是否关键。

测试详细信息

测试详细信息仅在测试报告中存在,包含与测试统计信息中相同的上述信息;然而,它们提供了一个更简洁的视图,因为不同的统计数据以表格形式呈现。在此列下方是空白空间,但只要您单击任何测试套件,就会显示包含与该套件及其子套件相关的各种属性的详细表格,并且测试详细信息显示与套件相关的信息。

测试执行日志

这仅在日志文件中存在,包含从测试生成的所有日志。要查看测试套件层次结构,请单击展开全部按钮以查看测试中存在的所有测试套件层次结构。它包含套件源文件和文件夹的位置,以及测试中关键字的信息。

测试着色信息

在任何 xUnit 测试结果中,红色表示失败,绿色表示成功。这种着色也导致了单元测试中流行的 TDD 咒语“红、绿、重构”,这表示开发顺序是首先创建测试,目的是自然失败,然后编写代码,使测试通过,最后以不破坏任何内容的方式重构现有代码。

以下截图展示了通过测试的应用程序,绿色背景清晰可见:

测试着色信息

同样,测试套件的失败也可以通过背景颜色反映出来。请注意,即使单个测试用例失败,整个报告也将显示失败的颜色,最终用户可以轻松地注意到,如下面的截图所示:

测试着色信息

这种约定在 Robot Framework 中也被遵循,正如报告背景颜色以及日志文件中执行测试所使用的颜色所示。

分离文件

生成的报告通常在每次执行时都会被覆盖。然而,可以通过提供唯一名称来使每次运行都独特,可以通过使用带时间戳的文件名来提供这个唯一名称。为了做到这一点,可以将pybot/jybot/ipybot命令与参数一起使用,这些参数会在文件名和扩展名之间插入时间戳,确保文件名的唯一性并确保不会发生文件覆盖。为此,需要将这些命令添加--timestampoutputs参数。这将在生成的报告文件名和扩展名之间插入时间戳,格式为YYYYMMDD-hhmmss

例如,这可以用来指定带时间戳的文件:

pybot --timestampoutputs -o metadata -l log -r report testsuites

修改输出

在生成的报告和日志文件中可以做出某些自定义设置,这些设置可以在 Robot Framework 中直接使用。这有助于根据要求设置测试报告,而无需更改报告结构,也不会以任何方式影响代码库。

自定义报告标题

--logtitle--reporttitle参数可以在日志文件和报告文件名称之前使用,分别设置它们的自定义标题;否则,在必要时使用测试日志或测试报告的默认值。

注意

当通过参数使用自定义名称时,下划线会被转换为空格,就像测试套件文件和文件夹名称一样。

为了不允许文件有标准的<root test suite> Test Report/Log标题,可以使用以下选项:

pybot --logtitle info_log -l log --reporttitle Tests_at_a_glance -r report testsuites

背景颜色自定义

报告中使用的颜色方案不需要更改,因为它确认了 xUnit 配置中使用的颜色,以及大多数其他测试/测试工具中使用的颜色。然而,在某些情况下,这可能不如其他替代方案好,例如,色盲人士可能难以区分默认颜色;这可能与品牌中使用的颜色形成对比,等等。要指定颜色,提供了--reportbackground successcolor:failurecolor选项,其中颜色名称可以原样提供,如红色、蓝色、黄色,或者通过提供颜色十六进制代码如#05AE04。

改变日志记录的多少

测试中进行的日志记录也可以自定义,这有助于在测试日志中允许包含各种元素和信息类型。可以分配各种日志级别,以便在不同场景下打印消息。然而,某些消息(例如 FAIL)仅由 Robot Framework 本身发出,这种情况仅发生在某些测试关键字缺失时。其他消息(如 Warn、Info、Debug 和 Trace)也可以用于不同重要性的问题,这与大多数流行的日志框架操作方式相似。

此外,可以通过在 Python 程序中使用日志 API 来自定义日志记录,其中可以使用robot.api.logger以及标准的 Python 日志记录。

使用--loglevel参数来指定生成日志文件的各种日志级别。如果这样做是在 info 级别以下,那么在日志文件中的报告链接下方将出现一个下拉菜单,如下面的图片所示:

更改日志记录量

更改报告格式

有时需要对生成的报告进行细微的修改,这可以通过自定义输出文件的 CSS 或修改下载的源代码并重新构建框架的定制安装来完成。在本节中,将讨论这两种定制策略。

如果在文本编辑器中打开日志文件,它将显示文件中内联使用的 CSS。同样,报告中也包含内联的 jQuery。通过这种方式,文件可以在不依赖外部文件或网站的情况下使用,并且报告可以在任何现代浏览器中运行。

这些文件可以根据用户的需求自由使用,但唯一需要注意的是,如果报告不是唯一生成的,那么 Robot Framework 的后续执行将覆盖报告/日志文件。

要进行定制,让我们使用之前生成的报告,其中测试已经完成。由于此报告已经生成,因此无法进行定制。因此,在文本编辑器中加载报告后,跳转到包含显示在页面右上角的内容的 JavaScript 函数所在的第 1247 行,如下所示:

function addHeader() { 
….
           '<div id="top-right-header">' + 
             '<div id="report-or-log-link"><a href="#"></a></div>' +
           '</div>', { 
        generated: window.output.generatedTimestamp,
….

此函数将加载已过的时间以及指向其他(日志/报告)文件的链接。在这里,可以在包含作为我们图标的图像的report-or-log-link div 之后立即添加另一个 div。因此,在同一函数内部更改的 div 结构变为:

...
           '<div id="top-right-header">' + 
             '<div id="report-or-log-link"><a href="#"></a></div>' + 
             '<div id="my_custom_image"><img src="img/github-icon.jpg" /></div>'+ 
           '</div>', { 
        generated: window.output.generatedTimestamp, 
  ….

此代码将负责报告中的图标存在。然而,由于这是一个外部图像,其路径必须正确解析到报告中。因此,如果报告需要在不同的计算机之间发送或与报告一起打包以供离线使用,也可以使用基于 Web 的图像 URL。

同样,如果需要在发送报告给经理或利益相关者之前更改报告的颜色,并且该人偏好特定的颜色,那么报告可以进一步调整。在第 1472 行,有一个 JavaScript 函数设置报告颜色:

function setBackground(topsuite) { 
    var color; 
    if (topsuite.criticalFailed) 
        color = window.settings.background.fail; 
    else if (topsuite.totalFailed) 
        color = window.settings.background.nonCriticalFail; 
    else 
        color = window.settings.background.pass; 
    $('body').css('background-color', color); 
}

在使用硬编码的值更改此函数之前,可以操作使用的颜色。因此,可以通过对函数进行以下更改来简单地设置背景颜色为白色:

function setBackground(topsuite) { 
    var color = 'White'; 
    $('body').css('background-color', color); 
}

更改报告格式

在进行前两个更改之后,只需刷新页面即可查看更改,包括在日志链接下方出现图标以及将背景更改为白色。

在快速调整生成的报告时,这会非常方便,但因为这个过程是手动的,所以像这样更改报告变成了一件麻烦事,尤其是如果报告数量很多或经常被覆盖。

为了解决这个限制,可以使用自定义构建的 Robot Framework。假设你有权访问整个 Robot Framework 仓库,可以操作 src/robot/htmldata 文件夹中的文件,将这些自定义更改发送到框架本身;安装 Robot Framework 后,这些更改将变得永久,并应用于从 Robot Framework 生成的每个报告。

创建派生报告

除了日志和报告文件外,每次测试执行都会生成一个 XML 文件作为输出,有时可能需要使用这些文件作为进一步分析测试的基础,例如对软件片段进行时间分析。XML 文件可以根据自定义要求进行解析和分析。在 Python 中,使用内置的 elementtree 库处理 XML 非常容易,不同的 XML 元素可以作为树进行遍历,并且可以在它们上执行不同的操作。

重新创建报告

如前所述,Robot Framework 提供了一个工具,通过使用 rebot 工具从生成的元数据中重新创建测试输出文件。此工具支持在 第一章 中提到的 pybot 命令的所有参数,即 使用 Robot Framework 入门,并且仅使用生成的 XML 文件作为输出。如果其他文件不存在或仅以 XML 格式存储大量测试结果时,这会非常方便。然而,rebot 的最重要特性在于将多个 XML 文件合并成一个单独的测试,这在你在不同环境中运行了相同的验收测试并希望将结果呈现为单个文件时非常有用。

假设你在文件夹中有来自不同状态(如 state0.xml、state1.xml、state2.xml 等)的测试结果文件,然后你可以通过使用以下方法简单地使用自定义命名的顶级测试套件重新创建一个单独的测试结果:

rebot --name Country_Results state/*.xml

查看差异

有时,你有多份测试结果,并想比较它们之间的差异。为此,一个名为 robotdiff 的 diff 工具提供了测试用例之间的比较。这个工具位于 robotframework 源代码的 tools/robotdiff 文件夹中。要生成比较,请执行以下操作:

python robotdiff.py output1.xml output2.xml output-n.xml

默认生成的报告是用户主目录中的 robotdiff.html,结果标题为 "Test Run Diff Report",每个测试名称都来自 XML 文件名。

进一步使用结果

由于生成的元数据结果文件是 xUnit 兼容的 XML 格式,它可以作为外部工具的输入,这些工具理解这种格式。一个这样的例子是 Jenkins 插件(wiki.jenkins-ci.org/display/JENKINS/Robot+Framework+Plugin),它支持基于这些文件生成统计信息。

摘要

本章介绍了测试执行生成的内容的输出定制,因为测试产生的数据和结果可以被重用和重新分析。详细说明了测试输出中使用的不同文件及其格式,以便进行修改。解释了修改单个报告的不同方法,以及如何根据组织的需求生成报告。还提到了如何修改框架和使用程序生成自定义报告的进一步指导,以及报告生成和测试报告的使用。

posted @ 2025-09-23 21:56  绝不原创的飞龙  阅读(5)  评论(0)    收藏  举报