• 接口自动化测试实战之接口框架修改与动态参数化与数据伪造


    一、前言

    本文章主要讲解Python接口自动化测试的框架搭建修改,自动化测试用例设计、接口测试中用例设计的动态参数化形式等内容,本文章会跳过部分框架搭建内容,废话不多说,让我们一起来看看叭。

    二、实战演练

    2.1 接口介绍

    我们先用一个接口为出发点,该接口为登录接口,请求方式为POST,登录后才可以进行各式各样的操作,基本信息如下所示:

     

    2.2 接口excel测试用例

    按照登录接口文档,进行测试用例的设计:

    2.3框架common目录

    测试用例属于数据,那么我们必定要读取excel,我们也有配置文件,还有日志系统,这些都属于通用内容,我们可以先将对应的代码模块添加到common中:

    1. """读取excel,有更简便的方法,该方法适合新手进行学习了解"""
    2. import openpyxl
    3. def read_excel(file_path, sheet_name):
    4. """读取excel中的数据"""
    5. workbook = openpyxl.load_workbook(file_path)
    6. sheet = workbook[sheet_name]
    7. values = list(sheet.values)
    8. workbook.close()
    9. title = values[0]
    10. rows = values[1:]
    11. new_rows = [dict(zip(title, rows)) for rows in rows]
    12. return new_rows
    13. """日志系统"""
    14. import logging
    15. def get_logger(logging_name="收集器",
    16. logger_level="DEBUG",
    17. stream_level="DEBUG",
    18. file=None,
    19. file_level="INFO",
    20. fmt="%(asctime)s--%(levelname)s--%(filename)s--%(lineno)d--%(message)s"):
    21. """获取logger收集器"""
    22. logger = logging.getLogger(logging_name)
    23. logger.setLevel(logger_level)
    24. stream_handler = logging.StreamHandler()
    25. stream_handler.setLevel(stream_level)
    26. logger.addHandler(stream_handler)
    27. fmt_obj = logging.Formatter(fmt)
    28. stream_handler.setFormatter(fmt_obj)
    29. # 判断是否有文件,如果有,初始化file_handler,如果没有文件则不执行
    30. if file:
    31. file_handler = logging.FileHandler(file, encoding="utf-8")
    32. file_handler.setLevel("INFO")
    33. logger.addHandler(file_handler)
    34. file_handler.setFormatter(fmt_obj)
    35. return logger
    36. log = get_logger()
    37. """yaml读取结果"""
    38. import yaml
    39. def read_yaml(file, encoding="utf-8"):
    40. with open(file, encoding="utf-8") as f:
    41. data = yaml.safe_load(f)
    42. return data

    2.4 测试用例设计

    在testcase目录下新建test_login用于测试登录并实现好excel的读取以及数据驱动,获取用例数据后我们先打印看下数据:

    1. import unittest
    2. import requests
    3. from common.excel import read_excel
    4. from config import path_config
    5. from unittestreport import ddt, list_data
    6. # 获取数据
    7. data = read_excel(path_config.case_path, "login")
    8. @ddt
    9. class TestLogin(unittest.TestCase):
    10. @list_data(data)
    11. def test_login_success(self, case_data):
    12. print(case_data)

     

    补充的完整代码如下所示:

    1. import unittest
    2. import requests
    3. import json
    4. from common.excel import read_excel
    5. from config import path_config
    6. from unittestreport import ddt, list_data
    7. # 获取数据
    8. data = read_excel(path_config.case_path, "login")
    9. @ddt
    10. class TestLogin(unittest.TestCase):
    11. @list_data(data)
    12. def test_login_success(self, case_data):
    13. print(case_data
    14. """
    15. 1、第一步得到响应数据
    16. 2、获取预期结果
    17. 3、预期结果与实际结果的对比
    18. """
    19. # 把json格式的字符串转换成字典,避免在读取的时候读取的是字符串而非字典格式
    20. json_data = json.loads(case_data["data"])
    21. headers = json.loads(case_data["headers"])
    22. expect = json.loads(case_data["expected"])
    23. respon = requests.request(
    24. method=case_data["method"],
    25. url=case_data["Api_Url"],
    26. json=json_data,
    27. headers=headers
    28. )
    29. actual = respon.json()
    30. self.assertEqual(actual["code"], expect["code"])

     

    2.5 用例设计优化

    在config目录下创建setting.py,添加好对应的host域名,而后可以进行url的拼接:

    1. # 域名
    2. host = "http://IP:端口"
    3. """片段代码"""
    4. respon = requests.request(
    5. method=case_data["method"],
    6. # 进行拼接,拼接前导入setting
    7. url=setting.host + case_data["Api_Url"],
    8. json=json_data,
    9. headers=headers
    10. )

    除此以外我们还需要进行断言的异常捕获,再次修改后的完整代码:

    1. import logging
    2. import unittest
    3. import requests
    4. import json
    5. from common.excel import read_excel
    6. from config import path_config
    7. from unittestreport import ddt, list_data
    8. from config import setting
    9. # 获取数据
    10. data = read_excel(path_config.case_path, "login")
    11. @ddt
    12. class TestLogin(unittest.TestCase):
    13. @list_data(data)
    14. def test_login_success(self, case_data):
    15. print(case_data)
    16. """
    17. 1、第一步得到响应数据
    18. 2、获取预期结果
    19. 3、预期结果与实际结果的对比
    20. """
    21. # 把json格式的字符串转换成字典,避免在读取的时候读取的是字符串而非字典格式
    22. json_data = json.loads(case_data["data"])
    23. headers = json.loads(case_data["headers"])
    24. expect = json.loads(case_data["expected"])
    25. respon = requests.request(
    26. method=case_data["method"],
    27. url=setting.host + case_data["Api_Url"],
    28. json=json_data,
    29. headers=headers
    30. )
    31. actual = respon.json()
    32. try:
    33. self.assertEqual(actual["code"], expect["code"])
    34. log.info(f"测试用例通过:{case_data}")
    35. except AssertionError as err:
    36. log.error(f"测试用例失败:{case_data},错误信息为:{err}")
    37. # 测试用例失败捕获后,使用raise抛出
    38. raise err

    三、动态参数化

    举个例子,我们在设计一个注册接口测试用例的时候,会碰到一个明显的瓶颈,该手机号是未进行注册的,在第一次执行自动化测试用例时能够成功的完成注册,但在第二次再次执行测试用例时会发现,手机号已存在,那么二次执行该测试用例就会执行失败,而面对这种情况,有以下几个解决思路:

    1. """
    2. 解决思路:
    3. 1、每一次通过手动的方式打开excel删除后重新输入一个新的手机号
    4. 2、在数据库中查询该手机号,如果该手机号已存在,那么在数据库进行手机号删除
    5. 3、在现有的手机号上的最末尾数+1
    6. 4、随机生成一个手机号
    7. 思路分析:
    8. 1、第一种方式虽然能够解决,但每一次执行时都需要人工手动的去替换,不便于维护
    9. 2、虽然能查询并删除手机号,但往往真实的项目不会轻易的做数据库删除操作,并且一个已注册手机号会有表关联,且大多数情况下测试无权限进行删除
    10. 3、这也是一个解决方式,我们可以在第11位数字上,每次都+1,弊端是终究会碰到可能会和其他手机号相冲突的号码从而执行失败,但效率远高于1和2
    11. 4、最后的方式也是动态参数化,在需要替换的数据上做标记,当循环遍历到这个标记时使用随机生成的号码替换这个标记,以在执行用例时能够顺利通过
    12. """

    动态参数化就是为了解决这一类的问题,让手机号持续性的随机变更,让每一次的执行都不会因为手机号的重复而导致用例失败(使用动态参数化仍然可能会随机到已注册的号码,但概率极低),而随机生成某一个手机号码就需要用到数据伪造。

    四、数据伪造

    在自动化测试领域中数据伪造并非是什么破坏系统安全的事情,而是希望能够自动化生成测试用例的数据且数据符合一定的规则,例如手机号,电子邮箱等等。数据伪造安可以用在自动化注册模块,也可以用于登录或其他文本输入框来检测一定的输入规则等。

    在Python中进行数据伪造库 – faker库,通过pip先进行安装后即可:

    1. import faker
    2. # 初始化faker对象,指定生成规则区域为中国
    3. fk = faker.Faker(locale="zh_CN")
    4. result = fk.phone_number()
    5. print(f"手机号:{result}")
    6. # 随机生成一个地址
    7. company = fk.company()
    8. print(f"地址:{company}")
    9. # 随机生成一个公司
    10. address = fk.address()
    11. print(f"公司:{address}")
    12. # 随机生成一个城市
    13. city = fk.city()
    14. print(f"城市:{city}")

     

    除了标准的伪造库能够提供伪造外,我们也可以使用自己期望的方式来制定一个规则:

    1. def generate_new_phone():
    2. phone = "1" + random.choice(["3", "5", "7", "8", "9"])
    3. for i in range(9):
    4. num = random.randint(0, 9)
    5. phone += str(num)
    6. return phone
    7. print(f"函数式手机号:{generate_new_phone()}")

     

    简易的封装伪造库函数,如果你是在框架中写数据伪造的代码,那么可以放在common中,从common中在导入以此来生成一些数据:

    1. import faker
    2. def generate_new_phone():
    3. fk = faker.Faker(locale="zh_CN")
    4. result = fk.phone_number()
    5. return result
    6. # 改动后的片段代码(如对片段代码有疑问,请参考前置文章):
    7. @ddt
    8. class TestLogin(unittest.TestCase):
    9. @list_data(data)
    10. def test_login_success(self, case_data):
    11. json_data = case_data["json"]
    12. if "#new_phone#" in json_data:
    13. new_phone = data_forgery.generate_new_phone()
    14. 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、计算机基础

      全套资料获取方式:点击下方小卡片自行领取即可

  • 相关阅读:
    PWN保护机制以及编译方法
    实战干货!用 Python 爬取股票实时数据!
    39.组合总和
    Apache HBase MTTR 优化实践
    Win11搭建 Elasticsearch 7 集群(一)
    Vue 路由 ElementUI组件库
    前端学习笔记--面试题系列总结
    嵌入式Linux入门-Linux文件IO讲解并实现copy程序
    springboot同城流浪动物救助与收养网站
    springboot社区人员管理系统的设计与实现毕业设计源码260839
  • 原文地址:https://blog.csdn.net/weixin_57794111/article/details/133207066