文章目录
前言
介绍robotframwork的官方文档:
https://robotframework-userguide-cn.readthedocs.io/zh_CN/latest/
https://github.com/robotframework/robotframework
这些文档晦涩难懂, 一上来就介绍语法,上例子, 全然不顾读者有没有测试或者python的背景, 因此我梳理了一下自己学习robot的过程, 按照由浅及深的方式写了这个文档. 当我们了解了robotframework的设计思想以及基本概念和处理流程后再回头看看这些文档就能够更好的进阶了.
什么是RobotFrameWork(扒皮RobotFrameWork)
RobotFrameWork高大上的说法是测试框架, 简单地说就是一个专门用于测试场景的一个Pyhthon高阶应用, 它新封装了很多应用测试场景的功能库(比如builtin, OperatingSystem, String,Process), 并且把这些库里面的库函数换成另一新名字叫Keyword,这些keywords会在测试脚本中被调用, 因此robotframwork测试文件本质上还是一个pyhton语言包装之后的python程序. 只不过它的语法变成了python 库里面新定义的函数的格式(初学者看到这些不伦不类的格式往往会感到晦涩难懂, 有懵圈的感觉, 所以在这里我们就给他扒皮指出它的本质). 真正了解到它的本质后一个小时内就能够掌握这个所谓的测试框架.
RobotFrameWork的安装:
git clone https://github.com/robotframework/robotframework.git
cd robotframework/
python3 setup.py install
***需要了解的是RobotFrameWork基本上不带python2.x版本玩了. 因此不要去用python2去玩RobotFrameWork.***
安装完成后就能在控制台下发现robot这个命令.
看看robot --help的一大坨输出, 可以初步扫一眼, 等熟悉robot的整体架构后再回来仔细分析每一个参数的高阶玩法, 这里我打了省略号:
Robot Framework -- A generic automation framework
Version: 5.0.dev1 (Python 3.7.5 on linux)
Usage: robot [options] paths
or: python -m robot [options] paths
or: python path/to/robot [options] paths
or: java -jar robotframework.jar [options] paths
Options
。。。。。。。。。。
root@exaleapsemi-r2:~#
RobotFrameWork的启动:
下面看看robot启动时的常用格式, 先不要管.robot文件的内容, 只需要知道它是一个测试脚本即可, 可以发现它的运行和linux一些操作文本的命令没什么不同:
robot my_tests.robot
robot -L debug my_tests.robot
robot -L debug --include smoke --variable HOST:10.0.0.42 path/to/tests/
第一个例子直接运行my_tests.robot脚本, 不带任何参数.
第一个例子是测试my_tests.robot脚本, 同时用-L选项指定输出Log的等级
第二个例子是测试path/to/tests/下面的所有脚本, 并且只执行标签是smoke的测试case, 同时设置一个变量HOST值是10.0.0.42
参数用法很灵活, 甚至支持通配符过滤测试case, 想要进阶研究要自己看看上面robot --help的输出.
Robot-Framework IDE
robot-framework-RIDE这个IDE工具可以用来辅助开发测试脚本. 我们这里只做类似VI的脚本编辑方式, 不展开介绍ride的使用. 因为只要掌握了robot测试脚本的语法, 暂时不大需要这样的IDE.只需要知道有这个东西存在即可.
Robot Framework几个基本概念
前面简单介绍了robot的安装使用以及IDE, 现在进入正题, 开始探索robot framework的设计思想. 先安利几个概念:
test和suit.
顾名思义, 简单地说test是指单个测试case, suit是指一套测试, 比如一个测试脚本可以看作一个suit, 在这个测试脚本里面有很多个case, 所以suit是test的集合.
setup和teardown
setup指的是在测试之前的动作, teardown指的是测试完成之后的动作. 举个栗子, 多个测试case在测试前需要做同样的动作A, 测试结束后都需要做同样的动作B, 这两个动作可以统一设计在setup/teardown里定义.这样不用再每一个case或者suit里面都去定义一次.
test setup 和test teardown
test setup/teardown定义每一个case在运行前和运行后的动作
suit setup和suit teardown
suit setup/teardown定义所有case在运行前和运行后的动作
tags
为了区分不同的测试case, 每一个case都可以打一个tag, 在运行的时候可以指定运行这个tag的case. 如果不指定tag, 也可以指定默认的tag名字
keywords关键字
关键字是测试脚本里面常用到的一个概念, 它的本质就是用python的库函数重新构建了一组应用测试场景的API, 比如Should Start With , Should Be Equal,Select Item From List等, 我们也可以自己像定义函数那样自己构建关键字.
Robot Framework测试脚本的结构
前面已经了解robot测试的基本概念, 现在来看看测试脚本的样子. 测试脚本分为四部分:
setting, Test Cases, Variable,Keywords. 其实把它看作一个python脚本就能够理解这个脚本的执行过程.
- setting, 导入了一些库函数, 比如下面内容里面的Attempt to Login with Credentials 等看起来晦涩难懂, 其实都是在lib/LoginLibrary.py里面定义的python函数, 而Status Should Be则是robot自己一个叫builtin的库函数里面定义的一个关键字(函数).
- Test Cases下面列的是每一个测试case, 第一行不带空格的是它的名字User can create an account and log in, 后面带了空格的是按顺序执行的动作.
- Variable, 定义变量. 在这个脚本里面没有体现, 但是变量的用法和编程语言一样.
- Keywords. 关键字. 所谓的关键字其实就是一个函数, 在test case里面会用到, keywords里面会看到[Arguments]这个定义, 它是对keywords的参数说明, 关键字是为test cases服务的
*** Settings ***
Library OperatingSystem
Library lib/LoginLibrary.py
*** Test Cases ***
User can create an account and log in
Create Valid User fred P4ssw0rd
Attempt to Login with Credentials fred P4ssw0rd
Status Should Be Logged In
User cannot log in with bad password
Create Valid User betty P4ssw0rd
Attempt to Login with Credentials betty wrong
Status Should Be Access Denied
*** Keywords ***
Clear login database
Remove file ${DATABASE FILE}
Create valid user
[Arguments] ${username} ${password}
Create user ${username} ${password}
Status should be SUCCESS
Creating user with invalid password should fail
[Arguments] ${password} ${error}
Create user example ${password}
Status should be Creating user failed: ${error}
Login
[Arguments] ${username} ${password}
Attempt to login with credentials ${username} ${password}
Status should be Logged In
# Keywords below used by higher level tests. Notice how given/when/then/and
# prefixes can be dropped. And this is a comment.
A user has a valid account
Create valid user ${USERNAME} ${PASSWORD}
She changes her password
Change password ${USERNAME} ${PASSWORD} ${NEW PASSWORD}
Status should be SUCCESS
She can log in with the new password
Login ${USERNAME} ${NEW PASSWORD}
She cannot use the old password anymore
Attempt to login with credentials ${USERNAME} ${PASSWORD}
Status should be Access Denied
现在我们知道一个.robot脚本文件的内容以及它们是如何运行的, 如果在这里还不明白请与笔者沟通. 除了上面提到.robot格式之外, robot还支持.html, tsv,txt,reStructedText格式. 其实没什么不同, 最后还是提炼setting, Test Cases, Variable,Keywords.这些字眼去运行测试case.
再多看看两个例子
下面再多看看两个例子来加深对于测试脚本的理解, 看完之后应该基本清楚robot的测试框架了.
例子一
下面例子介绍了Suite Setup/Suite Teardown/Test Setup/Test Teardown/的用法, 并且用到了变量定义,注意到log, log many都是builtin的库函数, 与print很相似.
*** Settings ***
#Documentation 当前测试集的描述文字
Suite Setup suitestart #测试集执行前的动作
Suite Teardown suitestop #测试集执行后的动作
Test Setup testsetup #用例执行前的动作
Test Teardown teststop #用例执行后的动作
#Force Tags #当前测试集下的用例都会被打上这个标签
#Default Tags #如果用例没有标签,则会默认打上这个标签
#Test Template #数据驱动模板
#Test Timeout #全局单个用例执行超时时间
#Metadata #定义元数据
#Library #引入的库
#Resource #当前测试集需要引入的资源文件
#Variables #引用的变量文件
Metadata 作者 orion-c # 自定义报告项目
Metadata 日期 2019-04-29
*** Variables ***
${_var} "hello" #定义一个标准参数
&{dict_var} sex='boy' age=7 #定义一个字典参数
*** Keywords ***
user custom keyword
[Arguments] ${arg1} ${arg2}='petter' @{list_arg} #传输参数,列表参数要放在最后
[Documentation] 描述信息
[Timeout] #自定义关键字的执行超时时间
[Tags] #标签
[Return] @{list_arg} #关键字的返回值
[Teardown] #关键词结束后的动作
log ${arg1}
log ${arg2}
log many @{list_arg} #打印列表或字典
suitestart
Log suitstart
suitestop
Log suitstop
testsetup
Log teststart
teststop
Log teststop
*** Test Cases ***
test_01
${test} user custom keyword 3 nivo 33 44
log many ${test}[1]
${list_lenght} BuiltIn.Get Length ${test} #获取列表长度
log ${list_lenght}
log many @{list_var}
log many &{dict_var}
log many &{dict_var}[sex] #获取字典值
root@wallace-VirtualBox:/home/test/QuickStartGuide#
看看运行结果:
root@wallace-VirtualBox:/home/test/QuickStartGuide# robot test_2.robot
==============================================================================
Test 2
==============================================================================
test_01 | FAIL |
Variable '@{list_var}' not found. Did you mean:
@{dict_var}
------------------------------------------------------------------------------
Test 2 | FAIL |
1 test, 0 passed, 1 failed
==============================================================================
Output: /home/test/QuickStartGuide/output.xml
Log: /home/test/QuickStartGuide/log.html
Report: /home/test/QuickStartGuide/report.html
root@wallace-VirtualBox:/home/test/QuickStartGuide#
上面的测试失败, 生成了output.xml, log.html, report.html报告, 原因是变量@{list_var}没有定义.
例子二
下面这个例子是NB2测试rtc的例子, 试着跟着注释去阅读这个测试脚本:
# File Name: test_rtc.robot
# Description: RPA sanity and Full test to check the Functioallity the RTC(Real Time Clock).
# Author: Ekta Hankare
# Last Modified: 2020
# Copyright: (c) 2019 ExaLeap.
# ExaLeap Proprietary and Confidential. All rights reserved.
*** Settings ***
Library OperatingSystem
Library BuiltIn
Library Process
Library String
*** Test Cases ***
NB2_RTC_01
[Documentation] RTC Driver Availability (Load/Unload)
[Tags] Sanity
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 1 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_02
[Documentation] Read,Write RTC time and date and readback recently updated time and date
[Tags] Sanity
Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 2 -d /dev/rtc' -b
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 2 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_03
[Documentation] Software to check the rtc functionality (hwclock)
[Tags] Full_Pass
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 3 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_04
[Documentation] Leap year
[Tags] Full_Pass_
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 4 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_05
[Documentation] RTC Interrupts
[Tags] Full_Pass
Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 5 -d /dev/rtc' -b
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 5 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_06
[Documentation] Wake up the system from sleep state using rtcwake command
[Tags] Full_Pass
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 6 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_07
[Documentation] To validate low frequeny crystal 32.768 KHz for real time clock
[Tags] Manual
${result}= Run cd Sources && sudo ./ip_validate.sh -n rtc -o '-t 7 -d /dev/rtc'
Log to console ${result}
Log ${result}
test ${result}
Execute Manual Step Does RTC have low frequency crystal 32.768 KHz oscillator.
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
NB2_RTC_08
[Documentation] To validate high frequeny crystal (26 MHz)
[Tags] Manual
${result}= Run cd Sources/ && sudo ./ip_validate.sh -n rtc -o '-t 8 -d dev'
Log to console ${result}
Log ${result}
test ${result}
Execute Manual Step Does FPGA have high frequency crystal 26 MHz oscillator.
Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
#NB2_RTC_09
# [Documentation] Wake up the system from poweroff state using wakealarm
# [Tags] Full_Pass
# ${result}= Run cd Sources/ && sudo ./ip_validate.sh -n rtc -o '-t 9 -d dev'
# Log to console ${result}
# Log ${result}
# test ${result}
# Pass Execution If 'return code 0' in '''${result}''' Test case is pass without any failure.
*** Keywords ***
test
[Arguments] ${result}
Should Not Contain ${result} command not found
${ret}= Get Lines Containing String ${result} TEST_WARNING
${len}= Get Length ${ret}
Run Keyword IF ${len}>0
... Log ${ret} warn
Pass Execution If ${len}>0 ${ret}
${ret4}= Get Lines Containing String ${result} TEST_SKIP
${len4}= Get Length ${ret4}
Pass Execution If ${len4}>0 ${ret4}
${ret1}= Get Lines Containing String ${result} TEST_ERROR
${len1}= Get Length ${ret1}
Run Keyword IF ${len1}>0 Run Keywords
... Log ${ret1} ERROR
... AND Fail ${ret1}
${ret2}= Get Lines Containing String ${result} TEST_CRITICAL
${len2}= Get Length ${ret2}
Run Keyword IF ${len2}>0 Run Keywords
... Log ${ret2} ERROR
... AND Fail ${ret2}
${ret3}= Get Lines Containing String ${result} TEST_FATAL
${len3}= Get Length ${ret3}
Run Keyword IF ${len3}>0 Run Keywords
... Log ${ret3} ERROR
... AND Fail ${ret3}
robot的输出结果简单介绍
使用robot命令执行robot test_xxx.robot后,会生成report.html, log.html,output.xml三个文件, 打开report.html如下:
测试结果分三部分:
Summery Information/TestStatistics / TestDetails.
Summery Information列出了一些基本信息,
上面的log,展示了测试脚本中定义的执行顺序. 可以通过这里来定位问题.
测试脚本和测试代码的布局
假设项目demo的代码放在Source目录, 那么robot测试脚本test_demo.robot,和Source放在同一目录, 在test_demo.robot中去调用脚本编译启动demo应用. 其他项目也可以放在这个目录下构成多个suit.
Jenkins里面启动robot自动测试
Jenkins里面在自定义构建的"构建"步骤里面选择执行shell, 在这里面可以启动robot 测试
然后在构建后操作选择publish HTML reports,中指定HTML的路径和html的文件名.
最后robotframework的入门就介绍到这里了, 本文主要介绍架构, builtin语法不在本文的讨论范围.可以参考:
http://robotframework.org/robotframework/latest/libraries/BuiltIn.html