接口自动化测试框架实例详解教程python+requests.docx

上传人:b****7 文档编号:26015986 上传时间:2023-06-17 格式:DOCX 页数:23 大小:96.30KB
下载 相关 举报
接口自动化测试框架实例详解教程python+requests.docx_第1页
第1页 / 共23页
接口自动化测试框架实例详解教程python+requests.docx_第2页
第2页 / 共23页
接口自动化测试框架实例详解教程python+requests.docx_第3页
第3页 / 共23页
接口自动化测试框架实例详解教程python+requests.docx_第4页
第4页 / 共23页
接口自动化测试框架实例详解教程python+requests.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

接口自动化测试框架实例详解教程python+requests.docx

《接口自动化测试框架实例详解教程python+requests.docx》由会员分享,可在线阅读,更多相关《接口自动化测试框架实例详解教程python+requests.docx(23页珍藏版)》请在冰豆网上搜索。

接口自动化测试框架实例详解教程python+requests.docx

接口自动化测试框架实例详解教程python+requests

接口自动化测试框架实例详解教程python+requests

  前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自动化框架,使用的是java语言,但对于一个学java,却在学python的我来说,觉得python比起java更简单些,所以,我决定自己写python的接口自动化测试框架,由于本人也是刚学习python,这套自动化框架目前已经基本完成了,于是进行一些总结,便于以后回顾温习,有许多不完善的地方,也遇到了许多的问题,希望大神们多多指教。

下面我就进行今天的主要内容吧。

  1、首先,我们先来理一下思路。

  正常的接口测试流程是什么?

  脑海里的反应是不是这样的:

  确定测试接口的工具—>配置需要的接口参数—>进行测试—>检查测试结果(有的需要数据库辅助)—>生成测试报告(html报告)

  那么,我们就根据这样的过程来一步步搭建我们的框架。

在这个过程中,我们需要做到业务和数据的分离,这样才能灵活,达到我们写框架的目的。

只要好好做,一定可以成功。

这也是我当初对自己说的。

  接下来,我们来进行结构的划分。

  我的结构是这样的,大家可以参考下:

  common:

存放一些共通的方法

  result:

执行过程中生成的文件夹,里面存放每次测试的结果

  testCase:

用于存放具体的测试case

  testFile:

存放测试过程中用到的文件,包括上传的文件,测试用例以及数据库的sql语句

  caselist:

txt文件,配置每次执行的case名称

  config:

配置一些常量,例如数据库的相关信息,接口的相关信息等

  readConfig:

用于读取config配置文件中的内容

  runAll:

用于执行case

  既然整体结构有了划分,接下来就该一步步的填充整个框架了,首先,我们先来看看config.ini和readConfig.py两个文件,从他们入手,个人觉得比较容易走下去哒。

  我们来看下文件的内容是什么样子的:

 [DATABASE]

  host=50.23.190.57

  username=xxxxxx

  password=******

  port=3306

  database=databasename

  [HTTP]

  #接口的url

  baseurl=http:

//xx.xxxx.xx

  port=8080

  timeout=1.0

  [EMAIL]

  mail_host=

  mail_user=xxx@

  mail_pass=*********

  mail_port=25

  sender=xxx@

  receiver=xxxx@

  subject=python

  content="Allinterfacetesthasbeencomplited\npleasereadthereportfileaboutthedetileofresultintheattachment."

  testuser=Someone

  on_off=1

  相信大家都知道这样的配置文件,没错,所有一成不变的东西,我们都可以放到这里来。

哈哈,怎么样,不错吧。

  现在,我们已经做好了固定的“仓库”。

来保存我们平时不动的东西,那么,我们要怎么把它拿出来为我所用呢?

这时候,readConfig.py文件出世了,它成功的帮我们解决了这个问题,下面就让我们来一睹它的庐山真面目吧。

  importos

  importcodecs

  importconfigparser

  proDir=os.path.split(os.path.realpath(__file__))[0]

  configPath=os.path.join(proDir,"config.ini")

  classReadConfig:

  def__init__(self):

  fd=open(configPath)

  data=fd.read()

  # removeBOM

  ifdata[:

3]==codecs.BOM_UTF8:

  data=data[3:

]

  file=codecs.open(configPath,"w")

  file.write(data)

  file.close()

  fd.close()

  self.cf=configparser.ConfigParser()

  self.cf.read(configPath)

  defget_email(self,name):

  value=self.cf.get("EMAIL",name)

  returnvalue

  defget_http(self,name):

  value=self.cf.get("HTTP",name)

  returnvalue

  defget_db(self,name):

  value=self.cf.get("DATABASE",name)

  returnvalue

  怎么样,是不是看着很简单啊,我们定义的方法,根据名称取对应的值,是不是soeasy?

当然了,这里我们只用到了get方法,还有其他的例如set方法,有兴趣的同学可以自己去探索下,这里我们就不在累述了。

  话不多说,我们先来看下common到底有哪些东西。

  既然配置文件和读取配置文件我们都已经完成了,也看到了common里的内容,接下来就可以写common里的共通方法了,从哪个下手呢?

今天,我们就来翻“Log.py”的牌吧,因为它是比较独立的,我们单独跟他打交道,也为了以后它能为我们服务打下良好基础。

  这里呢,我想跟大家多说两句,对于这个log文件呢,我给它单独启用了一个线程,这样在整个运行过程中,我们在写log的时候也会比较方便,看名字大家也知道了,这里就是我们对输出的日志的所有操作了,主要是对输出格式的规定,输出等级的定义以及其他一些输出的定义等等。

总之,你想对log做的任何事情,都可以放到这里来。

我们来看下代码,没有比这个更直接有效的了。

  importlogging

  fromdatetimeimportdatetime

  importthreading

  首先,我们要像上面那样,引入需要的模块,才能进行接下来的操作。

  classLog:

  def__init__(self):

  globallogPath,resultPath,proDir

  proDir=readConfig.proDir

  resultPath=os.path.join(proDir,"result")

  #createresultfileifitdoesn'texist

  ifnotos.path.exists(resultPath):

  os.mkdir(resultPath)

  #definedtestresultfilenamebylocaltime

  logPath=os.path.join(resultPath,str(datetime.now().strftime("%Y%m%d%H%M%S")))

  #createtestresultfileifitdoesn'texist

  ifnotos.path.exists(logPath):

  os.mkdir(logPath)

  #definedlogger

  self.logger=logging.getLogger()

  #definedloglevel

  self.logger.setLevel(logging.INFO)

  #definedhandler

  handler=logging.FileHandler(os.path.join(logPath,"output.log"))

  #definedformatter

  formatter=logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')

  #definedformatter

  handler.setFormatter(formatter)

  #addhandler

  self.logger.addHandler(handler)

  ,现在,我们创建了上面的Log类,在__init__初始化方法中,我们进行了log的相关初始化操作。

具体的操作内容,注释已经写得很清楚了(英文有点儿差,大家看得懂就行,嘿嘿……),这样,log的基本格式已经定义完成了,至于其他的方法,就靠大家自己发挥了,毕竟每个人的需求也不同,我们就只写普遍的共用方法啦。

接下来,就是把它放进一个线程内了,请看下面的代码:

  classMyLog:

  log=None

  mutex=threading.Lock()

  def__init__(self):

  pass

  @staticmethod

  defget_log():

  ifMyLog.logisNone:

  MyLog.mutex.acquire()

  MyLog.log=Log()

  MyLog.mutex.release()

  returnMyLog.log

  看起来是不是没有想象中的那样复杂啊,就是这样简单,python比java简单了许多,这也是我为什么选择它的原因,虽然小编我也是刚刚学习,还有很多不懂的地方。

好了,至此log的内容也结束了,是不是感觉自己棒棒哒~其实,无论什么时候,都不要感到害怕,要相信“世上无难事只怕有心人”。

  下面,我们继续搭建,这次要做的,是configHttp.py的内容。

没错,我们开始配置接口文件啦!

(终于写到接口了,是不是很开心啊~)

  下面是接口文件中主要部分的内容,让我们一起来看看吧。

  importrequests

  importreadConfigasreadConfig

  fromcommon.LogimportMyLogasLog

  localReadConfig=readConfig.ReadConfig()

  classConfigHttp:

  def__init__(self):

  globalhost,port,timeout

  host=localReadConfig.get_http("baseurl")

  port=localReadConfig.get_http("port")

  timeout=localReadConfig.get_http("timeout")

  self.log=Log.get_log()

  self.logger=self.log.get_logger()

  self.headers={}

  self.params={}

  self.data={}

  self.url=None

  self.files={}

  defset_url(self,url):

  self.url=host+url

  defset_headers(self,header):

  self.headers=header

  defset_params(self,param):

  self.params=param

  defset_data(self,data):

  self.data=data

  defset_files(self,file):

  self.files=file

  #definedhttpgetmethod

  defget(self):

  try:

  response=requests.get(self.url,params=self.params,headers=self.headers,timeout=float(timeout))

  #response.raise_for_status()

  returnresponse

  exceptTimeoutError:

  self.logger.error("Timeout!

")

  returnNone

  #definedhttppostmethod

  defpost(self):

  try:

  response=requests.post(self.url,headers=self.headers,data=self.data,files=self.files,timeout=float(timeout))

  #response.raise_for_status()

  returnresponse

  exceptTimeoutError:

  self.logger.error("Timeout!

")

  returnNone

  这里我们就挑重点来说吧。

首先,可以看到,这次是用python自带的requests来进行接口测试的,相信有心的朋友已经看出来了,python+requests这个模式是很好用的,它已经帮我们封装好了测试接口的方法,用起来很方便。

这里呢,我就拿get和post两个方法来说吧。

(平时用的最多的就是这两个方法了,其他方法,大家可以仿照着自行扩展)

  get方法

  接口测试中见到最多的就是get方法和post方法,其中,get方法用于获取接口的测试,说白了,就是说,使用get的接口,都不会对后台数据进行更改,而且get方法在传递参数后,url的格式是这样的:

http:

//接口地址?

key1=value1&key2=value2,是不是看起来很眼熟啊~(反正我看着它很眼熟~\(≧▽≦)/~啦啦啦),那我们要怎么使用它呢,请继续往下看。

  对于requests提供的get方法,有几个常用的参数:

  url:

显而易见,就是接口的地址url啦

  headers:

定制请求头(headers),例如:

content-type=application/x-www-form-urlencoded

  params:

用于传递测试接口所要用的参数,这里我们用python中的字典形式(key:

value)进行参数的传递。

  timeout:

设置接口连接的最大时间(超过该时间会抛出超时错误)

  现在,各个参数我们已经知道是什么意思了,剩下的就是往里面填值啦,是不是机械式的应用啊,哈哈,小编我就是这样机械般的学习的啦~

  举个栗子:

 url=‘

  header={‘content-type’:

application/x-www-form-urlencoded}

  param={‘user_id’:

123456,‘email’:

123456@}

  timeout=0.5

  requests.get(url,headers=header,params=param,timeout=timeout)

  post方法

  与get方法类似,只要设置好对应的参数,就可以了。

下面就直接举个栗子,直接上代码吧:

  url=‘

  header={‘content-type’:

application/x-www-form-urlencoded}

  data={‘email’:

123456@,‘password’:

123456}

  timeout=0.5

  requests.post(url,headers=header,data=data,timeout=timeout)

  怎么样,是不是也很简单啊。

这里我们需要说明一下,post方法中的参数,我们不在使用params进行传递,而是改用data进行传递了。

哈哈哈,终于说完啦,下面我们来探(了)讨(解)下接口的返回值。

  依然只说常用的返回值的操作。

  text:

获取接口返回值的文本格式

  json():

获取接口返回值的json()格式

  status_code:

返回状态码(成功为:

200)

  headers:

返回完整的请求头信息(headers['name']:

返回指定的headers内容)

  encoding:

返回字符编码格式

  url:

返回接口的完整url地址

  以上这些,就是常用的方法啦,大家可自行取之。

  关于失败请求抛出异常,我们可以使用“raise_for_status()”来完成,那么,当我们的请求发生错误时,就会抛出异常。

在这里提醒下各位朋友,如果你的接口,在地址不正确的时候,会有相应的错误提示(有时也需要进行测试),这时,千万不能使用这个方法来抛出错误,因为python自己在链接接口时就已经把错误抛出,那么,后面你将无法测试期望的内容。

而且程序会直接在这里当掉,以错误来计。

(别问我怎么知道的,因为我就是测试的时候发现的)

  好了。

接口文件也讲完了,是不是感觉离成功不远了呢?

嗯,如果各位已经看到了这里,那么恭喜大家,下面还有很长的路要走~哈哈哈,就是这么任性。

(毕竟小编我为了让各位和我差不多的小白能够更容易理解,也是使出了体内的洪荒之力啦)

  慢慢地长叹一口气,继续下面的内容。

  快,我想学(看)习(看)common.py里的内容。

  importos

  fromxlrdimportopen_workbook

  fromxml.etreeimportElementTreeasElementTree

  fromcommon.LogimportMyLogasLog

  localConfigHttp=configHttp.ConfigHttp()

  log=Log.get_log()

  logger=log.get_logger()

  #从excel文件中读取测试用例

  defget_xls(xls_name,sheet_name):

  cls=[]

  #getxlsfile'spath

  xlsPath=os.path.join(proDir,"testFile",xls_name)

  #openxlsfile

  file=open_workbook(xlsPath)

  #getsheetbyname

  sheet=file.sheet_by_name(sheet_name)

  #getonesheet'srows

  nrows=sheet.nrows

  foriinrange(nrows):

  ifsheet.row_values(i)[0]!

=u'case_name':

  cls.append(sheet.row_values(i))

  returncls

  #从xml文件中读取sql语句

  database={}

  defset_xml():

  iflen(database)==0:

  sql_path=os.path.join(proDir,"testFile","SQL.xml")

  tree=ElementTree.parse(sql_path)

  fordbintree.findall("database"):

  db_name=db.get("name")

  #print(db_name)

  table={}

  fortbindb.getchildren():

  table_name=tb.get("name")

  #print(table_name)

  sql={}

  fordataintb.getchildren():

  sql_id=data.get("id")

  #print(sql_id)

  sql[sql_id]=data.text

  table[table_name]=sql

  database[db_name]=table

  defget_xml_dict(database_name,table_name):

  set_xml()

  database_dict=database.get(database_name).get(table_name)

  returndatabase_dict

  defget_sql(database_name,table_name,sql_id):

  db=get_xml_dict(database_name,table_name)

  sql=db.get(sql_id)

  returnsql

  上面就是我们common的两大主要内容了,什么?

还不知道是什么吗?

让我告诉你吧。

  我们利用xml.etree.Element来对xml文件进行操作,然后通过我们自定义的方法,根据传递不同的参数取得不(想)同(要)的值。

  利用xlrd来操作excel文件,注意啦,我们是用excel文件来管理测试用例的。

  听起来会不会有点儿懵,小编刚学时也很懵,看文件就好理解了。

  excel文件:

  xml文件:

  至于具体的方法,我就不再一点点讲解了,总觉得大家都懂(小编刚学,望谅解),只是我个人需要详细记录,以后容易温习。

接下来,我们看看数据库和发送邮件吧(也可根据需要,不写该部分内容)

 这次使用的是MySQL数据库,所以我们就以它为例吧。

  importpymysql

  importreadConfigasreadConfig

  fromcommon.LogimportMyLogasLog

  localReadConfig=readConfig.ReadConfig()

  classMyDB:

  globalhost,username,password,port,database,config

  host=localReadConfig.get_db("host")

  username=localReadConfi

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1