低调大师

Robot Framework+SSHLibrary实现自动化运维质量检测

2015-2-10 8:48 16已围观 收藏 加入我们

Robot Framework+SSHLibrary介绍

首先,介绍一下robotframework,oschina这么介绍:

Robot Framework 是一个关键词驱动的自动测试框架。测试用例位于HTML或者TSV(以tab分隔值)文件,使用在测试库中实现的关键词来在测试中运行程序。因为 Robot Framework 是灵活和可扩展的,所以它很合适用于测试具有多种接口的复杂软件:用户接口,命令行,webservice,编程接口等。

Robot FrameworkCumcumber http://www.oschina.net/p/cucumber 具有相似的能力,都属于BDD自动化测试工具。 但是Cumcumber只能顺序验证测试步骤,比如:

Given  我在登录页
When  我输入帐号"zhangsan"
And      我输入密码"123456"
And      我点击登录按钮
Then    我能看到我的昵称"张三"

上述的 "我在登录页" 等步骤的定义,都在Cumcumber的step_definitions.rb中,用ruby语言定义。
如果对Cumcumber测试安卓手机APP感兴趣,可以参阅 使用calabash测试开源中国Android客户端

Robot Framework在语义级别就提供了FOR循环和IF判断,自定义Keyword直接在.robot文件中,不需要写一句Python语句。

然后再去官网 http://robotframework.org/ ,到TestLibraries看看都提供了什么测试库:

在此输入图片描述 STANDARD库中包含OperatingSystem,String,Collections,提供了调用本地shell命令,字符串处理,和Python集合的处理能力。

在此输入图片描述 EXTERNAL库中有手机APP测试相关的测试库、网页测试相关、http测试相关、数据库相关、ssh相关。

我最看中的就是其中SSHLibrary,它提供ssh登录和执行远程命令的能力,并能用sftp上传下载文件。
SSHLibrary对python库paramiko进行了封装,所以他是Farbric的兄弟,Fabric常用于自动化运维,但是缺少对运维结果的检测能力。

所以,Robot Framework+SSHLibrary天生就适合做网站的自动化运维质量检测。

自动化运行质量检测,包含那些内容?

  • mysql, mongo, nginx等工具的配置是否正确
  • mysql, mongo, nginx等工具的进程是否已崩溃
  • mysql, mongo, nginx的数据等目录的owner是否正确
  • 网站服务器各结点的网络配置是否正确
  • 各tomcat, jetty服务的版本是否符合预期

后面通过一个一个的小例子,来演示Robot Framework+SSHLibrary怎样达到自动化运维质量检测

Debian/Ubunbu下安装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

Redhat/CentOS 下安装Robot Framework+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

RobotFramework+SSHLibrary远程调用命令示例

示例来自: http://robotframework.org/SSHLibrary/

注意

  • 下面的${HOST}, ${USERNAME}, ${PASSWORD} 请使用自己远程机器名、帐号和密码
  • 还要确保远程机器已经开启了sshd服务

测试用例文件:

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

在此输入图片描述

Robot Framework+SSHLibrary实现自动化运维质量检测

example-100: 直接在命令行输入ssh密码

为了能方便演示,每个例子都有各编号如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-110: 执行测试时打印调试信息

上面的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指定十六进制字符。

example-120: 我要把服务器的结点信息保存在外部文件中

首先看一下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的几处新内容:

  • node-list.py 定义了所有结点的ip信息和ssh服务器列表,使用python的列表和字典定义
  • example-120.robot 中引入了新测试库: Collections http://robotframework.org/robotframework/latest/libraries/Collections.html
  • 重新定义了关键字:Open Connection And Log In,可以接受参数${node_ip}
  • 使用FOR循环遍历SSH_SERVERS中的每个结点。

example-130: 我要确保服务器结点的python版本都是2.7.3

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版本。

example-140: 检查交互式输出的内容

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}

执行测试结果:

在此输入图片描述

example-150: 关键字定义放在独立文件中

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-160: 执行测试的彩色打印导出到文件

复用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的方式给出答案。

文章转载至:https://my.oschina.net/fitnessefan/blog/377138
收藏 (0)

文章评论

共有0条评论来说两句吧...