首先,介紹一下robotframework,oschina這麼介紹:html
Robot Framework 是一個關鍵詞驅動的自動測試框架。測試用例位於HTML或者TSV(以tab分隔值)文件,使用在測試庫中實現的關鍵詞來在測試中運行程序。由於 Robot Framework 是靈活和可擴展的,因此它很合適用於測試具備多種接口的複雜軟件:用戶接口,命令行,webservice,編程接口等。node
Robot Framework 和 Cumcumber http://www.oschina.net/p/cucumber 具備類似的能力,都屬於BDD自動化測試工具。 可是Cumcumber只能順序驗證測試步驟,好比:python
Given 我在登陸頁 When 我輸入賬號"zhangsan" And 我輸入密碼"123456" And 我點擊登陸按鈕 Then 我能看到個人暱稱"張三"
上述的 "我在登陸頁" 等步驟的定義,都在Cumcumber的step_definitions.rb中,用ruby語言定義。
若是對Cumcumber測試安卓手機APP感興趣,能夠參閱 使用calabash測試開源中國Android客戶端mysql
Robot Framework在語義級別就提供了FOR循環和IF判斷,自定義Keyword直接在.robot文件中,不須要寫一句Python語句。linux
而後再去官網 http://robotframework.org/ ,到TestLibraries看看都提供了什麼測試庫:nginx
STANDARD庫中包含OperatingSystem,String,Collections,提供了調用本地shell命令,字符串處理,和Python集合的處理能力。git
EXTERNAL庫中有手機APP測試相關的測試庫、網頁測試相關、http測試相關、數據庫相關、ssh相關。github
我最看中的就是其中SSHLibrary,它提供ssh登陸和執行遠程命令的能力,並能用sftp上傳下載文件。
SSHLibrary對python庫paramiko進行了封裝,因此他是Farbric的兄弟,Fabric經常使用於自動化運維,可是缺乏對運維結果的檢測能力。web
因此,Robot Framework+SSHLibrary天生就適合作網站的自動化運維質量檢測。sql
後面經過一個一個的小例子,來演示Robot Framework+SSHLibrary怎樣達到自動化運維質量檢測
Python默認已安裝
pip: python環境下模塊安裝工具
sudo apt-get install python-pip
python-dev: 某些python模塊安裝須要Python.h,因此要安裝python-dev
sudo apt-get install python-dev
robotframework: http://robotframework.org
sudo pip install robotframework
若是使用默認pip源很慢,能夠指定豆瓣的pip源:
sudo pip install robotframework -i http://pypi.douban.com/simple
SSHLibrary: https://github.com/robotframework/SSHLibrary
pip install robotframework-sshlibrary
只要把Debian對應安裝命令中的apt-get 改爲yum, dev改爲devel Python默認已安裝
pip: python環境下模塊安裝工具
sudo yum install python-pip
python-devel: 某些python模塊安裝須要Python.h,因此要安裝python-devel
sudo yum install python-devel
robotframework: http://robotframework.org
sudo pip install robotframework
SSHLibrary: https://github.com/robotframework/SSHLibrary
pip install robotframework-sshlibrary
示例來自: http://robotframework.org/SSHLibrary/
注意:
測試用例文件:
shen@debian:~/robotframework$ cat executing-commands.robot *** Settings *** Documentation This example demonstrates executing commands on a remote machine ... and getting their output and the return code. ... ... Notice how connections are handled as part of the suite setup and ... teardown. This saves some time when executing several test cases. Library SSHLibrary Suite Setup Open Connection And Log In Suite Teardown Close All Connections *** Variables *** ${HOST} localhost ${USERNAME} shen ${PASSWORD} 123456 *** Test Cases *** Execute Command And Verify Output [Documentation] Execute Command can be used to ran commands on the remote machine. ... The keyword returns the standard output by default. ${output}= Execute Command echo Hello SSHLibrary! Should Be Equal ${output} Hello SSHLibrary! Execute Command And Verify Return Code [Documentation] Often getting the return code of the command is enough. ... This behaviour can be adjusted as Execute Command arguments. ${rc}= Execute Command echo Success guaranteed. return_stdout=False return_rc=True Should Be Equal ${rc} ${0} Executing Commands In An Interactive Session [Documentation] Execute Command always executes the command in a new shell. ... This means that changes to the environment are not persisted ... between subsequent Execute Command keyword calls. ... Write and Read Until variants can be used to operate in the same shell. Write cd .. Write echo Hello from the parent directory! ${output}= Read Until directory! Should End With ${output} Hello from the parent directory! *** Keywords *** Open Connection And Log In Open Connection ${HOST} Login ${USERNAME} ${PASSWORD}
gedit打開executing-commands.robot的效果:
執行結果:
shen@debian:~/robotframework$ pybot executing-commands.robot ============================================================================== Executing Commands :: This example demonstrates executing commands on a rem... ============================================================================== Execute Command And Verify Output :: Execute Command can be used t... | PASS | ------------------------------------------------------------------------------ Execute Command And Verify Return Code :: Often getting the return... | PASS | ------------------------------------------------------------------------------ Executing Commands In An Interactive Session :: Execute Command al... | PASS | ------------------------------------------------------------------------------ Executing Commands :: This example demonstrates executing commands... | PASS | 3 critical tests, 3 passed, 0 failed 3 tests total, 3 passed, 0 failed ============================================================================== Output: /home/shen/robotframework/output.xml Log: /home/shen/robotframework/log.html Report: /home/shen/robotframework/report.html
爲了能方便演示,每一個例子都有各編號如100,對應的代碼目錄~/robotframework/100 上述基本ssh例子先簡化以下:
shen@debian:~/robotframework/100$ cat example-100.robot *** Settings *** Documentation ssh示例 Library SSHLibrary Suite Setup Open Connection And Log In Suite Teardown Close All Connections *** Variables *** ${HOST} localhost ${USERNAME} shen ${PASSWORD} 123456 *** Test Cases *** 遠程執行命令並檢驗輸出 ${output}= Execute Command echo Hello SSHLibrary! Should Be Equal ${output} Hello SSHLibrary! *** Keywords *** Open Connection And Log In Open Connection ${HOST} Login ${USERNAME} ${PASSWORD}
說明: 上述檢驗內容是ssh到localhost,執行shell命令: echo Hello SSHLibrary!
,
應該看到stdout爲 Hello SSHLibrary!
下面用手工執行ssh來模擬上述檢驗:
在使用if判斷變量output時,碰到了單引號和雙引號的替換規則問題,並且bash的if-else-fi真心難寫。
只有下面if中的單雙引號使用是正確的:
if [ "$output" == 'Hello SSHLibrary!' ]; then echo -e "| \033[32mPASS\033[0m |"; else echo -e "| \033[31mFAIL\033[0m |"; fi
回到正題,我想在pybot命令行直接輸入ssh密碼,能夠這樣執行:
由於輸入的是錯誤密碼,因此提示: Authentication failed for user 'shen'.
規則1: pybot命令行中輸入的變量值會覆蓋robot文件中*** Variables ***
中定義的變量值
上面的example-100.robot運行時,屏幕上只打印了testcase名稱和測試結果綠色PASS或紅色FAIL。
在運行目錄下生成了3個文件:output.xml, log.html, report.html,先分別打開看看:
我不習慣去看html文件,因此我想在運行時直接打印output變量的內容。
先去官網找到Log To Console的幫助信息: http://robotframework.org/robotframework/latest/libraries/BuiltIn.html#Log%20To%20Console
官網幫助中的robotframework測試用例格式都是表格,可是最實用的是txt格式,測試用例文件的後綴能夠是.txt或.robot
表格格式的分隔方式就是一個一個格子,txt格式對應分隔符是兩個以上空格或者一個以上Tab。
shen@debian:~/robotframework/110$ cat example-110.robot *** Settings *** Documentation ssh示例 Library SSHLibrary Suite Setup Open Connection And Log In Suite Teardown Close All Connections *** Variables *** ${HOST} localhost ${USERNAME} shen ${PASSWORD} 123456 *** Test Cases *** 遠程執行命令並檢驗輸出 ${output}= Execute Command echo Hello SSHLibrary! Log To Console \n\${output}的內容:"\x1b[1;33m${output}\x1b[0m" Should Be Equal ${output} Hello SSHLibrary! *** Keywords *** Open Connection And Log In Open Connection ${HOST} Login ${USERNAME} ${PASSWORD}
請注意新增行:
Log To Console \n\${output}的內容:"\x1b[1;33m${output}\x1b[0m"
執行測試結果:
說明: \x1b[1;33m${output}\x1b[0m 是以高亮黃色打印變量${output}的內容。\x1b與echo打印彩色時的\033是相同的。
可是robotframework測試用例文件的語法中不支持\0nn八進制,只支持\xnn 十六進制。 Log To Console右邊必須先輸入兩個以上空格或1個以上Tab,再輸入變量;兩個變量之間也要如此分隔。
規則2: robotframework測試用例文件中字符$要用$轉義,\xnn指定十六進制字符。
首先看一下pybot的-h幫助: 執行命令: pybot -h
,其中的-v參數能夠指定一個變量的值,-V能夠從一個文件中指定多個變量。
shen@debian:~/robotframework/120$ cat node-list.py SSH_SERVERS = ['node01', 'node02', 'node03'] NODE_IP_MAP = { 'node01':'localhost', 'node02':'127.0.0.1', 'node03':'192.168.0.107', } shen@debian:~/robotframework/120$ cat example-120.robot *** Settings *** Documentation ssh示例 Library Collections Library SSHLibrary Suite Teardown Close All Connections *** Variables *** *** Test Cases *** 遠程執行命令並檢驗輸出 :FOR ${node} IN @{SSH_SERVERS} \ ${node_ip}= Get From Dictionary ${NODE_IP_MAP} ${node} \ Log To Console \n正在登陸 ${node}(${node_ip}) ... \ Open Connection And Log In "${node_ip}" \ Log To Console \n正在${node}(${node_ip})執行命令: echo Hello SSHLibrary! \ ${output}= Execute Command echo Hello SSHLibrary! \ Log To Console \n\${output}的內容:"\x1b[1;33m${output}\x1b[0m" \ Should Be Equal ${output} Hello SSHLibrary! *** Keywords *** Open Connection And Log In "${node_ip}" Open Connection ${node_ip} Login ${USERNAME} ${PASSWORD}
請注意例子120的幾處新內容:
shen@debian:~/robotframework/130$ cat node-list.py PYTHON_SERVERS = ['node01', 'node03'] SSH_SERVERS = ['node01', 'node02', 'node03'] NODE_IP_MAP = { 'node01':'localhost', 'node02':'127.0.0.1', 'node03':'192.168.0.107', } shen@debian:~/robotframework/130$ cat versions.py VERSIONS = { 'python':'2.7.3', 'gcc':'4.7.2', 'ssh':'OpenSSH_6.0p1', } shen@debian:~/robotframework/130$ cat example-130.robot *** Settings *** Documentation ssh示例 Library Collections Library SSHLibrary Suite Teardown Close All Connections *** Variables *** *** Test Cases *** 遠程執行命令並檢驗輸出 :FOR ${node} IN @{SSH_SERVERS} \ ${node_ip}= Get From Dictionary ${NODE_IP_MAP} ${node} \ Log To Console \n正在登陸 ${node}(${node_ip}) ... \ Open Connection And Log In "${node_ip}" \ Log To Console \n正在${node}(${node_ip})執行命令: echo Hello SSHLibrary! \ ${output}= Execute Command echo Hello SSHLibrary! \ Log To Console \n\${output}的內容:"\x1b[1;33m${output}\x1b[0m" \ Should Be Equal ${output} Hello SSHLibrary! 檢查python版本 :FOR ${node} IN @{PYTHON_SERVERS} \ ${node_ip}= Get From Dictionary ${NODE_IP_MAP} ${node} \ Open Connection And Log In "${node_ip}" \ Log To Console \n正在${node}(${node_ip})執行命令: python --version 2>&1 | cut -d' ' -f 2 \ ${output}= Execute Command python --version 2>&1 | cut -d' ' -f 2 \ ${version}= Get From Dictionary ${VERSIONS} python \ Log To Console \npython版本${output} == 指望版本${version} ? \ Should Be Equal ${output} ${version} *** Keywords *** Open Connection And Log In "${node_ip}" Open Connection ${node_ip} Login ${USERNAME} ${PASSWORD}
執行測試命令:
pybot -v USERNAME:shen -v PASSWORD:123456 -V node-list.py -V versions.py example-130.robot
若是更改指望版本爲2.6.6:
shen@debian:~/robotframework/130$ cat versions.py VERSIONS = { 'python':'2.6.6', 'gcc':'4.7.2', 'ssh':'OpenSSH_6.0p1', }
測試結果以下:
由於測試用例「檢查python版本」中的第一個結點的python版本檢查斷言:Should Be Equal ${output} ${version}
失敗,
因此robotframework直接退出本測試用例的執行,不會再去檢查第二個結點的python版本。
shen@debian:~/robotframework/140$ cat example-140.robot *** Settings *** Documentation 交互式檢查python版本 Library Collections Library SSHLibrary Suite Teardown Close All Connections *** Variables *** *** Test Cases *** 交互式檢查python版本 :FOR ${node} IN @{PYTHON_SERVERS} \ ${node_ip}= Get From Dictionary ${NODE_IP_MAP} ${node} \ Open Connection And Log In "${node_ip}" \ Write python \ ${output}= Read Until >>> \ Log To Console \n${node}(${node_ip})執行命令python的輸出:---\n${output}\n--- \ ${version}= Get From Dictionary ${VERSIONS} python \ Log To Console \n${node}(${node_ip})的python版本 == ${version} ? \ Should Contain ${output} ${version} *** Keywords *** Open Connection And Log In "${node_ip}" Open Connection ${node_ip} Login ${USERNAME} ${PASSWORD}
執行測試結果:
shen@debian:~/robotframework/150$ cat keywords.robot *** Settings *** Library Collections Library SSHLibrary *** Keywords *** Check Python Version "${servers}" "${version}" :FOR ${node} IN @{servers} \ ${node_ip}= Get From Dictionary ${NODE_IP_MAP} ${node} \ Open Connection ${node_ip} \ Login ${USERNAME} ${PASSWORD} \ Write python \ ${output}= Read Until >>> \ Log To Console \n${node}(${node_ip})執行命令python的輸出:---\n${output}\n--- \ Log To Console \n${node}(${node_ip})的python版本 == ${version} ? \ Should Contain ${output} ${version} shen@debian:~/robotframework/150$ cat example-150.robot *** Settings *** Documentation 交互式檢查python版本 Resource keywords.robot Suite Teardown Close All Connections *** Variables *** *** Test Cases *** 交互式檢查python版本 ${version}= Get From Dictionary ${VERSIONS} python Check Python Version "${PYTHON_SERVERS}" "${version}" *** Keywords *** shen@debian:~/robotframework/150$ pybot -v USERNAME:shen -v PASSWORD:123456 -V node-list.py -V versions.py example-150.robot ============================================================================== Example-150 :: 交互式檢查python版本 ============================================================================== 交互式檢查python版本 . node01(localhost)執行命令python的輸出:--- Python 2.7.3 (default, Mar 13 2014, 11:03:55) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> --- node01(localhost)的python版本 == 2.7.3 ? node03(192.168.0.107)執行命令python的輸出:--- Python 2.7.3 (default, Mar 13 2014, 11:03:55) [GCC 4.7.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> --- node03(192.168.0.107)的python版本 == 2.7.3 ? 交互式檢查python版本 | PASS | ------------------------------------------------------------------------------ Example-150 :: 交互式檢查python版本 | PASS | 1 critical test, 1 passed, 0 failed 1 test total, 1 passed, 0 failed ============================================================================== Output: /home/shen/robotframework/150/output.xml Log: /home/shen/robotframework/150/log.html Report: /home/shen/robotframework/150/report.html shen@debian:~/robotframework/150$
複用example-150的測試用例
pybot -C on -v USERNAME:shen -v PASSWORD:123456 -V node-list.py -V versions.py example-150.robot | tee ../160/color_output.txt
歡迎你們繼續提出問題,我將盡力以上述example的方式給出答案。