RobotFramework 测试自动化使用总结

安装环境

有个比较好的教程getting-started-robotfamework

如果需要在Linux上运行:

  1. 准备一个Linux机器,安装robot framework
    robotframework_pip_list.txt
  2. 开通samba
    Quick setup samba service
  3. 准备一个Windows机器,安装ride

如果需要在Linux上写UI automation

  1. 安装seleniumLibrary:
pip install --upgrade robotframework-seleniumlibrary
  1. 安装Chrome + Chromedriver
yum install google-chrome-stable

其他好用的安装方法
3. 找到chrome对应的chromedriver 版本,并下载 https://chromedriver.chromium.org/
4. 将下载的chromedriver 放到$PATH里的目录下
5. 在/usr/bin/google-chrome 脚本的最后填加参数
在这里插入图片描述

常用keyword

官方教程
Standard-libraries
SeleniumLibrary
RequestsLibrary

run keyword if
set variable if
Run
Fetch From Right
Fetch From Left
Sleep
Wait Until Keyword Succeeds
SSHLibrary.Open Connection I P 4 a l i a s = {IP4} alias= IP4alias={Alias}
Run Keyword If ‘${usekey}’==‘True’ SSHLibrary.Login With Public Key
${ret} SSHLibrary.Execute Command ${cmd}
SSHLibrary.close Connection
SSHLibrary.Switch Connection ${ssh_session}
Should Contain
Should be Equal/Should be Equal As Strings/Should be Equal As Integers

Open Browser
maximize browser window
wait until element is visible
Select Frame
Unselect Frame
wait until page contains element
Wait Until element Contains
frame Should Contain
Get Element Attribute
close all browsers

可以按住Control键查看keyword用法

开始构建

Example
简单写了两个case,经常用到的Libraries如图。
其中config.robot 可以放一些用户名密码或者key等不应该放到git上的信息,然后把这个文件放到git ignore里,不上传。

运行方法

结果
Example:
robot --test “casename” robotfile
robot -i sometag robotpath
robot -e deletedORnotReady -i BVT -d logPath --output output1.xml testsuitesPath
robot --rerunfailed logPath/output1.xml --output logPath/output2.xml testsuitesPath

解析log

GenerateContent.py

import os
import sys
import PasRes
import re
import AnalyzeRerunResults
import time

try:
        import xml.etree.cElementTree as ET
except ImportError:
        import xml.etree.ElementTree as ET

CONTENT_FORMATER = '''
<html>
<head>
<style>
body {
    font-size: 20px;
    font-family: Calibri;
    line-height: 19px;
}
</style>
</head>
<body>
Dear All:<br/>
This is the <strong>automation test report.</strong><br/>
<strong>Start Time:</strong> %s<br/>
<strong>Elapsed Time:</strong> %s<br/>
<strong>Total cases:</strong> %s<br/>
<strong>Failed cases:</strong> <font color="red">%s</font><br/>
<strong>Failed cases list:</strong><br/>
<font color='red'>%s</font>
<br/>
Thanks.<br/>
</body>
</html>
'''

def ParseRes(respath):
    f = o
    pen(respath,'r')
    resstr = f.read()
    f.close()
    reg = '{.*"elapsed":".*?","fail":(.*?),"label":"All Tests","pass":(.*?)}'
    m = re.search(reg,resstr)
    return m.group(1), m.group(2)

def ParseStime(respath):
    f = open(respath, 'r')
    str = f.read()
    f.close()
    begin = 'window.output["baseMillis"] = '
    end = ";"
    index = str.find(begin)
    index+=len(begin)
    sub_str = str[index:]
    index = sub_str.find(end)
    #print sub_str[:index]
    millsec = int(sub_str[:index])
    StartTime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(millsec/1000))
    
    reg = '{.*"elapsed":"(.*?)","fail":.*?,"id":".*?","label":"Testsuites","name":"Testsuites","pass":.*?}'
    elapTime = re.search(reg,str)
    return StartTime,elapTime.group(1)

def SummaryRes(res):
    if res == None:
        print 'get result dictionary fail!'
        sys.exit(1)
    else:
        sum = int(res[0]) + int(res[1])
        fl  = res[0]
        if int(res[0]) > 0:
            flag = 'FAIL'
        else:
            flag = 'PASS'

        return str(sum), fl, flag


def gen_fclist_htmlstring(cl,fcl):
    clstr = ''
    fclstr = ''
    for l in cl:
        clstr = clstr + str(l) + '<br/>'
    for i in fcl:
        fclstr = fclstr + str(i) + '<br/>'

    return clstr,fclstr

def get_fail_case_list(outputpath):
    tree = ET.parse(outputpath)
    count = 0
    failcasesname = []
    for elem in tree.iter(tag='test'):
        elemattri = elem.attrib
        for key in elemattri:
            if key == "name":
                testname = elemattri[key]
                status = elem.find("status")
                for key in status.attrib.keys():
                    if status.attrib[key] == "FAIL":
                        failcasesname.append(testname)

    str_fail_list = ''
    for l in failcasesname: 
            str_fail_list = str_fail_list + str(l) + '<br/>'
    print str_fail_list
    return str_fail_list

def gen_title_resultcontent(ReportFile, OutputFile):
    pt = ParseStime(ReportFile)
    sres = ParseRes(ReportFile)
    res = SummaryRes(sres)
    print res
    subject = 'AUTOMATION TEST REPORT :' + res[2]
    fl =  get_fail_case_list(OutputFile)
    content = CONTENT_FORMATER % (str(pt[0]), str(pt[1]), str(res[0]), str(res[1]), fl)
    return subject,content


if __name__ == '__main__':
    sub,cont = gen_title_resultcontent()
    print sub
    print cont

发送report

# -*- coding: utf-8 -*-

import types
import os
import logging
import boto
import GenerateContent
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE
from email import  Encoders
from boto.ses import SESConnection
import sys
import ftplib
import datetime
rootPath =  os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
logPath = os.path.join(rootPath, 'log')
binPath = os.path.join(rootPath, 'bin')
LogFilePath = os.path.join(logPath,'log.html')
ReportFilePath = os.path.join(logPath,'report.html')
OutputFilePath = os.path.join(logPath,'output.xml')


class AmazonSender(object):
    client = None

    def __init__(self, aws_key, aws_secret,proxy=None,proxy_port=None):
        self.aws_key = aws_key
        self.aws_secret = aws_secret
        self.proxy = proxy
        self.proxy_port = proxy_port

    def send_email(self, sender,
                         to_addresses,
                         subject,
                         text,
                         html=None,
                         files = [],
                         fileDisplayName = '',
                         reply_addresses=None,
                         sender_ascii=None):
        if not sender_ascii:
            sender_ascii = sender
        client = self.get_client()

        message = MIMEMultipart('alternative')
        message.set_charset('UTF-8')

        message['Subject'] = _encode_str(subject)
        message['From'] = _encode_str(sender)

        message['To'] = _convert_to_strings(to_addresses)

        if reply_addresses:
            message['Reply-To'] = _convert_to_strings(reply_addresses)

        message.attach(MIMEText(_encode_str(text), 'plain'))
        for file in files:
            part = MIMEBase('application', "octet-stream")
            part.set_payload( open(file,"rb").read() )
            Encoders.encode_base64(part)
            if fileDisplayName:
                part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(fileDisplayName))
            else:
                part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
            message.attach(part)

        if html:
            message.attach(MIMEText(_encode_str(html), 'html'))
        SENDMAIL_MAX_RETRY = 1
        for i in xrange(SENDMAIL_MAX_RETRY):
            try:
                client.send_raw_email(message.as_string(), sender_ascii, destinations=to_addresses)
                return True
            except Exception,e:
                logging.exception(e.message)
        return False

    def vertify_email(self, email):
        client = self.get_client()
        return client.verify_email_address(email)

    def get_client(self):
        if not self.client:
            self.client = boto.ses.connect_to_region(
                   'us-west-2',
                   aws_access_key_id=self.aws_key,
                   aws_secret_access_key=self.aws_secret)
        return self.client


#--- Helpers ----------------------------------------------
def _convert_to_strings(list_of_strs):
    if isinstance(list_of_strs, (list, tuple)):
        result = COMMASPACE.join(list_of_strs)
    else:
        result = list_of_strs
    return _encode_str(result)

def _encode_str(s):
    if type(s) == types.UnicodeType:
        return s.encode('utf8')
    return s


def send_report_email():
    title,contenttext = GenerateContent.gen_title_resultcontent(ReportFilePath,OutputFilePath)
    recvList = ['testauto@testauto.com']
    sender = AmazonSender(sys.argv[1],sys.argv[2])
    sender.send_email('testauto@testauto.com', recvList, title,text=None,html=contenttext, files=[])

def uploadThis(myFTP, path):
    files = os.listdir(path)
    for f in files:
        fh = open(f, 'rb')
        myFTP.storbinary('STOR %s' % f, fh)
        fh.close()

def UploadReportDirToFTP(LocalDir,FTPServer,Usr,Pwd,FTPPath):
    myFTP = ftplib.FTP(FTPServer, Usr, Pwd)
    myFTP.cwd(FTPPath)
    d = datetime.datetime.now()
    dsuf = d.strftime("%b-%d-%y-%H-%M")
    myFTP.mkd(dsuf)
    myFTP.cwd(dsuf)
    os.chdir(LocalDir)
    uploadThis(myFTP,LocalDir)

if __name__ == "__main__":
    sendmailpath = os.path.abspath(__file__)
    logpath = os.path.join(os.path.dirname(sendmailpath), "..","..","log")
   # UploadReportDirToFTP(logpath, 'server', 'user', 'password', ReportLocation)
    send_report_email()


脚本放到git上,然后通过Jenkins job定时触发

pipeline{
    agent{
        node{label 'automation'}
    }

    parameters {
        choice choices: ['a', 'b', 'c', 'd'], description: '', name: 'ENV'
        choice choices: ['x', 'y'], description: '', name: 'Region'
		listGitBranches branchFilter: 'refs.*/(.*)', credentialsId: '', defaultValue: 'develop', name: 'Branch', quickFilterEnabled: false, remoteURL: 'git@test.git', selectedValue: 'DEFAULT', sortMode: 'NONE', tagFilter: '*', type: 'PT_BRANCH'
    }
	stages{
		stage('RunCase'){
			steps{
				echo "Running Case!"
				script{
					def branches = [:]

					branches["RunCaseA"] = {
						build job: 'Automation_parallel_A',parameters: [
						    [$class: 'StringParameterValue', name: 'ENV', value:String.valueOf(ENV)],
							[$class: 'StringParameterValue', name: 'Region', value:String.valueOf(Region)]]							
					}
					branches["RunCaseB"] = {
						build job: 'Automation_parallel_B',parameters: [
						    [$class: 'StringParameterValue', name: 'ENV', value:String.valueOf(ENV)],
							[$class: 'StringParameterValue', name: 'Region', value:String.valueOf(Region)]]
					}
				parallel branches 
				}
		   }
		}
		stage('SendMail'){
			steps{
				build job: 'Sendmail',parameters: [
					[$class: 'StringParameterValue', name: 'ENV', value:String.valueOf(ENV)],
					[$class: 'StringParameterValue', name: 'Region', value:String.valueOf(Region)]]
			}
		}		
	}
}

Build periodically: H 23 * * *

这样基本流程就通了,补产品相关的case就可以了。有不足的以后补充吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
RobotFramework中 中SSHLibrary学习与总结 学习与总结 ⼀、安装SSHLibrary ⼆.关键字 1.与连接相关的 Open Connection Get Connection Get Connections Switch Connection Close Connection Close All Connections Login Login With Public Key Set Client Configuration Set Default Configuration Enable Ssh Logging 2.与⽂件/⽬录相关的 2.1 File Should Exist , File Should Not Exist, Directory Should Exist , Directory Should Not Exist 2.2 List Directory, List Files In Directory , List Directories In Directory 2.3 Put Directory ,Get Directory,Put File,Get File 3.与读写执⾏相关的 Write Write Bare Write Until Expected Output Read Read Until Read Until Prompt Read Until Regexp Execute Command Start Command Read Command Output ⼀、安装 ⼀、安装SSHLibrary 安装命令:pip install robotframework-sshlibrary ⼆ ⼆.关键字 关键字 1.与连接相关的 与连接相关的 Open Connection ⽤法: [ host " alias=None " port=22 " timeout=None " newline=None " prompt=None " term_type=None " width=None " height=None " path_separator=None " encoding=None ] 默认设置:timeout=3 seconds, newline=LF, prompt=None, loglevel=INFO, term_type=vt100, width=80,height=24, path_separator=/, encoding=UTF-8.其 中,newline=LF/CRLF(\n,\r\n) 更改默认设置: 1.导⼊库时: Library SSHLibrary 10 seconds prompt=$ 2.使⽤ Set Client Configuration/Set Default Configuration 3.调⽤Open Connection时: 结果: ${con1} =index=1 path_separator=/ prompt=# width=80 newline= height=24 encoding=UTF-8 alias=backend host=10.69.140.112 timeout=3 seconds term_type=vt100 port=2222 Get Connection ⽤法:[ index_or_alias=None " index=False " host=False " alias=False " port=False " timeout=False " newline=False " prompt=False " term_type=False " width=False " height=False " encoding=False ] 1.获取connection的信息,如果调⽤时没有加 index_or_alias,返回当前的conection信息。 2.获取connection的特定属性信息,后边加属性名=⾮false/False字符串。 结果: ${con1} =index=1 path_separator=/ prompt=# width=80 newline= height=24 encoding=UTF-8 alias=backend host=10.69.140.112 timeout=3 seconds term_type=vt100 port=2222 ${con2} = (2222, 3.0) Get Connections ⽤法:没有输⼊值,获取所有打开的connection的信息 结果: ${con1} = index=1 path_separator=/ prompt=$ width

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值