您的位置:首页 > 其它

接口测试框架(三)-框架优化

2018-03-08 17:33 267 查看
参考博客:https://www.bstester.com/2015/08/interface-test-automation-scheme-details
看到一篇接口自动化测试的文章,觉得这个文章里的方案更加的容易编写测试用例。优点是测试用例的参数配置很方便,直接用excel表格中写入自己希望执行的用例就行了,有点像JMter。



用这种方法的话,测试用例统一使用excel文档保存,结合之前的接口测试框架能够更加清晰,简单的写出测试用例。因为看上去太好用了(不用为每一个接口测试用例单独写一个方法,简直太省事了),我就将这个方法加入到测试框架中了。

* 一、加入读取、写入Excel文件功能

第一步,在文件读取类中加入读取与写入excel文件的类。from xlrd import open_workbook
from xlutils.copy import copy
from xlwt import Style

class ExcelReader():
def __init__(self, excel_file, sheet, title_line=True):
if os.path.exists(excel_file):
self.excel_file = excel_file
else:
raise FileNotFoundError('File not found!%s')
self.sheet = sheet
self.title_line = title_line
self.table = None
self._data = list()

def set_value(self,col, row, value):
# 将传入值写进xlsw文件相应的行号,列号中
rb = open_workbook(self.excel_file, formatting_info=True)
wb = copy(rb)
ws = wb.get_sheet(0)
ws.write(col, row, value, Style.default_style)
wb.save(self.excel_file)

@property
def data(self):
# 读取xlsx文件
if not self._data:
work_book = open_workbook(self.excel_file)
if type(self.sheet) not in [int, str]:
print '[Excel sheet error]Input <int> <str> please'
elif type(self.sheet) is str:
self.table = work_book.sheet_by_name(self.sheet)
else:
self.table = work_book.sheet_by_index(self.sheet)
# 判断是否有标题,标题有无影响数据的格式(可运行最下方main函数进行比较)
# 有标题:[{标题1:参数1,标题2:参数2,标题3:参数3}]
# 无标题:[[参数1(行1),参数2(行1),参数3(行1)],[参数1(行2),参数2(行2),参数3(行2)]]
if self.title_line:
title = self.table.row_values(0)
for row in range(1, self.table.nrows):
self._data.append(dict(zip(title, self.table.row_values(row))))
else:
for col in range(self.table.nrows):
self._data.append(self.table.row_values(col))
return self._data这里参照了灰蓝的写法,自己再加入了写入excel文件的方法。

* 二、创建测试类用于读取excel中的测试用例

这一步主要是讲落叶归根博客中的方法引入到我们的测试框架中。大致的思路是,将excel中的数据存入我们的用例类中,生成一个个的测试用例。好像就这一块算是我自己独立完成的,哎,要走的路好长呀。
这里有几个很重要的点,分别是:参数、关联、检查点、是否运行
参数:注意一定要是字典类型否则会出错。参数还要支持参数化,例如$token则会去配置文件中读取token的值,并赋值给该参数。
关联:这里还是拿token举例。比如说我先执行登录接口,登录成功后会返回给我们一个token,接下来的测试都需要用到token。那么我们在这里将登录接口中的token设为关联,运行登录测试用例后,就会将刚获取的token的值存入配置文件中。
检查点:这个比较简单,看响应内容中是否有包含该字符串。
是否运行:这里的值设为yes就会执行,没有的话就不会执行。



#!/usr/bin/env python
#coding=utf-8

from utils.file_reader import YamlReader
from utils.config import BASE_PATH
from utils.client import HTTPsClient
from utils.log import logger
import yaml
import json
import os

class InterfaceCase(object):
# 接口测试对象,属性对应接口测试xlsx文件。方法有建立用例数据,运行用例数据
def __init__(self, data):
self.data = data
self.no = int('%d' % data['No.'])
self.apiName = data['API']
self.testCase = data['TestCase']
self.host = data['HOST']
self.url = data['URL']
self.requestMethod = data['RequestMethod']
self.params = data['Params']
self.relation = data['Relation']
self.checkPoint = data['CheckPoint']
self.active = data['Active']
self.result = 'Na'
self.response = None
self.y = YamlReader(os.path.join(BASE_PATH, 'config', 'test.yaml'))
self.get_config()

def __str__(self):
# 漂亮的输出测试用例的重要属性
return 'No.' + str(self.no) + ' API:' + self.apiName + ' TestCase:' + self.testCase + \
' result:' + self.result

def get_config(self):
# 将参数中带有$的参数与配置文件中的参数匹配,并赋值
# 例如:参数中有$token,则将配置文件中token的值付给token这个参数
try:
params = json.loads(self.params)
except ValueError:
logger.warn('No.%s Params input error!' % self.no)
return
data = self.y.data
for i in params:
if '$' in params[i]:
try:
params[i] = data[0][i]
except KeyError:
raise KeyError('No.%s Params "%s" not found!' % (self.no, i))
self.params = params

def run(self):
# 运行用例,暂时只支持POST以及GET方法。client.py中可支持更多参数配置
h = HTTPsClient(url=self.host+self.url, method=self.requestMethod)
if self.requestMethod == 'POST':
self.response = h.json_transform_dict(h.send(data=self.params))
elif self.requestMethod == 'GET':
self.response = h.json_transform_dict(h.send(params=self.params))
else:
raise KeyError('method "%s" not support!' % self.requestMethod)
if self.checkPoint:
try:
params = self.checkPoint.split('=')
except TypeError:
logger.error('checkPoint input error!')
raise TypeError('checkPoint input error : %s' % self.checkPoint)
value = str(self.response[params[0]])
if value != params[1]:
self.result = 'Fail'
logger.info('No.%s check point "%s" not found ' % (self.no, self.checkPoint))
return self.response
elif value == params[1]:
self.result = 'Pass'
else:
self.result = 'Pass'
# 判断是否存在关联,如果有且格式正确则将执行后的参数写入配置文件
# 例如:$token=token,则将response中的token值存入到配置文件中
if self.relation:
try:
l = self.relation.split(',')
except TypeError:
logger.error('relation input error!')
raise TypeError('relation input error : %s' % self.relation)
for i in l:
try:
params = i[1:].split('=')
except TypeError:
logger.error('relation input error!')
raise TypeError('relation input error : %s' % i)
data = self.y.data[0]
# response['data']根据项目不同可能略有差异
# 此处防止response中想要获取的值为空,产生异常
if self.response['data'][params[0]] == None:return self.response
try:
data[params[1]] = self.response['data'][params[0]].encode('utf-8')
except AttributeError:
data[params[1]] = self.response['data'][params[0]]
# 将变量写入yaml文件
self.y.data = yaml.dump(data, default_flow_style=False)
return self.response

* 三、编写测试用例

都写好啦,终于可以编写接口测试用例了!11,和10列我用来存储执行用例的情况,一个是检查点是否成功,另一个是响应内容。#!/usr/bin/env python
#coding=utf-8

import unittest
import os
from utils.file_reader import ExcelReader
from utils.log import logger
from utils.config import Config, DATA_PATH
from utils.interface_case import InterfaceCase

class InterfaceTest001(unittest.TestCase):
excel_path = os.path.join(DATA_PATH, Config().get('data')['interface_case_list'])
e = ExcelReader(excel_path, 0, True)
case_list = e.data

def test_func(self):
for i in self.case_list:
# 运行用例前,将xlsx文件中执行结果以及用例执行情况还原
self.e.set_value(int('%d' % i['No.']), 11, 'Na')
self.e.set_value(int('%d' % i['No.']), 10, '')
t = InterfaceCase(i)
# 是否执行该条用例
if t.active == 'yes':
response = t.run()
logger.info(t)
# 将用例执行结果以及用例执行情况写入xlsx
self.e.set_value(t.no, 10, response['msg'])
self.e.set_value(t.no, 11, t.result)

if __name__ == '__main__':
# 运行测试用例
unittest.main()
事后一些小小的想法
虽然刚开始的时候觉得落叶归根这种exc
aa22
el存储测试用例的方法实在是太赞了,但是写完之后发现了很多的局限性。比如这样写,我就很难用灰蓝博客中介绍的生成html报告的方法,只能看自己输出的日志文件。
项目开始的时候,我想用这个框架做接口测试,但是发现这个测试框架根本就不够灵活。比如我要做一个登录次数上限的用例,我就不能用这个测试框架,必须要自己重新写测试类。
还有一个特别困扰的问题,师父希望接口测试的脚本更加的灵活。灵活到,我给别人发一个脚本,他F5就可以直接运行。而不是这个框架这样,需要其他的测试员去读懂这个框架。读懂之后还要配置这个框架需要的环境。
总的来说,动手编写这个框架还是很开心的,提升了自己编写python脚本的能力。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: