前文:
本文主要进行接口自动化测试脚本设计时,当面临微服务众多且没有统一的域名映射时,如何在一个脚本中动态对请求地址的更改(避免在unittest的测试项中写死请
求地址)。
问题背景:
接口自动化的回归测试通常用于线上环境或者灰度环境的全量接口测试,我司接口自动化测试是利用 unittest 库做测试case的管理,再辅以requests库做请求和响应管理,
HTMLTestReportCN做 报告展示。
在线上做回归测试时,域名都是统一的,所以一般只要在 setupclass 函数中做个定义好域名即可,但是因为系统重构,需要在测试环境也进行全量回归测试。我们测试环
境又是微服务,一是服务多,二是没有做统一的域名映射。所以这就给脚本设计带来了一定困难。
解决设想:
遇到这种问题时,当时想出了两种思路
1.在具体的测试项中写死请求地址。
好处:可以解决实际问题
坏处:工作量大切繁琐
但是假设我有100个微服务(假设每个微服务就一个接口),那仅请求地址就得写100遍,这样带来的工作量太大了,而且写脚本本身就是
期望以自动化的形式去减少手工操作,这样一搞就显得得不偿失了。
2.实现自动更改请求地址,一切交由程序去判断,去执行。
好处:减少工作量且程序自主性高(避免了人为操作干扰)
坏处:得在unittest库本身的限制内实现一个可以动态请求的过程
解决:
因为unittest的每一个测试项都是一个单独的函数,那么就相当于是在原本函数功能不变的情况下再增加些其他功能,这就有点装饰器的意思了。感觉思路可行。
设想:
1.调用测试函数时,请求装饰器,将整个函数传给装饰器函数。
2.装饰器函数要做的就是根据函数名(我是依据的函数名,为每个微服务赋予一个特定的名字)或其他具备唯一性的条件进行判断,不同的判断项走不同的逻辑。
注意点:
因为装饰器本身是在unittest库规则之下,并且要动态更改setupClass函数内定义的地址,所以需要考虑把整个实现unittest.TestCase的测试类的内部属性当参数传递给装饰
器函数,具体过程参考下面代码实现。
# -*- coding: UTF-8 -*-
import os,sys
import os ,sys
import time
import csv
from client import *
from datetime import datetime
from config import utils
pack_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pack_dir)
data_dir = os.path.join(pack_dir, "")
#测试类
class interface_all(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.baseurl = "requestUrl"
print("初始化数据完成。")
@classmethod
def tearDownClass(cls):
print()
print("All cases finished.")
def setUp(self):
self.__data = {}
self.start = datetime.now()
print(self.start)
print('##############test start###############')
def tearDown(self):
self.end = datetime.now()
print((self.end - self.start).seconds)
print('##############test end###############')
def changeUrl(func): # func接收body
def ware(self, *args, **kwargs): # self,接收body里的self,也就是类实例
print('This is a decrator!')
print(func.__name__)
print('police' in func.__name__ )
print(self.baseurl)
if 'XXX' in func.__name__:
self.baseurl = 'http://····:port'
elif 'YYY' in func.__name__:
self.baseurl = 'http://····:port'
elif 'ZZZ' in func.__name__:
self.baseurl = 'http://····:port'
return func(self, *args, **kwargs)
return ware
@changeUrl
def test_01_XXX(self):
''' '''
self.url = self.baseurl + 'url1'
self.client = Client(url=self.url, method=Method.POST, type=Type.FORM_FILE)
data = self.__data
data = self.__data
client = self.client
client.set_data(data)
client.send()
client.write_to_csv(self.__path)
client.check_status_code()
client.check_dict_equal()
@changeUrl
def test_02_YYY(self):
''' '''
self.url = self.baseurl + 'url2'
self.client = Client(url=self.url, method=Method.POST, type=Type.FORM_FILE)
data = self.__data
client = self.client
client.set_data(data)
client.send()
client.write_to_csv(self.__path)
client.check_status_code()
client.check_dict_equal()
@changeUrl
def test_03_ZZZ(self):
''' '''
self.url = self.baseurl + 'url3'
self.client = Client(url=self.url, method=Method.POST, type=Type.FORM_FILE)
data = self.__data
client = self.client
client.set_data(data)
client.send()
client.write_to_csv(self.__path)
client.check_status_code()
client.check_dict_equal()