本文章主要讲解Python接口自动化测试的框架搭建修改,自动化测试用例设计、接口测试中用例设计的动态参数化形式等内容,本文章会跳过部分框架搭建内容,废话不多说,让我们一起来看看叭。
我们先用一个接口为出发点,该接口为登录接口,请求方式为POST,登录后才可以进行各式各样的操作,基本信息如下所示:
按照登录接口文档,进行测试用例的设计:
测试用例属于数据,那么我们必定要读取excel,我们也有配置文件,还有日志系统,这些都属于通用内容,我们可以先将对应的代码模块添加到common中:
- """读取excel,有更简便的方法,该方法适合新手进行学习了解"""
- import openpyxl
-
- def read_excel(file_path, sheet_name):
- """读取excel中的数据"""
- workbook = openpyxl.load_workbook(file_path)
- sheet = workbook[sheet_name]
- values = list(sheet.values)
- workbook.close()
- title = values[0]
- rows = values[1:]
- new_rows = [dict(zip(title, rows)) for rows in rows]
- return new_rows
- """日志系统"""
- import logging
-
-
- def get_logger(logging_name="收集器",
- logger_level="DEBUG",
- stream_level="DEBUG",
- file=None,
- file_level="INFO",
- fmt="%(asctime)s--%(levelname)s--%(filename)s--%(lineno)d--%(message)s"):
- """获取logger收集器"""
- logger = logging.getLogger(logging_name)
- logger.setLevel(logger_level)
- stream_handler = logging.StreamHandler()
- stream_handler.setLevel(stream_level)
- logger.addHandler(stream_handler)
-
- fmt_obj = logging.Formatter(fmt)
- stream_handler.setFormatter(fmt_obj)
-
- # 判断是否有文件,如果有,初始化file_handler,如果没有文件则不执行
- if file:
- file_handler = logging.FileHandler(file, encoding="utf-8")
- file_handler.setLevel("INFO")
- logger.addHandler(file_handler)
- file_handler.setFormatter(fmt_obj)
-
- return logger
-
-
- log = get_logger()
- """yaml读取结果"""
- import yaml
-
-
- def read_yaml(file, encoding="utf-8"):
- with open(file, encoding="utf-8") as f:
- data = yaml.safe_load(f)
- return data
在testcase目录下新建test_login用于测试登录并实现好excel的读取以及数据驱动,获取用例数据后我们先打印看下数据:
- import unittest
- import requests
- from common.excel import read_excel
- from config import path_config
- from unittestreport import ddt, list_data
-
-
- # 获取数据
- data = read_excel(path_config.case_path, "login")
-
- @ddt
- class TestLogin(unittest.TestCase):
- @list_data(data)
- def test_login_success(self, case_data):
- print(case_data)
补充的完整代码如下所示:
- import unittest
- import requests
- import json
- from common.excel import read_excel
- from config import path_config
- from unittestreport import ddt, list_data
-
-
- # 获取数据
- data = read_excel(path_config.case_path, "login")
-
- @ddt
- class TestLogin(unittest.TestCase):
- @list_data(data)
- def test_login_success(self, case_data):
- print(case_data
- """
- 1、第一步得到响应数据
- 2、获取预期结果
- 3、预期结果与实际结果的对比
- """
- # 把json格式的字符串转换成字典,避免在读取的时候读取的是字符串而非字典格式
- json_data = json.loads(case_data["data"])
- headers = json.loads(case_data["headers"])
- expect = json.loads(case_data["expected"])
- respon = requests.request(
- method=case_data["method"],
- url=case_data["Api_Url"],
- json=json_data,
- headers=headers
- )
- actual = respon.json()
- self.assertEqual(actual["code"], expect["code"])
在config目录下创建setting.py,添加好对应的host域名,而后可以进行url的拼接:
- # 域名
- host = "http://IP:端口"
- """片段代码"""
- respon = requests.request(
- method=case_data["method"],
- # 进行拼接,拼接前导入setting
- url=setting.host + case_data["Api_Url"],
- json=json_data,
- headers=headers
- )
除此以外我们还需要进行断言的异常捕获,再次修改后的完整代码:
- import logging
- import unittest
- import requests
- import json
- from common.excel import read_excel
- from config import path_config
- from unittestreport import ddt, list_data
- from config import setting
-
-
- # 获取数据
- data = read_excel(path_config.case_path, "login")
-
- @ddt
- class TestLogin(unittest.TestCase):
- @list_data(data)
- def test_login_success(self, case_data):
- print(case_data)
- """
- 1、第一步得到响应数据
- 2、获取预期结果
- 3、预期结果与实际结果的对比
- """
- # 把json格式的字符串转换成字典,避免在读取的时候读取的是字符串而非字典格式
- json_data = json.loads(case_data["data"])
- headers = json.loads(case_data["headers"])
- expect = json.loads(case_data["expected"])
- respon = requests.request(
- method=case_data["method"],
- url=setting.host + case_data["Api_Url"],
- json=json_data,
- headers=headers
- )
- actual = respon.json()
- try:
- self.assertEqual(actual["code"], expect["code"])
- log.info(f"测试用例通过:{case_data}")
- except AssertionError as err:
- log.error(f"测试用例失败:{case_data},错误信息为:{err}")
- # 测试用例失败捕获后,使用raise抛出
- raise err
举个例子,我们在设计一个注册接口测试用例的时候,会碰到一个明显的瓶颈,该手机号是未进行注册的,在第一次执行自动化测试用例时能够成功的完成注册,但在第二次再次执行测试用例时会发现,手机号已存在,那么二次执行该测试用例就会执行失败,而面对这种情况,有以下几个解决思路:
- """
- 解决思路:
- 1、每一次通过手动的方式打开excel删除后重新输入一个新的手机号
- 2、在数据库中查询该手机号,如果该手机号已存在,那么在数据库进行手机号删除
- 3、在现有的手机号上的最末尾数+1
- 4、随机生成一个手机号
- 思路分析:
- 1、第一种方式虽然能够解决,但每一次执行时都需要人工手动的去替换,不便于维护
- 2、虽然能查询并删除手机号,但往往真实的项目不会轻易的做数据库删除操作,并且一个已注册手机号会有表关联,且大多数情况下测试无权限进行删除
- 3、这也是一个解决方式,我们可以在第11位数字上,每次都+1,弊端是终究会碰到可能会和其他手机号相冲突的号码从而执行失败,但效率远高于1和2
- 4、最后的方式也是动态参数化,在需要替换的数据上做标记,当循环遍历到这个标记时使用随机生成的号码替换这个标记,以在执行用例时能够顺利通过
- """
动态参数化就是为了解决这一类的问题,让手机号持续性的随机变更,让每一次的执行都不会因为手机号的重复而导致用例失败(使用动态参数化仍然可能会随机到已注册的号码,但概率极低),而随机生成某一个手机号码就需要用到数据伪造。
在自动化测试领域中数据伪造并非是什么破坏系统安全的事情,而是希望能够自动化生成测试用例的数据且数据符合一定的规则,例如手机号,电子邮箱等等。数据伪造安可以用在自动化注册模块,也可以用于登录或其他文本输入框来检测一定的输入规则等。
在Python中进行数据伪造库 – faker库,通过pip先进行安装后即可:
- import faker
-
- # 初始化faker对象,指定生成规则区域为中国
- fk = faker.Faker(locale="zh_CN")
- result = fk.phone_number()
- print(f"手机号:{result}")
-
- # 随机生成一个地址
- company = fk.company()
- print(f"地址:{company}")
-
- # 随机生成一个公司
- address = fk.address()
- print(f"公司:{address}")
-
- # 随机生成一个城市
- city = fk.city()
- print(f"城市:{city}")
除了标准的伪造库能够提供伪造外,我们也可以使用自己期望的方式来制定一个规则:
- def generate_new_phone():
- phone = "1" + random.choice(["3", "5", "7", "8", "9"])
- for i in range(9):
- num = random.randint(0, 9)
- phone += str(num)
- return phone
-
-
- print(f"函数式手机号:{generate_new_phone()}")
简易的封装伪造库函数,如果你是在框架中写数据伪造的代码,那么可以放在common中,从common中在导入以此来生成一些数据:
- import faker
-
- def generate_new_phone():
- fk = faker.Faker(locale="zh_CN")
- result = fk.phone_number()
- return result
- # 改动后的片段代码(如对片段代码有疑问,请参考前置文章):
- @ddt
- class TestLogin(unittest.TestCase):
- @list_data(data)
- def test_login_success(self, case_data):
- json_data = case_data["json"]
- if "#new_phone#" in json_data:
- new_phone = data_forgery.generate_new_phone()
- json_data = json_data.replace("#new_phone", new_phone)
最后:下面是配套学习资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!【100%无套路免费领取】
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux
6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 ,10、开放性测试题,11、安全测试,12、计算机基础