当前位置: 移动技术网 > IT编程>脚本编程>Python > Python http接口自动化测试框架实现方法示例

Python http接口自动化测试框架实现方法示例

2019年01月09日  | 移动技术网IT编程  | 我要评论

瑶源葆春,yahoo音乐,ailete北京

本文实例讲述了python http接口自动化测试框架实现方法。分享给大家供大家参考,具体如下:

一、测试需求描述

对服务后台一系列的http接口功能测试。

输入:根据接口描述构造不同的参数输入值

输出:xml文件

eg:http://xxx.com/xxx_product/test/content_book_list.jsp?listid=1

二、实现方法

1、选用python脚本来驱动测试

2、采用excel表格管理测试数据,包括用例的管理、测试数据录入、测试结果显示等等,这个需要封装一个excel的类即可。

3、调用http接口采用python封装好的api即可

4、测试需要的http组装字符转处理即可

5、设置2个检查点,xml文件中的返回值字段(通过解析xml得到);xml文件的正确性(文件对比)

6、首次执行测试采用半自动化的方式,即人工检查输出的xml文件是否正确,一旦正确将封存xml文件,为后续回归测试的预期结果,如果发现错误手工修正为预期文件。(注意不是每次测试都人工检查该文件,只首次测试的时候才检查)

三、excel表格样式

四、实现代码(代码才是王道,有注释很容易就能看明白的)

1、测试框架代码

#****************************************************************
# testframe.py
# author   : vince
# version  : 1.1.2
# date    : 2011-3-14
# description: 自动化测试平台
#****************************************************************
import os,sys, urllib, httplib, profile, datetime, time
from xml2dict import xml2dict
import win32com.client
from win32com.client import dispatch
import xml.etree.elementtree as et
#import mysqldb
#excel表格中测试结果底色
ok_color=0xffffff
ng_color=0xff
#nt_color=0xffff
nt_color=0xc0c0c0
#excel表格中测试结果汇总显示位置
testtime=[1, 14]
testresult=[2, 14]
#excel模版设置
#self.titleindex=3    #excel中测试用例标题行索引
#self.casebegin =4    #excel中测试用例开始行索引
#self.argbegin  =3    #excel中参数开始列索引
#self.argcount =8    #excel中支持的参数个数
class create_excel:
  def __init__(self, sfile, dtitleindex=3, dcasebegin=4, dargbegin=3, dargcount=8):
    self.xlapp = win32com.client.dispatch('et.application')  #ms:excel wps:et
    try:
      self.book = self.xlapp.workbooks.open(sfile)
    except:
      print_error_info()
      print "打开文件失败"
      exit()
    self.file=sfile
    self.titleindex=dtitleindex
    self.casebegin=dcasebegin
    self.argbegin=dargbegin
    self.argcount=dargcount
    self.allresult=[]
    self.retcol=self.argbegin+self.argcount
    self.xmlcol=self.retcol+1
    self.resultcol=self.xmlcol+1
  def close(self):
    #self.book.close(savechanges=0)
    self.book.save()
    self.book.close()
    #self.xlapp.quit()
    del self.xlapp
  def read_data(self, isheet, irow, icol):
    try:
      sht = self.book.worksheets(isheet)
      svalue=str(sht.cells(irow, icol).value)
    except:
      self.close()
      print('读取数据失败')
      exit()
    #去除'.0'
    if svalue[-2:]=='.0':
      svalue = svalue[0:-2]
    return svalue
  def write_data(self, isheet, irow, icol, sdata, color=ok_color):
    try:
      sht = self.book.worksheets(isheet)
      sht.cells(irow, icol).value = sdata.decode("utf-8")
      sht.cells(irow, icol).interior.color=color
      self.book.save()
    except:
      self.close()
      print('写入数据失败')
      exit()
  #获取用例个数
  def get_ncase(self, isheet):
    try:
      return self.get_nrows(isheet)-self.casebegin+1
    except:
      self.close()
      print('获取case个数失败')
      exit()
  def get_nrows(self, isheet):
    try:
      sht = self.book.worksheets(isheet)
      return sht.usedrange.rows.count
    except:
      self.close()
      print('获取nrows失败')
      exit()
  def get_ncols(self, isheet):
    try:
      sht = self.book.worksheets(isheet)
      return sht.usedrange.columns.count
    except:
      self.close()
      print('获取ncols失败')
      exit()
  def del_testrecord(self, suiteid):
    try:
      #为提升性能特别从for循环提取出来
      nrows=self.get_nrows(suiteid)+1
      ncols=self.get_ncols(suiteid)+1
      begincol=self.argbegin+self.argcount
      #提升性能
      sht = self.book.worksheets(suiteid)
      for row in range(self.casebegin, nrows):
        for col in range(begincol, ncols):
          str=self.read_data(suiteid, row, col)
          #清除实际结果[]
          startpos = str.find('[')
          if startpos>0:
            str = str[0:startpos].strip()
            self.write_data(suiteid, row, col, str, ok_color)
          else:
            #提升性能
            sht.cells(row, col).interior.color = ok_color
        #清除testresul列中的测试结果,设置为nt
        self.write_data(suiteid, row, self.argbegin+self.argcount+1, ' ', ok_color)
        self.write_data(suiteid, row, self.resultcol, 'nt', nt_color)
    except:
      self.close()
      print('清除数据失败')
      exit()
#执行调用
def httpinvoke(ipport, url):
  conn = httplib.httpconnection(ipport)
  conn.request("get", url)
  rsps = conn.getresponse()
  data = rsps.read()
  conn.close()
  return data
#获取用例基本信息[interface,argcount,[argnamelist]]
def get_caseinfo(data, suiteid):
  caseinfolist=[]
  sinterface=data.read_data(suiteid, 1, 2)
  argcount=int(data.read_data(suiteid, 2, 2))
  #获取参数名存入argnamelist
  argnamelist=[]
  for i in range(0, argcount):
    argnamelist.append(data.read_data(suiteid, data.titleindex, data.argbegin+i))
  caseinfolist.append(sinterface)
  caseinfolist.append(argcount)
  caseinfolist.append(argnamelist)
  return caseinfolist
#获取输入
def get_input(data, suiteid, caseid, caseinfolist):
  sarge=''
  #参数组合
  for j in range(0, caseinfolist[1]):
    if data.read_data(suiteid, data.casebegin+caseid, data.argbegin+j) != "none":
      sarge=sarge+caseinfolist[2][j]+'='+data.read_data(suiteid, data.casebegin+caseid, data.argbegin+j)+'&'
  #去掉结尾的&字符
  if sarge[-1:]=='&':
    sarge = sarge[0:-1]
  sinput=caseinfolist[0]+sarge  #组合全部参数
  return sinput
#结果判断
def assert_result(sreal, sexpect):
  sreal=str(sreal)
  sexpect=str(sexpect)
  if sreal==sexpect:
    return 'ok'
  else:
    return 'ng'
#将测试结果写入文件
def write_result(data, suiteid, caseid, resultcol, *result):
  if len(result)>1:
    ret='ok'
    for i in range(0, len(result)):
      if result[i]=='ng':
        ret='ng'
        break
    if ret=='ng':
      data.write_data(suiteid, data.casebegin+caseid, resultcol,ret, ng_color)
    else:
      data.write_data(suiteid, data.casebegin+caseid, resultcol,ret, ok_color)
    data.allresult.append(ret)
  else:
    if result[0]=='ng':
      data.write_data(suiteid, data.casebegin+caseid, resultcol,result[0], ng_color)
    elif result[0]=='ok':
      data.write_data(suiteid, data.casebegin+caseid, resultcol,result[0], ok_color)
    else: #nt
      data.write_data(suiteid, data.casebegin+caseid, resultcol,result[0], nt_color)
    data.allresult.append(result[0])
  #将当前结果立即打印
  print 'case'+str(caseid+1)+':', data.allresult[-1]
#打印测试结果
def statisticresult(excelobj):
  allresultlist=excelobj.allresult
  count=[0, 0, 0]
  for i in range(0, len(allresultlist)):
    #print 'case'+str(i+1)+':', allresultlist[i]
    count=countflag(allresultlist[i],count[0], count[1], count[2])
  print 'statistic result as follow:'
  print 'ok:', count[0]
  print 'ng:', count[1]
  print 'nt:', count[2]
#解析xmlstring返回dict
def get_xmlstring_dict(xml_string):
  xml = xml2dict()
  return xml.fromstring(xml_string)
#解析xmlfile返回dict
def get_xmlfile_dict(xml_file):
  xml = xml2dict()
  return xml.parse(xml_file)
#去除历史数据expect[real]
def delcomment(excelobj, suiteid, irow, icol, str):
  startpos = str.find('[')
  if startpos>0:
    str = str[0:startpos].strip()
    excelobj.write_data(suiteid, irow, icol, str, ok_color)
  return str
#检查每个item (非结构体)
def check_item(excelobj, suiteid, caseid,real_dict, checklist, begincol):
  ret='ok'
  for checkid in range(0, len(checklist)):
    real=real_dict[checklist[checkid]]['value']
    expect=excelobj.read_data(suiteid, excelobj.casebegin+caseid, begincol+checkid)
    #如果检查不一致测将实际结果写入expect字段,格式:expect[real]
    #将return ng
    result=assert_result(real, expect)
    if result=='ng':
      writestr=expect+'['+real+']'
      excelobj.write_data(suiteid, excelobj.casebegin+caseid, begincol+checkid, writestr, ng_color)
      ret='ng'
  return ret
#检查结构体类型
def check_struct_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin, structcount):
  ret='ok'
  if structcount>1: #传入的是list
    for structid in range(0, structcount):
      structdict=real_struct_dict[structid]
      temp=check_item(excelobj, suiteid, caseid,structdict, structlist, structbegin+structid*len(structlist))
      if temp=='ng':
        ret='ng'
  else: #传入的是dict
    temp=check_item(excelobj, suiteid, caseid,real_struct_dict, structlist, structbegin)
    if temp=='ng':
      ret='ng'
  return ret
#获取异常函数及行号
def print_error_info():
  """return the frame object for the caller's stack frame."""
  try:
    raise exception
  except:
    f = sys.exc_info()[2].tb_frame.f_back
  print (f.f_code.co_name, f.f_lineno)
#测试结果计数器,类似switch语句实现
def countflag(flag,ok, ng, nt):
  calculation = {'ok':lambda:[ok+1, ng, nt],
             'ng':lambda:[ok, ng+1, nt],
             'nt':lambda:[ok, ng, nt+1]}
  return calculation[flag]()

2、项目测试代码

# -*- coding: utf-8 -*-
#****************************************************************
# xxx_server_case.py
# author   : vince
# version  : 1.0
# date    : 2011-3-10
# description: 内容服务系统测试代码
#****************************************************************
from testframe import *
from common_lib import *
httpstring='http://xxx.com/xxx_product/test/'
expectxmldir=os.getcwd()+'/testdir/expect/'
realxmldir=os.getcwd()+'/testdir/real/'
def run(interface_name, suiteid):
  print '【'+interface_name+'】' + ' test begin,please waiting...'
  global expectxmldir, realxmldir
  #根据接口名分别创建预期结果目录和实际结果目录
  expectdir=expectxmldir+interface_name
  realdir=realxmldir+interface_name
  if os.path.exists(expectdir) == 0:
    os.makedirs(expectdir)
  if os.path.exists(realdir) == 0:
    os.makedirs(realdir)
  excelobj.del_testrecord(suiteid) #清除历史测试数据
  casecount=excelobj.get_ncase(suiteid) #获取case个数
  caseinfolist=get_caseinfo(excelobj, suiteid) #获取case基本信息
  #遍历执行case
  for caseid in range(0, casecount):
    #检查是否执行该case
    if excelobj.read_data(suiteid,excelobj.casebegin+caseid, 2)=='n':
      write_result(excelobj, suiteid, caseid, excelobj.resultcol, 'nt')
      continue #当前case结束,继续执行下一个case
    #获取测试数据
    sinput=httpstring+get_input(excelobj, suiteid, caseid, caseinfolist)
    xmlstring=httpinvoke(com_ipport, sinput)   #执行调用
    #获取返回码并比较
    result_code=et.fromstring(xmlstring).find("result_code").text
    ret1=check_result(excelobj, suiteid, caseid,result_code, excelobj.retcol)
    #保存预期结果文件
    expectpath=expectdir+'/'+str(caseid+1)+'.xml'
    #savexmlfile(expectpath, xmlstring)
    #保存实际结果文件
    realpath=realdir+'/'+str(caseid+1)+'.xml'
    savexmlfile(realpath, xmlstring)
    #比较预期结果和实际结果
    ret2= check_xmlfile(excelobj, suiteid, caseid,expectpath, realpath)
    #写测试结果
    write_result(excelobj, suiteid, caseid, excelobj.resultcol, ret1, ret2)
  print '【'+interface_name+'】' + ' test end!'

3、测试入口

# -*- coding: utf-8 -*-
#****************************************************************
# main.py
# author   : vince
# version  : 1.0
# date    : 2011-3-16
# description: 测试组装,用例执行入口
#****************************************************************
from testframe import *
from xxx_server_case import *
import xxx_server_case
#产品系统接口测试
#设置测试环境
xxx_server_case.excelobj=create_excel(os.getcwd()+'/testdir/xxx_testcase.xls')
xxx_server_case.com_ipport=xxx.com'
#add testsuite begin
run("xxx_book_list", 4)
#add other suite from here
#add testsuite end
statisticresult(xxx_server_case.excelobj)
xxx_server_case.excelobj.close()

更多关于python相关内容可查看本站专题:《python socket编程技巧总结》、《python数据结构与算法教程》、《python函数使用技巧总结》、《python字符串操作技巧汇总》、《python入门与进阶经典教程》及《python文件与目录操作技巧汇总

希望本文所述对大家python程序设计有所帮助。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网