如何使用RobotFramework编写好的测试用例
- 概述
- 命名
- 测试套件命名
- 测试用例命名
- 关键字命名
- setup和teardown的命名
- 文档
- 测试套件文档
- 测试用例文档
- 用户关键字文档
- 测试套件结构
- 测试用例结构
- 工作流测试
- 数据驱动测试
- 用户关键字
- 变量
- 变量的命名
- 传参和返回值
- 避免使用Sleep关键字
- 我们AT中的一些约定
概述
- 这篇文档是使用Robot Framework编写好的测试用例的高级纲要,至于如何实际和被测系统(SUT)交互超出了本文档的范围。
- 最重要的大纲是使得测试用例尽可能地让熟悉相关领域的人容易理解,这样会降低维护成本。
- 更多信息请查看以下链接:
Robot Framework该做的和不该做的
编写可维护的自动化接收测试 文章
如何结构化一个可伸缩且可维护的接收测试套件 博客
命名
测试套件命名
- 套件名称应该尽可能描述清楚。
- 套件名称会从文件名或目录名自动创建:
- 文件名的扩展名不会出现在套件名称中;
- 下划线会被转成空格;
- 如果套件名称都是小写字母,那么名称会自动转成首字母大写。
- 名称可以相对长一点,但是过长的话在文件系统中不方便。
- 如果需要的话,顶级套件的名称可以在命令行使用
--name
选项进行重写。
举例:
- 在文件系统中看到的是login_tests.robot,在RIDE中看到的是Login Tests
- IP_v4_and_v6在RIDE中看到的是IP v4 and v6
测试用例命名
- 测试用例和测试套件名称描述应该相似。
- 如果套件包含了多个相似的测试,并且套件命名良好的话,那么测试名称可以短一点。
- 测试用例名称就是你在测试用例文件中指定的名称,不会有任何的转换。
比如,如果我们在一个和非法登录相关的invalid_login.robot
文件中有很多测试,那么下面这些测试用例名称都是可以的:
*** Test Cases ***
Empty Password
Empty Username
Empty Username And Password
Invalid Username
Invalid Password
Invalid Username And Password
下面的名称就有点长了:
Login With Empty Password Should Fail
Login With Empty Username Should Fail
Login With Empty Username And Password Should Fail
Login With Invalid Username Should Fail
Login With Invalid Password Should Fail
Login With Invalid Username And Invalid Password Should Fail
关键字命名
- 关键字名称描述应该清晰。
- 应该解释该关键字做什么而不是怎么做。
- 不同的抽象级别(比如,
Input Text
和Administrator logs into system
)。 - 至于应该是每个单词首字母大写还是应该只有名称的首字母大写没有明确的规范。
- 每个单词的首字母大写通常用于关键字名称很短的情况,比如
Input Text
; - 如果关键字的命名像一个句子,那么一般将该关键字的首字母大写。比如
Administrator logs into system
。这些关键字通常也具有更高的级别。
- 每个单词的首字母大写通常用于关键字名称很短的情况,比如
好的关键字命名:
*** Keywords ***
Login With Valid Credentials
不好的关键字命名:
*** Keywords ***
Input Valid Username And Valid Password And Click Login Button
setup和teardown的命名
- 尽量使用描述做什么的名称。可能使用一个已存在的关键词。
- 如果setup和teardown包含了不相干的步骤,那么可以接受更抽象的名称:
- 将关键字名称逐个列出来会产生重复和维护问题(比如
Login to system, add user, activate alarms and check balance
) - 使用一些通用的名字通常来说更好一些(比如
Initialize system
)。
- 将关键字名称逐个列出来会产生重复和维护问题(比如
- 如果已存在实现了更低级别步骤的关键字,那么建议使用内置的
Run Keywords
。
*如果setup或teardown只需要一次的话,那么使用最好,这样不会重复。 - 使用测试的每个人务必要明白该setup或teardown做了什么。
好的命名:
*** Settings ***
Suite Setup Initialize System
好的命名2(如果只使用一次):
*** Settings ***
Suite Setup Run Keywords
... Login To System AND
... Add User AND
... Activate Alarms AND
... Check Balance
不好的命名:
*** Settings ***
Suite Setup Login To System, Add User, Activate Alarms And Check Balance
文档
测试套件文档
- 通常,最好是将所有的文档添加到测试用例文件中。
- 应该包含背景信息,比如为什么创建测试,执行环境需要注意的地方等等。
- 不要重复测试套件名称,如果真的不需要,那就最好不要有文档。
- 不要包含太多的详细信息和测试用例。
- 测试用例本身应该是理解起来清晰的。
- 重复信息浪费时间和精力,还会造成维护问题。
- 文档可以包含更多信息的链接。
- 如果需要以键值对形式的文档信息,可以考虑使用测试套件元数据metadata,比如
Version:1.0
。 - 顶级套件的文档和元数据可以分别使用
--doc
和--metadata
选项从命令行进行设置。
好的文档:
*** Settings ***
Documentation Tests to verify that account withdrawals succeed and
... fail correctly depending from users account balance
... and account type dependent rules.
... See http://internal.example.com/docs/abs.pdf
Metadata Version 0.1
不好的文档(特别当套件名称像account_withdrawal.robot
时):
*** Settings ***
Documentation Tests Account Withdrawal.
测试用例文档
- 测试用例通常不需要文档。
- 父套件的名字和可能的文档以及测试用例本身的名字应该给出足够的背景信息。
- 测试用例的结构应该尽可能地清晰,不需要文档或其它注释。
- Tags标签通常比文档更灵活,并提供了更多的功能,比如statistics【统计】、include/exclude等等。
- 有时测试文档是有用的,适当地使用很关键。
好的文档:
*** Test Cases ***
Valid Login
[Tags] Iteration-3 Smoke
Open Login Page
Input Username ${VALID USERNAME}
Input Password ${VALID PASSWORD}
Submit Credentials
Welcome Page Should Be Open
不好的文档:
*** Test Cases ***
Valid Login
[Documentation] Opens a browser to login url, inputs valid username
... and password and checks that the welcome page is open.
... This is a smoke test. Created in iteration 3.
Open Browser ${URL} ${BROWSER}
Input Text field1 ${UN11}
Input Text field2 ${PW11}
Click Button button_12
Title Should Be Welcome Page
用户关键字文档
- 如果关键字很简单的话就不需要文档了,此时应该具备好的关键字和参数名以及清晰的结构。
- 重要的用法是给参数和返回值加文档。
- 在资源文件中,使用 Libdoc生成的文档可以在编辑器(RIDE)中完成关键字输入之后,按下Ctrl键看到注释。
测试套件结构
- 套件中的测试应该是相关的,公用的setup和teardown通常是一个很好的说明。
- 一个文件中不应该有太多的测试用例(最大10个),除非是数据驱动的测试。
- 测试应是独立的,使用setup/teardown初始化。
- 有时,测试间的依赖是无法避免的。
- 比如,分别初始化所有的测试可能花费太多时间。
- 绝对不要有太长的测试依赖链。
- 使用内置的变量
${PREV TEST STATUS}
验证前一个测试的状态。
测试用例结构
- 测试用例应该容易理解。
- 一个测试用例应该测试一个东西,可以很小(一个功能的一部分),也可以很大(端到端)。
- 选择合适的抽象级别:
- 使用抽象级别要一致
- 在测试用例的级别不要包含不必要的详细信息
- 两种测试用例:工作流测试和数据驱动测试。
工作流测试
- 通常有以下阶段:
- 前置条件(可选,通常在setup中)
- 操作(对系统做一些操作)
- 验证(对结果进行验证,必须要有)
- 清理工作(可选,总是在teardown中完成)
- 关键字描述测试做了什么
- 使用明确的关键字名称和合适的抽象级别
- 应该包含足够的信息以手动运行。
- 不需要文档或注释来解释测试做了什么。
- 不同的测试可以有不同的测试级别
- 细节功能的测试可以更精确。
- 端到端的测试可以是非常高的级别。
- 一个测试应该只包含一个测试级别。
- 不同的风格:
- 对于低级别细节的更技术性的测试和集成测试。
- 将“可执行的说明书”作为需求。
- 使用领域语言。
- 每个人(包括客户和产品拥有者)应该总可以理解。
- 测试用例级别没有复杂的逻辑。
- 没有循环或if/else
- 小心使用变量赋值
- 测试用例不应该看起来像脚本
- 最大10个步骤,最好更少。
下面是使用了“正常的”关键字驱动的样式:
*** Test Cases ***
Valid Login
Open Browser To Login Page
Input Username demo
Input Password mode
Submit Credentials
Welcome Page Should Be Open
下面是使用了更高级的"gherkin"样式:
*** Test Cases ***
Valid Login
Given browser is opened to login page
When user "demo" logs in with password "mode"
Then welcome page should be open
数据驱动测试
- 每个测试应该有一个高级的关键字
- 不同的参数创建不同的测试
- 一个测试可以运行相同的关键字多次来验证相关变化的结果
- 如果该关键字是以用户关键字实现的,那么它一般包含了和工作流测试相似的工作流。
- 如果在其它地方不需要该关键字,那么在和测试相同的文件中创建该关键字是个好主意。
- 推荐使用数据驱动测试
- 不需要重复写该关键字多次
- 在一个测试中方很容易测试多种变化。
- 如果可能的话,推荐给列命名标题头。
- 如果真的需要大量的测试,可以考虑基于一个外部模型生成。
样例:
*** Settings ***
Test Template Login with invalid credentials should fail
*** Test Cases *** USERNAME PASSWORD
Invalid Username invalid ${VALID PASSWORD}
Invalid Password ${VALID USERNAME} invalid
Invalid Both invalid invalid
Empty Username ${EMPTY} ${VALID PASSWORD}
Empty Password ${VALID USERNAME} ${EMPTY}
Empty Both ${EMPTY} ${EMPTY}
*** Keywords ***
Login with invalid credentials should fail
[Arguments] ${username} ${password}
Input Username ${username}
Input Password ${password}
Submit Credentials
Error Page Should Be Open
用户关键字
- 应该容易理解,和工作流测试具有相同的规则。
- 不同的抽象级别。
- 可以包含一些编程逻辑(比如循环,if/else等等)
- 尤其是在一些低级的关键字种。
- 复杂的逻辑一般在测试库种而不是在用户关键字中。
变量
- 封装一些长的或者复杂的值。
- 在关键字之间传递信息。
变量的命名
- 名字明确但不要太长。
- 可以对变量进行注释。
- 使用一致的大小写规范:
- 在一个确定的范围内部对局部变量使用小写。
- 其它情况使用大写(全局,套件或测试用例级别的变量)。
- 空格和下划线都可以作为单词分隔符。
- 推荐在变量表中也要列出那些会动态设置的变量:
- 使用内置的关键字
Set Global Variable,Set Suite Variable
等对变量动态设置值。 - 初始值应该解释真正的值在哪里/如何设置。
- 使用内置的关键字
样例:
*** Settings ***
Suite Setup Set Active User
*** Variables ***
# Default system address. Override when tested agains other instances.
${SERVER URL} http://sre-12.example.com/
${USER} Actual value set dynamically at suite setup
*** Keywords ***
Set Active User
${USER} = Get Current User ${SERVER URL}
Set Suite Variable ${USER}
传参和返回值
- 通常的做法是从关键字中返回值,再将它们赋值给其它变量,然后将它们作为实参传给其它关键字。
- 另一种方法是将信息存在一个测试库中,或者使用内置的
Set Test Variable
关键字。- 避免在测试用例级别使用编程风格。
- 使用此方法可能会更复杂,并使得可复用关键字变得困难。
好的例子:
*** Test Cases ***
Withdraw From Account
Withdraw From Account $50
Withdraw Should Have Succeeded
*** Keywords ***
Withdraw From Account
[Arguments] ${amount}
${STATUS} = Withdraw From User Account ${USER} ${amount}
Set Test Variable ${STATUS}
Withdraw Should Have Succeeded
Should Be Equal ${STATUS} SUCCESS
不是很好的例子:
*** Test Cases ***
Withdraw From Account
${status} = Withdraw From Account $50
Withdraw Should Have Succeeded ${status}
*** Keywords ***
Withdraw From Account
[Arguments] ${amount}
${status} = Withdraw From User Account ${USER} ${amount}
[Return] ${status}
Withdraw Should Have Succeeded
[Arguments] ${status}
Should Be Equal ${status} SUCCESS
避免使用Sleep关键字
- 同步测试时,Sleep是一种非常不稳定的方式。
- 安全边际会使得平均Sleep时间太长。
- 使用那些具有轮询确定操作发生的关键字代替Sleep关键字:
- 关键字名称通常以
Wait
开头 - 应该设置一个等待的最大时间
- 内置的关键字
Wait Unitl Keyword Succeeds
内部可能封装了其它关键字
- 关键字名称通常以
- 有时Sleep是最简单的解决方案:
- 总是要小心使用
- 不要在用户关键字中使用,因为它们可能被其它测试或关键字使用。
- 在调试时阻止执行可能很有用。
以上翻译自https://github.com/robotframework/HowToWriteGoodTestCases/blob/master/HowToWriteGoodTestCases.rst
我们AT中的一些约定
我们项目现在做的是接口测试,比如对api/user/mobileregister
接口进行测试。
测试套件的命名:TC_接口类名_方法名,比如上面的接口对应的套件名称是TC_User_MobileRegister
。其中TC是TestCase的缩写,本该是TS【TestSuite】的,但一直这样用了,姑且就这样用吧。User是上面的接口所对应的类型,MobileRegister是该类中方法名,注意都是单词首字母大写。对一个接口的测试必须都写在一个测试套件中。
测试用例的命名:没有强制要求,如果说有,就是名字要明确、有序
比如,下面这个创建购买订单时的测试用例。明确体现在每个case名称后面都有简短的关键汉字说明;有序体现在有数字编号。还有一点是,如果有多个单词,单词之间没有分隔符,并且单词首字母大写。
变量的命名:
- 全局变量都定义在Common文件夹下的
variables.txt
文件中,见下图。规则是必须以G_
开头,单词首字母大写,只有一个单词的话全部大写也可以。比如${G_Server}或${G_SERVER}都可以,但有两个及以上单词时建议使用${G_ServerUrl}(这里还有几个之前没遵守的变量还没改)。 - 套件范围的变量命名建议单词之间以下划线分隔。比如
${user_name},${user_Name}
都可以。 - 测试用例中的变量和关键字中的变量建议使用首个单词首字母小写,比如
${userName},${tradePwd}
等等。 - 注意:robot framework IDE中,如果一个关键字定义的形式参数包含
${userName}
,但在测试用例中包含了一个从服务端返回的UserName字段,你将返回的值放到了${user_name}
或${User_Name}
,验证期望的${userName}
和返回的值是否相等时,RF会将这两个肉眼看着不同的变量当作同一个变量对待,所以必须明确区分这两个要比较的变量。比如,将返回的值存在变量${res_userName}
中。
关键字的命名:
目前项目中有两种用户关键字,一种是在Common文件夹下的resource.txt中的关键字,一种是每个测试套件中定义的关键字。
resource.txt文件中的关键字是经常使用的一些关键字,命名规范是每个单词首字母大写,区别于系统关键字。虽然字体颜色本身有所区分了,但是形式上再有所区分不是更明显了吗,而且颜色可以随意设置的。见下图。
每个测试套件中定义的关键字是只在该测试套件中使用关键字,命名规范是单词之间以下划线分隔,分割线之间的单词或词组都是首字母小写。见下图。