最近,我更改了项目-我进入了一个新的开发阶段,在此之前,我没有进行过手动或自动测试。 客户没有对工具箱施加条件(除了它是Python),所以我做出了自己的选择。 在本文中,我将解释为什么在这种情况下我选择了Robot Framework。 最后,将为本文专门编写一些示例,以说明我们在说什么。

我从事自动化测试已有10多年了,其中约有三人与机器人框架进行了交互。
如上所述,不久前,我来到一个新项目,在那里我从头开始测试自动化。 关于该项目-NDA,我无法告诉您。 我只注意到这是一个很酷的自动化工具,将来应该会节省大量的人力资源。 它是从微服务构建的。 到目前为止,我的工作涉及其中四个,但是将来我会将自己的活动扩展到其他人,这全都归结为我每天只有8个工作小时的事实。 一切都需要时间。
在此项目中缺少测试与缺少推荐工具相同。 作为Python堆栈的一部分,我可以自由选择。 我利用了它。
为什么选择机器人框架?
我认为我可以归功于机器人框架的支持者。 在我看来,几乎所有内容都可以完成。
在其他项目上,该公司使用pytest。 但是,我认为它不具有这种功能,因为它受到Python功能的限制。 您只需要编写Python代码,并注意在这样的变量中需要一定的值即可。 就我的口味而言,它很简单,但是太抽象了。 开发人员还有很多工作要做,他们必须手动添加所有有用的功能。 机器人框架自己完成。 这里有四点值得您重视的项目。
柔韧性
机器人框架本身是用Python编写的(即Python可以做的所有事情),为此,社区创建了许多库,极大地扩展了要解决的问题的范围。
在机器人框架下,您可以轻松地编写自己的库,将其与几乎所有内容集成在一起,并且一切都将立即生效。 不需要拐杖或自行车。
此外,Robot Framework允许您编写参数测试(模板),从而极大地加快了自动化工具的工作。
测试中的俄语
基本要点之一是,可以用俄语编写关键字(由于某种原因在过去一直以这种方式称呼机器人框架中的传统方法,类似关键字)。 结果,测试文本当然与文学语言相去甚远,但是乍一看就清楚那里发生了什么。 首先,最终开发人员并不需要,例如,利益相关者。 他们可以独立打开测试并查看实际发生的情况:“从...中选择随机元素”,等等。
标记
机器人框架与标签配合良好。 您不仅可以运行带有特定标签的测试,还可以在其帮助下分析报告。 日志文件包含有关标签的统计信息,如果您事先考虑标签的排列,则可以基于该统计信息采取一些措施。
方便地,您无需在每次测试中都将所有标签写在一条长长的鞋垫上,但是您可以将测试嵌入树状结构中。 就我而言,它看起来像这样:第一个级别是微服务,第二个级别是测试的类型,第三个级别是测试本身(放置包含用于嵌入其中的标签的init文件很方便)。
我为每种微服务,每种测试方法(烟雾测试,CRUD测试,集成等)创建了一个标签。 我可以运行特定类型或仅针对特定服务的测试。 我还标记功能的类型-列表或详细。 如果负责该列表的产品在产品中“中断”,则带有此标签的所有测试都将变为红色,无论它们位于何处以及与之相关。
通过标签,我将自动测试绑定到Jira。 当跟踪器的错误关闭并且红色的测试变为绿色时,我们仍然拥有确切更改的历史记录。 许多月后,如果测试再次变红,我们可以看到上次已采取了哪些措施来解决该问题,甚至可以假设导致重复播放该错误。
我为非关键错误添加了另一个特殊标签。 如果至少有一个测试崩溃,则GitLab不允许我们对程序集执行任何操作。 这是合乎逻辑的-在修复所有错误之前,我们无法发布产品,甚至无法发布每周冲刺。 但是,我们的优先级较低且漏洞不多。 对于他们,我选择了一个标签,该标签允许Robot Framework不会删除整个程序集,除非这些测试(带有此标签的测试)明确失败。
很棒的日志
日志分析是测试不可或缺的一部分。 无论运行测试时发生什么情况,Robot Framework绝对可以编写所有内容。 到目前为止,我不得不编写一个特殊的包装程序,该包装程序从日志中隐藏了登录名和密码以连接到数据库。
这样的细节有助于更快地了解测试崩溃的原因-被测系统是否正常工作,或者测试中没有考虑到某些东西并且需要对其进行修复? 这个问题的答案并不总是很明显。 开发人员和测试人员的错误分配为50/50。
在其他工具(在同一pytest中)中,您可以创建相同的详细日志。 但是,生成测试的任务在于编写测试的开发人员。 他需要考虑真正需要哪种日志条目。
现在项目上有什么
从我开始使用机器人框架的那一刻起,已经过去了几个月。 目前,Robot Framework已经实现了200多个测试,并且如上所述,它与GitLab集成在一起,可以帮助检查对开发产品所做的更改(带有标识符的测试用例可以将自动测试绑定到它们的测试用例存储在testrail中)。
为了计算覆盖率,我编写了一个实用程序,该实用程序获取Swagger的后端API列表并将其与经过测试的内容进行比较。 因此,我们对当前的覆盖范围有了清晰的了解。 例如,我们知道今天微服务已全部覆盖,而其他微服务已覆盖98%。 在添加了尚未反映在测试中的新功能之后,覆盖率下降了。 因此,您可以计划由我实施下一个冲刺。
当然,该项目正在进一步发展。 例如,现在我们正在部署一个模拟服务器(
我的同事已经在Habré上写了关于它是什么以及为什么需要它的信息)。
现在练习
以上示例是专为本文设计的,用于说明上述思想。 如果您想亲自尝试这些示例,它们都将发布
在我们的资源库中 。
最简单的测试示例
让我们从对机器人框架的最简单的测试开始。
在下面的示例中,首先创建到某个显然可访问的资源的会话(在我们的示例中为
en.wikipedia.org/wiki )。 通过调用获取根目录(/),我们检查状态码200。
*** Settings *** Documentation smoke-. Library RequestsLibrary *** Variables *** ${base_url} https://en.wikipedia.org/wiki ${url} / *** Test Cases *** Wiki Create session conn ${base_url} disable_warnings=1 ${response} Get request conn ${url} Delete all sessions Should be equal ${response.status_code} ${200}
模板(参数)测试
Robot Framework允许您创建测试模式。 如果将测试从前面的示例转移到模板视图,则可以通过添加带有必要参数的调用来轻松扩展它。 例如,让我们检查答案200是否包含有科学家传记的页面。
*** Settings *** Documentation smoke-. . ... . Library RequestsLibrary Test Setup Test Teardown Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases *** /Isaac_Newton /Albert_Einstein /Stephen_Hawking *** Keywords *** Create session conn ${base_url} disable_warnings=1 Delete all sessions Smoke- [Arguments] ${url} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200}
标记和读取日志
我们将继续改进最简单的测试。
将模板作为单个切入点,我们可以轻松地添加对科学家出生年份的验证。 这样,我们确认加载的页面显示正确的数据。
另外,在下面的示例中,我以俄语名称包装了现有关键字-根据我的口味,因此测试可以更自然地阅读。 作为一名测试人员,我总是被称为“仿佛是英语”的方法所困扰,但完全是文盲。 用您所知道的语言写总是更好。
*** Settings *** Documentation smoke-. . ... . ... . ... . Library RequestsLibrary Test Setup Test Teardown Test Template Smoke- *** Variables *** ${base_url} https://en.wikipedia.org/wiki *** Test Cases *** [Tags] Newton /Isaac_Newton 1642 [Tags] Einstein /Albert_Einstein 1879 [Tags] Hawking /Stephen_Hawking 1942 ( ) [Tags] Numbers /123456789 1899 *** Keywords *** Create session conn ${base_url} disable_warnings=1 Delete all sessions Smoke- [Arguments] ${url} ${expected_word} ${response} Get request conn ${url} Should be equal ${response.status_code} ${200} ... msg= GET ${url} , 200 . ${response.text} ${expected_word} [Arguments] ${text} ${expected_word} Should contain ${text} ${expected_word} msg= ${expected_word}!
注意
[Tags]
。 您可以在此处添加标签,正如我在上文所述,这些标签将有助于评估报告级别的问题。 同样,通过__init __。Robot文件中的“
Force Tags
”(请参见
我们的存储库中的示例),您可以为目录中的所有测试(包括嵌套测试)设置标签。 如果正确执行了标记,甚至没有读取测试本身的名称,也没有深入了解其逻辑,我们可以相当准确地假定它在测试项目中不起作用。
查看有关这些测试启动的报告。 为了清楚起见,我添加了一个将发现错误的测试。
报告统计是其最重要的部分。

在我们的示例中,带有
numbers
标签的测试未完全通过(我们有1分之1,但在现实生活中,例如20分之17)。 可以假设问题出在此页面中。
标签有助于有选择地运行测试。 要在启动行中运行带有特定标记的所有测试,必须指定:
--include <tag>
甚至支持带有标签的逻辑操作:
-- include <tag>AND<tag>
例如,如果您只想对带有数字标签的测试运行冒烟测试,则应添加:
--include smokeANDnumbers
非关键测试
让我们继续进行一些可以大大简化工作的技巧。
用标签标记测试后,您可以将其中一个或多个定义为“非关键”标签。 带有此类标签的测试仍将显示错误(如果有),但是最后,这些错误将不会被解释为“无效”。 当考虑到一些较小的错误,将它们输入到错误跟踪器中但尚未修复时,我将使用此选项。 没有它,CI中包含的自动测试在检测到此类已知问题后将无法组装项目,这并不总是很方便。
添加一个新测试:
( ) [Tags] Letters Known /abcdefghi 1799
在启动时,使用以下键将添加的标签定义为“非关键”:
--noncritical Known
python中的关键字
在下面的示例中,我将说明如何添加我的库。
创建一个新的关键字“生成数字数组”。 它的目的很明显(为此,我喜欢俄语名称)。
from random import randint from typing import List from robot.api.deco import keyword class ArrayGeneratorLibrary: ROBOT_LIBRARY_SCOPE = 'GLOBAL' @keyword(" ") def generate_array(self, length: int, minimal: int, maximal: int) -> List[int]: result = [] for i in range(int(length)): result.append(randint(int(minimal), int(maximal))) return result
我们在测试中连接库:
Library libraries.ArrayGeneratorLibrary
并使用它:
, python. ${array} ${5} ${2} ${8} Log to console ${array}
不要忘记,如果您有嵌套结构,则应使用点将其分隔,如示例中所示。
另一个技巧:
${}
中传递的数字被视为int,而不是字符串!
内联参数
另一个不错的事情是内置参数,它不像通常那样在调用结束时传递,而是直接传递到他的体内。
为了说明这一点,我们将为上面创建的数组生成器编写一个包装器,该包装器允许使用内置参数:
${n} , ${from} ${to} ${result} ${n} ${from} ${to} [Return] ${result}
现在您可以这样写:
. ${array} 5 , 2 8 Log to console ${array}
替换部分方法名称,python插入和循环
我真正喜欢机器人框架的下一个技巧是替换名称的一部分。 假设我们有两种方法:一种选择偶数,另一种选择奇数。
[Arguments] ${list} ${evens} Evaluate [i for i in $list if i % 2 == 0] [Return] ${evens} [Arguments] ${list} ${odds} Evaluate [i for i in $list if i % 2 != 0] [Return] ${odds}
上面使用的关键字
Evaluate
允许您“在这里”执行一行python代码。 请注意,如果您不想用变量的内容替换字符串的一部分,即传递一个链接,则应在
$
符号后立即使用不带大括号的变量名!
因此,您可以调用这两种方法,替换其名称的不同部分:
, . . ${types} Create list ${array} 5 , 12 28 FOR ${type} IN @{types} ${numbers} Run keyword ${type} ${array} log to console ${numbers} END
方法装饰器
是的,Robot Framework允许您为其他关键字编写修饰符!
为了说明此功能,我们编写了一个装饰器,该装饰器在任何返回列表的方法的响应中选择负数。
, [Arguments] ${keyword} @{args} &{kwargs} ${list} Run keyword ${keyword} @{args} &{kwargs} ${negs} Evaluate [i for i in $list if i < 0] [Return] ${negs}
请注意:
@{args}
都是未命名的参数;
&{kwargs}
都是命名参数。
有了这个束,您可以重定向它们,实际上创建一个装饰器。
使用装饰器将如下所示:
${negs} , 10 -5 5 log to console ${negs}
而不是结论
在上面的示例中,我展示了Robot Framework的主要功能,这些功能使工作变得更加轻松。 但是他的筹码不限于此。
如有任何疑问,请在评论中写。 我们将选出阅读兴趣的主要方向,并在全文中回答这些问题。
文章的作者:弗拉基米尔·瓦西亚夫
PS:我们在Runet的多个站点上发表文章。 订阅我们在
VK ,
FB或
Telegram频道上的页面,以查找有关我们所有出版物和其他Maxilect新闻的信息。