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

一、前言

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

二、实战演练

2.1 接口介绍

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

2.2 接口excel测试用例

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

2.3框架common目录

测试用例属于数据,那么我们必定要读取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

2.4 测试用例设计

在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"])

2.5 用例设计优化

在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、计算机基础

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

猜你喜欢

转载自blog.csdn.net/weixin_57794111/article/details/133207066