-
Sikuli+RobotFramework集成
2011-10-27 12:09:05
我经手的一个手机项目曾经用Sikuli做自动化,但是其难看及简陋的test report着实让我郁闷的了一段时间,找来找去,只想到了一个替换方案,详细内容参见如何保存Sikuli的运行结果,但是这个方案仍然没有办法提供一个完整的结果统计数据,后来看到了Robot Framework这个测试框架,它本身并不能对被测试系统做任务测试,是通过第三方的工作及TestLibraries驱动完成的,但是它提供了一套完整的test report及log管理,后来想想是否可以将Sikuli与Robot Framework集成在一起呢?
抱着这种想法,在网上搜索(当然是google上而且是英语的关键字搜索)了一下,有一个贴子http://groups.google.com/group/robotframework-users/browse_thread/thread/d92ce2ec8b530d42?fwc=1&pli=1有人提到了在Mac版下如何进行2者的集成,后来又有贡献者提供了在window xp下2者集成的详细过程http://blog.mykhailo.com/2011/02/how-to-sikuli-and-robot-framework.html以下我只介绍在Mac OS下如何进行2者的集成,需要在windows OS的童鞋可参考http://blog.mykhailo.com/2011/02/how-to-sikuli-and-robot-framework.html1. Robot Framework 集成 Sikuli的工作原理如下:Robot Framework是基于Python的,它提供了2种方法执行脚本, 一个是python (pybot), 另一个是jython(jybot), Robot Framework支持自定义的libraries及第三方工具; Sikuli是通过jython执行脚本;初步的想法是:把Sikuli写成的脚本作为libraries供Robot调用,执行脚本时使用'jybot'驱动Sikuli工具完成, 如下集成结构图2. 操作步骤:- (1)安装
- (2)确保Sikuli脚本可以正确被java执行
- (3)将Sikuli脚本转换成Robot Framework可识别的libraries
- (4)执行脚本
- (5)运行结果
以下按上述步骤详述:(1)安装(以下是针对Mac OS的)- Java Runtime Environment (JRE 6_23) to run jython scripts.
- Jython 2.5.1 itself.
- Python 2.7.1 (it is required by Robot Framework distribution. See a note below).
- Robot Framework 2.5.5 (或更高版本, download Mac distribution)
- Sikuli X (Mac distribution)
(2)确保Sikuli脚本可以正确被java执行为了保证Sikuli的脚本可以通过Robot Framework驱动执行,我们首先要确保sikuli的脚本可以通过命令行的形式执行(java命令),详细过程参见 https://answers.launchpad.net/sikuli/+faq/1110- a.创建一个测试文件夹,本案例为 /work/RobotSikuli
- b.找到下载完成的Sikuli.App文件,右击“Show Package Contents”, 将其目录“/
Contents/ /work/RobotSikuliFrameworks”文件夹拷贝至 - c.打开/work/RobotSikuli/Frameworks文件夹,新建一个change-path.sh脚本,脚本中包括如下内容:
#!/bin/sh
for lib in *.*lib
do
for ref in `otool -L $lib | grep executable_path | awk '{print $1'}`
do
install_name_tool -change $ref @loader_path/../Frameworks/`basename $ref` $lib
done
done- d.打开终端,跳转至/work/RobotSikuli/Frameworks目录,执行如下命令
1. chmod +x change-path.sh:先用命令把批处理文件修改为可执行文件
2. ./change-path.sh :执行该文件。
3. 然后输入”otool -L *.*lib“: 确保脚本中所有libraries中@executable_path都被@loader_path "即/../Frameworks"所替换- e. 在/work/RobotSikuli/中新建一个名称为tmplib的文件夹,然后做如下运作
1. 找到下载完成的Sikuli.App文件,右击“Show Package Contents”, 解压目录“/Contents/Resources/Java/sikuli-script.jar”
2. 在解压后的文件夹中,找到“sikuli-script/META-INF/lib/libScreenMatchProxy.jnilib”并拷贝至/work/RobotSikuli/tmplib中
3. 在终端中执行“otool -L /work/RobotSikuli/tmplib/libScreenMatchProxy.jnilib”:确保原先所有指向 /opt/local/lib/*.dylib转为指向 @loader_path/../Frameworks/*.dylib如果执行步骤d,e时有问题,可以直接从网上下载整理好的文件执行,地址为:http://people. csail.mit. edu/vgod/ sikuli/ sikuli- libs.zip - f.在步骤e-2中解压好sikuli-script.jar文件夹中,找到“/sikuli-script/Lib”文件夹,将整个Lib文件夹拷贝至/work/RobotSikuli目录下;然后再将未解压的sikuli-script.jar包也拷贝到/work/RobotSikuli目录中
- g.下载patch http://
people. ,并该下载好的文件放在/work/RobotSikuli/Lib/sikuli目录中,然后在终端中执行如下动作csail.mit. edu/vgod/ sikuli/ sikuli- mod.patch
1. cd到/work/RobotSikuli/Lib/sikuli目录下
2. patch < sikuli-mod.patch
这个patch是给相同目录下的Screen.py及Sikuli.py打patch
Note: 但我不知道为什么要这么做,我根据上述步骤执行时提示“hunks failed”,但是后来验证该步并没有影响后续的动作- h. 在/work/RobotSikuli/中新建一个名称为test_suites的文件夹,在这个文件中放置写好的sikuli脚本,附件中有一个已经写好的sikuli脚本可以下载下来备用( Calc1.sikuli.zip(58.9 KB))
- i. 在/work/RobotSikuli/中新建一个名称为my_lib的文件夹,把附件中文件“Calc.py”拷贝该文件夹中,现在我们来看一下目前RobotSikuli文件夹结构
- j. 打开终端,先跳转至在/work/RobotSikuli/目录下,然后执行如下语句:java -d32 -Dpython.path=Lib -jar sikuli-script.jar Calc1.sikuli, 执行完成后,可以查看结果,这样就验证了Sikuli确实可以在命令行的情况执行脚本
(3)将Sikuli脚本转换成Robot Framework可识别的libraries- a. 根据Robot中说明,引用自定义的libraries时最简单的办法就是直接将一个module(in Python)或class(in Jython)映射成Robot中的"keywords name(相当于类)", 参考放在mylib中的sikuli脚本的.py文件,其就相当于是一个module了,可以直接当作test libraries被调用。
- b. 接下来我们要做的就是通过Robot驱动Sikuli的脚本运行,我们需要做的就是在使用Robot的格式想一个全新的脚本,脚本中所用的keywords可以直接引用.py文件中的方法名;Robot脚本参见附件 robot_calc1.txt(259 B )
(4)执行脚本:根据1中所介绍的原理,我们通过jybot这个工具执行Robot脚本,执行过程如下:1.打开终端,切换至/work/RobotSikuli目录下
2.export CLASSPATH=sikuli-script.jar
3.jybot --pythonpath=myLib:Lib test_suites/robot_calc1.txt(5)运行结果第2个case应该执行失败的,且查看log详细日志时,它的提示是“INFO FAIL:Actual result '4' is not equal to expected result '5'”,但在Report的状态栏显示的是PASS;后来想一下,这个提示只是在INFO中,RobotFramework并不知道没有办法知道INFO是通过还是失败。请公司的架构帮忙看了一下RobotFramework的代码,原来RobotFramework生成test report的机制是通过捕获异常来判断是否成功还是失败,在他的建议下,把原来写的sikuli(/myLib/Calc1.py)的脚本做了修正, 修改内容如下:将原有脚本中的print改为raise exception原来的脚本:def verifyResult(self, *args):expected_result = str(eval(''.join(args)))actual_result = self.getResultFromClipboard()#verificationif actual_result == expected_result:print("PASS: Action performed correctly and result equals %s" % expected_result)else:print AssertionError("FAIL: Actual result '%s' is not equal to expected result '%s'" % (actual_result, expected_result))现在的脚本:def verifyResult(self, *args):expected_result = str(eval(''.join(args)))actual_result = self.getResultFromClipboard()#verificationif actual_result == expected_result:raise AssertionError("PASS: Action performed correctly and result equals %s" % expected_result)else:raise AssertionError AssertionError("FAIL: Actual result '%s' is not equal to expected result '%s'" % (actual_result, expected_result))至此, Sikuli与RobotFramework的集成全部搞定,附上生成的报告后序:感叹啊,高手就是高手,人家只用了几个小时就把RobotFramework的代码及机制全搞清楚了,很快就能定位问题所在,这就是差距啊,我什么时候才能达到这种水平呢? -
Automation One By One - Robot Framework - User Keywords
2011-08-26 10:15:17
在 Automation One By One - Robot Framework - Test Case 这一章中已经简单介绍了keywords相关概念,我们知道keywords分为2大类,一类是Librarykeywords,另一类是userkeywords。对于Librarykeywords我们不在这边做详细的介绍了,本章主要介绍如何创建userkeywords.
1. userkeywords的语法(syntax)- 与test case的语法类似,唯一不同在于存放的位置不同,test case放在test case table中,keyword放在keywords table中***keywords***
userkeywords_name [Arguments]
ExamplesExample without arguments
***keywords***
Open Login Page
Open Browser http://www.baidu.com
Title Should Be 百度知道
Example with arguments
***keywords***
Title Should Start With [Arguments] ${expected_value}
${title} = Get Title
Should Start With ${title} ${expected_value}
2. keywords table中可以加入settings命令
为了与keywords的name区分,keywords table中的命令使用[settings]格式。
可以使用的settings命令如下:- [Documentation]
- Used for setting a user keyword documentation.
- [Arguments]
- Specifies user keyword arguments.
- [Return]
- Specifies user keyword return values.
- [Timeout]
- Sets the possible user keyword timeout. Timeouts are discussed in a section of their own.
3. userkeywords中的arguments格式
4. userkeywords name中嵌入arguments.- 语法:在userkeyword名中嵌入argument后不能再使用[arguments]添加其它的参数了。
- 在userkeyword名中的arguments依赖于调用userkeyword时传递的值,如下例子
百度高级搜索页面
*** Settings ***
Library Selenium Library 15
Test Setup Start Selenium Server
Test Teardown Stop Selenium Server
*** Testcases ***
TC1 [Documentation] embedded arguments
Open Browser http://news.baidu.com/advanced_news.html
Select 最近一年 from list
Select 最近一周 from list
Select 最近一小时 from list
comment 上述的值应该在下拉列表范围内,如果不在,系统会报错
*** Keywords ***
Select ${date} from list
Sleep 3s
Select From List name=mt ${date}- 需要注意的事,如果传递的值是带有空格的,如 最近 一年, 在调用函数时必须用引号引起来,说明要传递的是一个参数,否则,系统会认为是2个值。
5. 定义一个可以返回值的userkeywords - 实现这个功能,可以借助settings-[Return]命令实现
*** Keywords ***
Return Value keyword
[Return] pass
Return One Value [Arguments] ${arg}
Do Something ${arg}
${value} = Get Some Value
[Return] ${value}
6. 调用userkeywords
从开发的角度讲,userkeywords及Librarykeywords相当于一个个封装好的函数,在test case中使用这些keywords时与调用函数的方法一样。调用keywords
***Test Cases***
Open Login Page
Title Should Start 百度
-
Automation One By One - Robot Framework - 变量及赋值
2011-07-29 11:12:02
前面已经提到变量有三类,一类是scalar variable ${variable},一类是list variable,还有一类是内置(Built-in)的变量.
1. 给scalar variable类型的变量赋值:${scalar variable}
(1)${scalar variable}= simple strings
(2)${scalar variable}= objects
无论scalar类型的变量被赋予什么值,这个值先被转换成Unicode,然后再按字符串显示出来。转换的过程相当于调用这个对象的__unicode__,__str__
2. 给list variable赋值: @{variable}
(1)列表变量中的值,可以是一个,也可以是多数(无数),还可以是空
(2)列表变量的值通常是字符类型的,其它类型的也可以
(3)可以通过@{NAME}[i]形式来访问列表中的某一个值
(4)可将list variables当作scalar类型的变量使用,使用方法是将list变量的符号从@替换成$就可以了;这种表达式让我们使用built-in类库及Collection类库中list相关的keywords成为可能。
(5)list变量可以应用在setting table中,但仅限于一部分的settings命令可用。- 对于Library及Resource的settings来说list变量不能作为其name使用,只能作为argument使用
- 对于Setup/Teardown的settings来说list变量不能当作keyword的name使用,只能作为argument使用
- 对于tag的settings来说可以随意使用
- 对于不支持list变量的settings来说,我们可以使用scalar变量的形式来表达(如library及setup中的name不能使用list变量,我们可以用scalar变量代替list变量)
Using list variables with settings Settings Value Value Comment Library ExampleLibrary @{LIB ARGS} # This works Library ${LIBRARY} @{LIB ARGS} # This works Library @{NAME AND ARGS} # This does not work Suite Setup Some Keyword @{KW ARGS} # This works Suite Setup ${KEYWORD} @{KW ARGS} # This works Suite Setup @{KEYWORD} # This does not work Default Tags @{TAGS} # This works
3. 给Envrionment Variables赋值:%{ENV_VAR_NAME}
(1)只能赋值string类型的值
(2)可于 OperatingSystem library 类库中的keyword一块应用
4. 可以将keyword中返回的值作为变量存储
${keyword_return_value}= Get Matching Xpath Count [locator]
${keyword_return_value}= Get Element Attribute [locator]
...
5. 内置Build-in变量Available operating-system-related built-in variables Variable Explanation ${CURDIR} An absolute path to the directory where the test data file is located. This variable is case-sensitive. ${TEMPDIR} An absolute path to the system temporary directory. In UNIX-like systems this is typically /tmp, and in Windows c:\Documents and Settings\<user>\Local Settings\Temp. ${EXECDIR} An absolute path to the directory where test execution was started from. New in Robot Framework 2.1. ${/} The system directory path separator. / in UNIX-like systems, \ in Windows. ${:} The system path element separator. : in UNIX-like systems and ; in Windows. Variable Explanation Available ${TEST NAME} The name of the current test case. Test case @{TEST TAGS} Contains the tags of the current test case in alphabetical order. Test case ${TEST STATUS} The status of the current test case, either PASS or FAIL. Test teardown ${TEST MESSAGE} The possible error message of the current test case. Test teardown ${PREV TEST NAME} The name of the previous test case, or an empty string if no tests have been executed yet. Everywhere ${PREV TEST STATUS} The status of the previous test case: either PASS, FAIL or an empty string when no tests have been executed. Everywhere ${PREV TEST MESSAGE} The possible error message of the previous test case. Everywhere ${SUITE NAME} The full name of the current test suite. Everywhere ${SUITE SOURCE} An absolute path to the suite file or directory. New in Robot Framework 2.5. Everywhere ${SUITE STATUS} The status of the current test case, either PASS or FAIL. Suite teardown ${SUITE MESSAGE} The full message of the current test suite, including statistics. Suite teardown ${OUTPUT FILE} An absolute path to the current output file. Has different values during execution when outputs are split. Everywhere ${LOG FILE} An absolute path to the current log file or string NONE when no log file is created. Has different values during execution when outputs are split. Everywhere ${REPORT FILE} An absolute path to the report file or string NONE when no report is created. Everywhere ${SUMMARY FILE} An absolute path to the summary file or string NONE when no summary is created. Everywhere ${DEBUG FILE} An absolute path to the debug file or string NONE when no debug file is created. Everywhere ${OUTPUT DIR} An absolute path to the output directory. Everywhere
-
Automation One By One - Robot Framework - 数据类型
2011-07-29 10:19:31
Robot Framework中的数据类型均是通过变量(Variable)来表达的。
Robot Framework提供以下几种数据类型:
1. 字符串:${variable}, ${get value from keyword}, 80 ... 默认均是字符串类型
2. 数值型:表达数值型,必须使用${Numbers}来表示Test Case Action Argument Argument Comment Example 1A Connect example.com 80 # Connect gets two strings as arguments Example 1B Connect example.com ${80} # Connect gets a string and an integer Example 2 Do X ${3.14} ${-1e-4} # Do X gets floating point numbers 3.14 and -0.0001
3. 布尔值Test Case Action Argument Argument Comment Boolean Set Status ${true} # Set Status gets Boolean true as an argument Create Y something ${false} # Create Y gets a string and Boolean false
4. Null/None值Test Case Action Argument Argument Comment None Do XYZ ${None} # Do XYZ gets Python None as an argument Null ${ret} = Get Value arg # Checking that Get Value returns Java null Should Be Equal ${ret} ${null}
上述这些类型的变量均是大小写不敏感的,即 ${True} and ${true} 是相等的. 另外, ${None} and ${null} 属于属于同义词。
5. 空格、Empty
Robot Framework允许你使用${SPACE},${EMPTY}来表示空格及空Test Case Action Argument Argument One Space Should Be Equal ${SPACE} \ \ Four Spaces Should Be Equal ${SPACE * 4} \ \ \ \ \ Ten Spaces Should Be Equal ${SPACE * 10} \ \ \ \ \ \ \ \ \ \ \ Quoted Space Should Be Equal "${SPACE}" " " Quoted Spaces Should Be Equal "${SPACE * 2}" " \ " Empty Should Be Equal ${EMPTY} \
-
Automation One By One - Robot Framework - 优化Test Case
2011-07-12 09:43:58
还是以前面提到成功登录百度账号的feature为例。*** Settings ***Library Selenium LibraryResource /Path/to/Variable.txt
Resource /Path/to/loginkeywords.txt
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]
仔细想想这个test case是不是还有什么不完美的地方呢?
我们说一个test case最大的特性就是repeatability, 即保证每次执行时步骤都是可重现的,output的也都是一样的。
看看上面这个test case,它是否具有可重现性的特质呢? 如果用户已经登录了,这面的脚本是否可以执行通过?
如何解决这个问题?- 在test case的真正代码执行前,我们先判断一下是否已经登录,如果已经登录则执行退出运作然后再执行登录的操作,如果没有登录则执行登录操作。
- 我们修改一下test case
- 先查找一下有没有退出按钮
- 如果有单击退出
- 如果没有再执行接下来的脚本
*** Settings ***Library Selenium LibraryResource /Path/to/Variable.txt
Resource /Path/to/loginkeywords.txt
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
${status}= Call Selenium Api is_element_present link=登出 (将是否存在登出按钮的结果当成变量存储起来)
Run Keyword If ${status} == True Click link=登出 (以变量为条件进行判断)
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]- 为了方便用户理解,我们把刚才新增的脚本放在loginkeywords.txt中.
- 修改过后的Test Case及LoginKeywords如
*** Settings ***Library Selenium LibraryResource /Path/to/Variable.txt
Resource /Path/to/loginkeywords.txt
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Whether Login
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]*** Keywords *** Whether LoginEnter Username [Arguments] ${username}
${status}= Call Selenium Api is_element_present link=登出 (将是否存在登出按钮的结果当成变量存储起来)
Run Keyword If ${status} == True Click link=登出 (以变量为条件进行判断)
Open Login Page (移除)
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Successful [Arguments] ${username}Page Should Contain ${username}
Login Is Failed [Arguments] ${username}
Page Should Not Contain ${username} -
Automation One By One - Robot Framework - Keyword/Variable Files
2011-07-11 16:55:31
根据Automation One By One - Robot Framework - Test Suite中所描述的百度账号的feature,我们分成了几个test suites,每个suite中都包含了一类test case files.
比如02_login test suite中包含了成功登录和登录失败2个test case files,比对一下2个test case file中不同的地方:- Variable表中的username内容不同
- Test Case表中最后一句,一个是Login Is Successful, 一个是Login Is Failed
- Keywords表中Login Is Successful/Login Is Failed定义的内容不同
- 把Variable的内容提取出来形成一个名称为variables.txt的文档。(文档名称可自定义)
variable.txt文档中的内容:
***Variables***
@{username}= user1 user2 user3 user4 user5 user6
@{password}= password1 password2 password3 ...- 把keywords中的内容提取出来形成一个名称为loginkeywords.txt的文档。(文档名称可自定义)
loginkeywords.txt文档中的内容:
*** Keywords ***Open Login PageEnter Username [Arguments] ${username}
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Successful [Arguments] ${username}Page Should Contain ${username}
Login Is Failed [Arguments] ${username}
Page Should Not Contain ${username}
2. 提取成功后,原来的test suites的结构就发生了变化- 原来是
- Baidu
- __init__.txt
- 01_register
- 01_registerfailed
- 02_registersucceed
- __init__.txt
- 02_login
- 01_loginfailed
- 02_loginsucceed
- __init__.txt- 现在是
- Baidu
- __init__.txt
- variables.txt (注意:因为注册和登录的变量有可能用的是一样的,所以可以将variables提取到最高级别,方便注册和登录的test suite共享)
- 01_register
- 01_registerfailed
- 02_registersucceed
- __init__.txt
- 02_login
- 01_loginfailed
- 02_loginsucceed
- loginkeywords.txt
- __init__.txt
3. 提取后test case file的内容也有变化,如登录中2个test file 内容的变化- 登录失败
*** Settings ***Library Selenium LibraryResource /Path/to/Variable.txt (移除variables表格,导入variables文件)
Resource /Path/to/loginkeywords.txt (移除keywords表格,导入loginkeywords文件)*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[4]Enter Password @{password}[0]Click the Login ButtonLogin Is Failed @{username}[4]- 登录成功
*** Settings ***Library Selenium LibraryResource /Path/to/Variable.txt (移除variables表格,导入variables文件)
Resource /Path/to/loginkeywords.txt (移除keywords表格,导入loginkeywords文件)*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]
总之一句话:Test Case File中只保留初始化所必须的settings及test case中不重复的步骤,越精简越好。即写脚本要有面向对象的思想(封装,继承,多态)
-
Automation One By One - Robot Framework - Test Suite
2011-07-08 13:55:40
前面已经介绍了如何进行Test case及Test file的编写,如果要编写的test case有很多,我们需要对这些test case分类,形成不同的test file或是test suite.
test file:可以整合一个或多个test case,一个test file可以看成是一个test suite.
test suite: 可以整合一个或多个test file,是比test file更高一级的test suite.
比如前面介绍的百度账号登录的功能,要想登录肯定是先注册,对注册的测试应该分为成功注册和失败注册2类,登录也要分成登录成功和登录失败2类来测试,那我们就可以把这些测试做一个分类,如下:- Baidu -- test suite
- 01_register -- test suite
- 01_registerfailed -- test file
- 02_registersucceed -- test file
- 02_login -- test suite
- 01_loginfailed -- test file
- 02_loginsucceed -- test file
执行脚本时,即可以单独执行某个test file,又可以执行某一类test suite(比如Baidu(执行所有test file),01_register(只执行其下的test file),02_login(只执行其下的test file))
在Automation One By One - Robot Framework - Conception这篇文章中已经介绍了test suite,要想把一个文件夹当成一个test suite必须添加一个初始化文件 (initialization file), 这个初始化文件中存放的是test file中共同的settings或keyword, 所以我们要想真正的执行一个test suite必须将上述的组织结构加入初始人文件 __init__.txt- Baidu -- test suite
- __init__.txt
- 01_register -- test suite
- 01_registerfailed -- test file
- 02_registersucceed -- test file
- __init__.txt
- 02_login -- test suite
- 01_loginfailed -- test file
- 02_loginsucceed -- test file
- __init__.txt__init__.txt中的内容是从原来的test case file中挑出来的共用的东西,比如02_login中的初始化文件内容包括:
*** Settings ***Suite Setup Start Selenium ServerSuite Teardown Stop Selenium Server
Test Setup Setup TestTest Teardown Close All Browsers
*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window
如此以来login test case file中的内容将变成如下
*** Settings ***Library Selenium Library
***Variables***
@{username}= user4 user5 user6 ...
@{password}= password1 password2 password3 ...
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]
*** Keywords ***Open Login PageEnter Username [Arguments] ${username}
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Successful [Arguments] ${username}Page Should Contain ${username}
而对于更高级的test suite(BaiDu)中的__init__.txt文件来说,其内容应该是所有的test suites中共存的东西,即*** Settings *** Suite Setup Start Selenium ServerSuite Teardown Stop Selenium Server
那下一级的test suite的初始化文件中应该将高一级的test suite中包含的东西移除掉,即低一级test suite中的初始化文件
*** Settings ***
Test Setup Setup TestTest Teardown Close All Browsers
*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window
所以总结一下:
第一级test suite - BaiDu包含的内容如下:- __init__.txt
*** Settings *** Suite Setup Start Selenium ServerSuite Teardown Stop Selenium Server- 01_register-test suite
- 02_login-test suite
- __init__.txt
*** Settings ***
Test Setup Setup TestTest Teardown Close All Browsers
*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window- 01_registerfailed-test case file
- 02_registersucceed-test case file
- __init__.txt
*** Settings ***
Test Setup Setup TestTest Teardown Close All Browsers
*** Keywords ***
Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window- 01_loginfailed-test case file
*** Settings ***Library Selenium Library
***Variables***
@{username}= user1 user2 user3 ...
@{password}= password1 password2 password3 ...
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Failed
*** Keywords ***Open Login PageEnter Username [Arguments] ${username}
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Failed [Arguments] ${username}Page Should Not Contain ${username}
- 02_loginsucceed-test case file
*** Settings ***Library Selenium Library
***Variables***
@{username}= user1 user2 user3 ...
@{password}= password1 password2 password3 ...
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]
*** Keywords ***Open Login PageEnter Username [Arguments] ${username}
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Successful [Arguments] ${username}Page Should Contain ${username}
- __init__.txt
-
Automation One By One - Robot Framework - Test File
2011-07-07 11:41:37
在http://www.51testing.com/index.php?uid-49689-action-viewspace-itemid-240392中,提到了test case file,如果要想执行test case必须把test case放在test file中。
Test File包含了四部分:Setting(required), Variable(optional), Test Case(required), Keyword(optional)- Setting、Test Case是必须的
- Variable只有当需要变量的时候才有用
- Keyword只有当standard libraries及external libraries没有,需要将多个keywords组合成另一个功能强大的keyword时才有用。
1. Setting- Setting相当做初始化的工作。
- Robot Framework本身并不与被测试网站直接交互,而是以test libraries作为驱动,这些libraries可以是第三方的测试工具类库也可以是标准的类库,我们采用的Selenium Library。
- 要想将一个test case执行起来,必须将Selenium Library导入到test file中;Robot Framework提供了Library setting来完成这项工作。
- 要导入的library的名称是大小写敏感的。
- Selenium Library提供了5个默认参数:
- timeout=5.0, server_host=localhost, server_port=4444, jar_path=None, run_on_failure=Capture Screenshot
- Example
- *** Settings ***
- Library Selenium Library
如果调用Selenium Library时不提供任何参数,则意味着默认参数刚会被使用。- *** Settings ***
- Library Selenium Library 15 http://192.168.1.15 4455 ${EMPTY} ${SPACE*2}
如果调用Selenium Library时提供参数,则以提供的值使用。2. Test Case - 以登录百度账号为例
Selenium Library有5个参数,有的参数需要赋新值,有的需要使用默认值,如何处理?- 新值直接添加即可。
- 默认值,可以输入${EMPTY}或是'\ '代表调用时使用默认值。
*** Settings ***Library Selenium Library*** Testcases ***Login Should Succeed When the Correct Username and Password are EnteredStart Selenium ServerOpen Browser http://www.baidu.com/ chromeMaximize Browser WindowClick Link link=登录Input Text username user1Input Text normModPsp password1Click Button xpath=//input[@value=' 登录 ']Page Should Contain user1Close BrowserStop Selenium Server3. Suite Settings- 第1行,代表从现在开始是Test Case的内容了
- 第2行,是Test Case的Name
- 第3行,启动Selenium Server, 因为是代助selenium RC来驱动脚本的。
- 第4行,打开一个网址,Open Brower关键字提供了3个参数url, browser=firefox, alias=None;url是Required Arguement,其它的参数如果不提供则按默认值;本例子中的brower参数重新赋值了chrome,则相当于用chrome打开定义的url
- 第5行,最大化打开的浏览器窗口
- 第6行,单击登录链接
- 第7、8行,输入用户名及密码
- 第9行,单击登录按钮
- 第10行,校验是否登录成功
- 第11行,关闭浏览器
- 第12行,停止Selenium Server
- Robot Framework执行脚本时的机制是,当某一步失败,接下来的步骤将不会被执行,这样以来,如果上述的脚本任何一步失败,则tear down的task则永远不会被执行,那这个case也就永远不会被关闭,接下来的case也就不会被执行。
- 为了解决这个问题,我们可以将setup及teardown抽象出来,放在settings下面,这样一个case的某步失败后,Robot Framework会自动执行tearn down task,且下一个Case会在上一个case tear down后仍然可以执行(setup)。
- 相同的原因,我们也希望打开浏览及关闭浏览器的运作也需要在开始执行case前及case失败后完成,这个愿望是可以通过settting中的Test Setup/Test Teardown setting来实现。
*** Settings ***Library Selenium LibrarySuite Setup Start Selenium ServerSuite Teardown Stop Selenium ServerTest Setup Open Browser http://www.baidu.com/ chromeTest Teardown Close All Browsers
*** Testcases ***Login Should Succeed When the Correct Username and Password are EnteredMaximize Browser WindowClick Link link=登录
Input Text username user1Input Text normModPsp password1Click Button xpath=//input[@value=' 登录 ']Page Should Contain user1- Suite Setup: Fires once before any tests during the suite are run.
- Suite Teardown: Fires when all tests in the suite have completed, even when one of them has failed.
- Test Setup: Fires before each test is executed.
- Test Teardown: Fires at the end of each test execution, even when the test fails.
*** Settings ***Library Selenium LibrarySuite Setup Start Selenium ServerSuite Teardown Stop Selenium ServerTest Setup Open Browser http://www.baidu.com/ chromeTest Teardown Close All Browsers
***Variables***
@{username}= user1 user2 user3 ...
@{password}= password1 password2 password3 ...*** Testcases ***Login Should Succeed When the Correct Username and Password are EnteredMaximize Browser WindowClick Link link=登录Input Text username @{username}[0]Input Text normModPsp @{password}[0]Click Button xpath=//input[@value=' 登录 ']Page Should Contain @{username}[0]- 变量的设置应该放置在 ***Variable***
- 变量命名最好由a-z,A-Z,0-9,_,space组成
- Variable的作用域:
- Variable定义在Testcases内容中,则只对该testcase起作用;
- 如果一个test file中包含了2个test cases,而这2个test cases都需要用到同一个变量,那就需要把这个变量提升至Variables中,这个变量的作用域覆盖到了test file中所有的test cases;
- 无论是在test case中或test file中的变量,其作用范围只是这个test case或test file;如果这个变量需要被不同的test files或是test suite中共用的,则需要将所有变量存在一个文件中,然后将这个变量文件作为resource导入。
- 在Settings中,使用Resource setting完成导入的运作。
***Settings***
Resource /path/to/file.txt- Variable有类型有以下几种:
- Scalar Variable: 只有一个值的变量, 表达式${username}= user1
- List Variable: 一个变量中包含多个值,表达式:@{username}= user1 user2 user3 ...
- 取得某一个特定值时,用@{NAME}[i]来表达, i索引,从0开始
- Environment Variable: 操作系统级的变量,属全局变量 表达式%{ENV_VAR_NAME}
- 在第3点中,已经把start/stop selenium server,open/close browser抽离出来了, 看看test case table中还有一个Maximize Browser Window,这个Keyword也可以抽离出来放在每个test caser之前完成,那么如何把它也放在Test Setup中呢?
- 因为setup/teardown setting只能带一个keyword,我们可以借助keywords table来实现
*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window- 我们新建了一个Keyword,名称为Setup Test, 这个keyword实现的功能就是打开浏览器并最大化它,所以应该按如下修改脚本:
*** Settings ***Library Selenium Library
Suite Setup Start Selenium ServerSuite Teardown Stop Selenium ServerTest Setup Setup TestTest Teardown Close All Browsers
***Variables***
@{username}= user1 user2 user3 ...
@{password}= password1 password2 password3 ...*** Testcases ***Login Should Succeed When the Correct Username and Password are EnteredClick Link link=登录Input Text username @{username}[0]Input Text normModPsp @{password}[0]Click Button xpath=//input[@value=' 登录 ']Page Should Contain @{username}[0]*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser Window- 上述脚本中有些keywords不是特别易读,为了提高脚本的可读性,我们借助keyword table完成。
*** Keywords ***Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser WindowEnter Username [Arguments] ${username}Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is SuccessfulPage Should Contain Welcome- 优化后的脚本如下:
*** Settings ***Library Selenium Library
Suite Setup Start Selenium ServerSuite Teardown Stop Selenium Server
Test Setup Setup TestTest Teardown Close All Browsers
***Variables***
@{username}= user1 user2 user3 ...
@{password}= password1 password2 password3 ...
*** Testcases ***Login Should Succeed When the Correct Username and Password are Entered
Open Login PageEnter Username @{username}[0]Enter Password @{password}[0]Click the Login ButtonLogin Is Successful @{username}[0]
*** Keywords ***
Setup TestOpen Browser Open Browser http://www.baidu.com/ chromeMaximize Browser WindowEnter Username [Arguments] ${username}
Open Login Page
Click Link link=登录Input Text uname ${username}Enter Password [Arguments] ${password}Input Text pwd ${password}Click the Login ButtonClick Button loginLogin Is Successful [Arguments] ${username}Page Should Contain ${username}- 执行这个Test Case时,先将目录定位到这个文件所在的文件夹,然后pybot validlogin.txt 即可。
-
Automation One By One - Robot Framework - Test Case
2011-07-06 09:41:29
接续上一篇:http://www.51testing.com/?uid-49689-action-viewspace-itemid-240392
Robot Framework组成Test Case的要素:
(1)Action(步骤) - Keyword, 存在2大类Keyword- Library keywords - 通常来自标准类库或第三方类库
- Standard Libraries
- External Libraries
- SeleniumLibrary
- SwingLibrary
- 自定义的libraries - http://robotframework.googlecode.com/svn/tags/robotframework-2.5.6/doc/userguide/RobotFrameworkUserGuide.html#creating-test-libraries
- User keywords - 通过Keyword table创建,来源是Library keywords, user keywords可以与test case位于同一文件内或是作为单独的一个文件导入到test case的文件中;
- 这类的Keyword可以想像成把若干Library keywords集合到一起,形成一个新的keyword,新keyword可以完成一步或几步action,其作用类似于编程中的函数或类。
- 在接下来的文章中,主要是针对SeleniumLibrary及BuiltinLibrary进行介绍。
(2)Argument - 可以是变量或常量- Argument与任何语言中的参数作用是一样的,其主要的目的就是为keywords传递数据。
- 一个keyword可以有0个或多个Arguments。
- Robot中参数类型有以下几种,这种分类是从Python中借鉴而来的:
- Required Argument =(Positional Arrangement位置参数)以正确的定位顺序及数量来传入函数的,顺序改变了或数量不正确就不能完成参数的传递
- Examples: - Login
***Test Case***
TC1 [Documentation] User can create an account and log in Create Valid User username1 password123
Attempt to Input with Credentials username1 password123
Status Should Be Logged In- username1/password123/Logged In 都是位置参数
- 有些Keyword也可以没有参数
- Named Argument(关键字参数)- 如果命名了参数,可以不按顺序传递参数
***Test Case***
TC2 [Documentation] Named Argument
Example Keyword arg2=xxx arg3=yyy- Default Argument - 默认参数是一个已经赋值的关键字参数,如果在函数调用时没有给出值,那么这个赋值就会被传递。
如:OperatingSystem library中有一个关键字Create File,这个关键字有3个参数 path, content=, encoding=UTF-8
当使用这个关键字时,path参数必须存在,content及enconding可以不输入,如果不输入则意味着content为空,encoding是UTF-8;如果输入了则按输入的值传递
***Test Case***
TC3 [Documentation] Default Argument
Create File ${TEMPDIR}/empty.txt
Create File ${TEMPDIR}/utf-8.txt Hyvä esimerkki
Create File ${TEMPDIR}/iso-8859-1.txt Hyvä esimerkki ISO-8859-1- Argument可以是常量也可以是变量
如上述 Create File Keyword, encoding可以是常量如ISO-8859-1,也可是使用变量。
假设我现在有一个encoding的列表,列表中的值有ISO-8859-1,UTF-8,GBK等等,每次取值都是不一样的。
在Robot中,我们可以将encodning定义为列表
@{encoding}=ISO-8859-1 UTF-8 GBK
当调用Create File这个Keyword时,我们需要传一个变量,即@{encoding}[0],@{encoding}[1]- Argument接收的变量可以是一个值,也可是一个对象
Python及C中均有 *varargs概念
Robot中的Join Paths keyword,其Argument有2个,分别是*paths,base
*path意味可以传递任意数量的变量; base只是传递一个变量- 以上类型的参数可以同时存在,但是有一定规则:
- Required Argument(位置参数)必须放在Named Argument(关键字参数)之前
- Required Argument(位置参数)必须出现在任何一个默认参数之前
- 如果参数一个对象(即列表或元组),则其必须放在Required Argument(位置参数)和Default Argument(默认参数)之后
- Library keywords - 通常来自标准类库或第三方类库
-
Automation One By One - Robot Framework - Conception
2011-07-04 18:17:38
手动测试过程中,有Test Case(Test Environment,Test Data,Test Steps, Expected Result), Test Suite的概念;软件开发过程上有面向对象的概念(即继承、封装,多态),做自动化测试开发需要具备测试人员的基础知识及程序员的思想。
1. Test Case - 包含测试数据,一系列的操作步骤及期望值。- 写Test Case时,可以使用4种格式,分别是hypertext markup language (HTML), tab-separated values (TSV), plain text, or reStructuredText (reST) formats,本实例中使用plain text的格式。
- Plain text格式的Test Case使用至少2个空格做为分隔符。
- 因为空格作为分隔符使用,当需要使用空格原义时,可以使用${EMPTY}变量或是 \ 来进行转义。
- 组成Test Case的要素
- 操作步骤(Test Steps)- Action (用Keyword来实现)
- 期望值(Expected Result)- Argument(可以使用Variable)
- 测试数据(Test Data)- Argument
- Example:
***Test Cases***
My Test [Documentation] Example test
Log ${MESSAGE}
Another Test
Should Be Equal ${MESSAGE} Hello, world!
My Test/Another Test 是Test Case的名字
Log/Should Be Equal - 是Action(Keywords)
${Message}/Hello, world - 是期望值(可以是变量也可以是常量)
2. 多个Test Cases可以放在同一个文件中,称为test case file。- Test Case File的组成
Table name Used for Setting table 2) Defining metadata for test casesVariable table Defining variables
that can be used elsewhere in the test caseTest case table Creating test cases from available keywords Keyword table Creating user keywords from existing lower-level keywords - Examples:
***Settings***
Library OperatingSystem
***Variables***
${MESSAGE} Hello, world!
***Test Cases***
My Test [Documentation] Example test
Log ${MESSAGE}
My Keyword /tmp
Another Test
Should Be Equal ${MESSAGE} Hello, world!
***Keywords***
My Keyword [Arguments] ${path}
Directory Should Exist ${path}
3. Test Suite - A test suite created from a directory can have similar settings as a suite created from a test case file。- 1个或多个具有相同设置的Test Case File可以组成一个Test Suite, 多个Test Suites可以组成另一个更高层的Test Suite。
- Test Suite中的Test case file可以通过在名称中添加数字来进行排序,如01__some_tests.txt and 02__more_tests.txt。
- 每层次Test Suites中都应该包含一个初始化文件,即以__init__.txt命名的文件(从Python语法中借鉴而来)。
- 初始化文件的内容与Test case file文件中的内容基本相同,除了不支持test case table及一部分的settings table内容。
Table name Used for Setting table 2) Defining metadata for test suiteVariable table Defining variables
that can be used elsewhere in the test caseKeyword table Creating user keywords from existing lower-level keywords - 初始化文件主要作用是把具有相同Settings的test case file聚集在一起。
- 初如化文件中的主要内容:
- Documentation/Metada
- Suite Setup, Suite Teardown
- Test Setup, Test Teardown
- Force Tags,
- Default Tags,Test Template,Test Timeout - Not supported
- Examples:
***Settings***
Library OperatingSystem
Suite Setup Start Selenium Server
Force Tags example
***Variables***
${MESSAGE} Hello, world!
***Keywords***
My Keyword [Arguments] ${path}
Directory Should Exist ${path} -
Automation One By One - Robot Framework - Installation
2011-07-04 13:26:40
1. 什么是Robot Framework?
关于Robot Framework的快速入门可参见:http://www.virtuousprogrammer.com/?p=264
关于Robot Framework的详细说明参见:http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.5.7
2. Robot Framework Architecture
需要说明的是,Robot Framework本身并不与被测系统有任何直接的交互,它通过Test Libraries或是一些测试工具(如Selenium, AuotIt, Sikuli)作为驱动与被测系统进行交互,相当于是Test Libraries 或测试工具的front-end.
在接下来的详解中,我们使用Selenium作为Robot Framework的驱动。
3. 安装
Robot Framework需要Python或Jython环境,具体需要哪个环境主要是看你使用的Test Libraries或是Test Tools的需要,如果使用Sikuli作为测试工具则需要安装Jpython.
我们选择Python.
(1). 先安装Python(2.5+),没有可从如下地址下载:http://www.python.org/
(2). 下载Robot Framework,有几种安装方法可用,参见Installation
MacOSX安装方式:转到Robot Framework安装目录
python setup.py install
MacOSX安装方式:- 转到Selenium Library安装目录
python setup.py install
为了能方便地通过命令行运行Robot Framework的脚本,需要设置环境变量,对于Unix类的操作系统环境变量是自动完成的,但是Windows操作系统需要手动设置,具体的方法参见:http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.5.7#setting-up-environment
(5). 验证安装$ pybot --version
Robot Framework 2.5 (Python 2.6.x on darwin)
-
Automation One By One - Outline
2011-07-04 09:28:53
公司采用的敏捷的开发模式,需求拆分成Userstories, 这些Uerstories划分成若干阶段来完成,每个阶段大概2-3周,一个阶段被称为一个迭代,每个迭代完成完成优先级较高的Userstories.
敏捷开发模式中的测试,每个迭代中不仅要完成本迭代的Userstories的测试,还要考虑与前一迭代功能的回归测试,随着完成的Userstories越多,Tester要测试的Cases也会越来越多,工作量也会越来越大,而且重复性的工作容易使人麻痹。为了确保已经完成的功能不受新功能或是Bug修复的影响,减轻Tester的工作量,提高工作效率,我们决定针对功能模块引入自动化。
引用自动化我们考虑了以下几个方面-5W1H:
1. Why - 上面已经列明了原因,说明了我们要进行自动化测试的目的。
2. Who - 谁会参与自动化测?参与人员的编程水平如何?- 目前公司没有能力招聘高级的自动化测试人员,参与人员主要是原先做黑盒测试的Tester及刚毕业的计算机专业实习生,所以选择的工具要尽量简单易学,上手快。
- 但同时又要满足我们对自动化测试工具的要求:
- 即要支持网页测试也要支持手机软件测试。
- 要有完整的测试框架,能生成详细的测试报告。
- 每个检查点均有详细的执行结果;
- 输入每个测试用例的执行结果;
- 有日志。
- 要有可使用的IDE。
- 生成的脚本要具备可维护性,移植性及重复性。
- 批量、定制执行、自动运行。
- 异常处理机制。
- 版本管理。
4. When - 什么时候引入自动化?- 因为自动化测试团队的能力有限,我们还没有办法做到测试驱动开发,所以我们选定在下个迭代完成上个迭代的自动化开发工作,即落后一迭代开始自动化。
- 对于安全或性能自动化测试最好是在有稳定的版本后再进行。
5. Which/Where - 自动化测试的范围?- 功能、性能、安全、单元测试。
- 稳定但重复性比较高的。
- 关键功能点
- 手动测试很难办到
- 。。。
我的栏目
标题搜索
我的存档
数据统计
- 访问量: 123323
- 日志数: 79
- 建立时间: 2008-02-14
- 更新时间: 2013-08-09