全网最牛,接口自动化测试mock框架模块实战,入门到高阶...


前言

mock的介绍

py3已将mock集成到unittest库中;
为的就是更好的进行单元测试;
简单理解,模拟接口返回参数;
通俗易懂,直接修改接口返回参数的值;

mock的作用

1、解决依赖问题,达到解耦作用
当我们测试某个目标接口(模块)时,该接口依赖其他接口,当被依赖的接口未开发完成时,可以用mock模拟被依赖接口,完成目标接口的测试;

2、模拟复杂业务的接口
当我们测试某个目标接口(模块),该接口依赖一个非常复杂的接口时,可以用mock来模拟这个复杂的业务接口;也解决接口依赖一样的原理

3、单元测试
如果某个接口(模块)未开发完成时,又需要编写测试用例,则可以通过mock模拟该接口(模块)进行测试

4、前后端联调
前端开发的页面需要根据后端返回的不同状态码展示不同的页面,当后端接口未开发完成时,也可通过mock来模拟后端接口返回自己想要的数据

mock类解读

class Mock(spec=None,side_effect=None,return_value=DEFFAULT,name=None) 

secp:定义mock对象的属性值,可以是列表,字符串,甚至一个对象或者实例
side_effect:可以用来抛出异常或者动态改变返回值,它必须是一个iterator(列表),它会覆盖return_value
return_value:定义mock方法的返回值,它可以是一个值,可以是一个对象(如果存在side_effect参数那这个就没有用,也就是不能同时用)
name:作为mock对象的一个标识,在print时可以看到

mock实际使用

一个未开发完成的功能如何测试?

def add(self, a, b):
    """两个数相加"""
    pass


class TestSub(unittest.TestCase):
    """测试两个数相加用例"""

    def test_sub(self):
        # 创建一个mock对象 return_value代表mock一个数据
        mock_add = mock.Mock(return_value=15)
        # 将mock对象赋予给被测函数
        add = mock_add
        # 调用被测函数
        result = add(5, 5)
        # 断言实际结果和预期结果
        self.assertEqual(result, 15)

一个完成开发的功能如何测试?

class SubClass(object):
    def add(self, a, b):
        """两个数相加"""
        return a + b


class TestSub(unittest.TestCase):
    """测试两个数相加用例"""


    def test_add2(self):
        # 初始化被测函数类实例
        sub = SubClass()
        # 创建一个mock对象 return_value代表mock一个数据
        # 传递side_effect关键字参数, 会覆盖return_value参数值, 使用真实的add方法测试
        sub.add = Mock(return_value=15, side_effect=sub.add)
        # 调用被测函数
        result = sub.add(5, 5)
        # 断言实际结果和预期结果
        self.assertEqual(result, 10)

side_effect:这里给的参数值是sub.add相当于add方法的地址,当我们调用add方法时就会调用真实的add方法

简单理解成:传递了side_effect参数且值为被测函数地址时,mock不会起作用;两者不可共存

另外,side_effect接受的是一个可迭代序列,当传递多个值时,每次调用mock时会返回不同的值;

mock_obj = mock.Mock(side_effect= [1,2,3])
print(mock_obj())
print(mock_obj())
print(mock_obj())
print(mock_obj())

# 输出
Traceback (most recent call last):
File "D:/MyThreading/mymock.py", line 37, in <module>
print(mock_obj())
File "C:\Python36\lib\unittest\mock.py", line 939, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "C:\Python36\lib\unittest\mock.py", line 998, in _mock_call
result = next(effect)
StopIteration

存在依赖关系的功能如何测试?

# 支付类
class Payment:

    def requestOutofSystem(self, card_num, amount):
        '''
        请求第三方外部支付接口,并返回响应码
        :param card_num: 卡号
        :param amount: 支付金额
        :return: 返回状态码,200 代表支付成功,500 代表支付异常失败
        '''
        # 第三方支付接口请求地址(故意写错)
        url = "http://third.payment.pay/"
        # 请求参数
        data = {
    
    "card_num": card_num, "amount": amount}
        response = requests.post(url, data=data)
        # 返回状态码
        return response.status_code

    def doPay(self, user_id, card_num, amount):
        '''
        支付
        :param userId: 用户ID
        :param card_num: 卡号
        :param amount: 支付金额
        :return:
        '''
        try:
            # 调用第三方支付接口请求进行真实扣款
            resp = self.requestOutofSystem(card_num, amount)
            print('调用第三方支付接口返回结果:', resp)
        except TimeoutError:
            # 如果超时就重新调用一次
            print('重试一次')
            resp = self.requestOutofSystem(card_num, amount)

        if resp == 200:
            # 返回第三方支付成功,则进行系统里面的扣款并记录支付记录等操作
            print("{0}支付{1}成功!!!进行扣款并记录支付记录".format(user_id, amount))
            return 'success'

        elif resp == 500:
            # 返回第三方支付失败,则不进行扣款
            print("{0}支付{1}失败!!不进行扣款!!!".format(user_id, amount))
            return 'fail'

# 单元测试类
class payTest(unittest.TestCase):

    def test_pay_success(self):
        pay = Payment()
        # 模拟第三方支付接口返回200
        pay.requestOutofSystem = mock.Mock(return_value=200)
        resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
        self.assertEqual('success', resp)

    def test_pay_fail(self):
        pay = Payment()
        # 模拟第三方支付接口返回500
        pay.requestOutofSystem = mock.Mock(return_value=500)
        resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
        self.assertEqual('fail', resp)

    def test_pay_time_success(self):
        pay = Payment()
        # 模拟第三方支付接口首次支付超时,重试第二次成功
        pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 200])
        resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
        self.assertEqual('success', resp)

    def test_pay_time_fail(self):
        pay = Payment()
        # 模拟第三方支付接口首次支付超时,重试第二次失败
        pay.requestOutofSystem = mock.Mock(side_effect=[TimeoutError, 500])
        resp = pay.doPay(user_id=1, card_num='12345678', amount=100)
        self.assertEqual('fail', resp)

可能会有人问:第三方支付都不能用,我们的测试结果是否是有效的呢?

通常在测试一个模块的时候,是可以认为其他模块的功能是正常的,只针对目标模块进行测试是没有任何问题的,所以说测试结果也是正确的

mock装饰器

一共两种格式

 @patch('module名字.方法名') 
 @patch.object(类名, '方法名') 
# 装饰类演示
from mock import Mock, patch


# 单独的相乘函数
def multiple(a, b):
    return a * b


# 单独的捕获Exception函数
def is_error():
    try:
        os.mkdir("11")
        return False
    except Exception as e:
        return True


# 计算类,包含add方法
class calculator(object):
    def add(self, a, b):
        return a + b


# 装饰类演示 - 单元测试类
class TestProducer(unittest.TestCase):

    # case执行前
    def setUp(self):
        self.calculator = calculator()

    # mock一个函数,注意也要指定module
    @patch('mock_learn.multiple')
    def test_multiple(self, mock_multiple):
        mock_multiple.return_value = 3
        self.assertEqual(multiple(8, 14), 3)

    # mock一个类对象的方法
    @patch.object(calculator, 'add')
    def test_add(self, mock_add):
        mock_add.return_value = 3
        self.assertEqual(self.calculator.add(8, 14), 3)

    # mock调用方法返回多个不同的值
    @patch.object(calculator, 'add')
    def test_effect(self, mock_add):
        mock_add.side_effect = [1, 2, 3]
        self.assertEqual(self.calculator.add(8, 14), 1)
        self.assertEqual(self.calculator.add(8, 14), 2)
        self.assertEqual(self.calculator.add(8, 14), 3)

    # mock的函数抛出Exception
    @patch('os.mkdir')
    def test_exception(self, mkdir):
        mkdir.side_effect = Exception
        self.assertEqual(is_error(), True)

    # mock多个函数,注意函数调用顺序
    @patch.object(calculator, 'add')
    @patch('mock_learn.multiple')
    def test_more(self, mock_multiple, mock_add):
        mock_add.return_value = 1
        mock_multiple.return_value = 4
        self.assertEqual(self.calculator.add(3, 3), 1)
        self.assertEqual(multiple(3, 3), 4)
下面是我整理的2023年最全的软件测试工程师学习知识架构体系图

一、Python编程入门到精通

请添加图片描述

二、接口自动化项目实战

请添加图片描述

三、Web自动化项目实战

请添加图片描述

四、App自动化项目实战

请添加图片描述

五、一线大厂简历

请添加图片描述

六、测试开发DevOps体系

请添加图片描述

七、常用自动化测试工具

请添加图片描述

八、JMeter性能测试

请添加图片描述

九、总结(尾部小惊喜)

只有勇往直前的人,才能创造属于自己的奇迹;只有愿意付出的人,才能收获真正的成就;只有坚持不懈的人,才能实现自己的梦想。别停下脚步,勇敢地追逐,你将发现无限可能!

只有坚持不懈的努力,才能追逐梦想;只有永不放弃的奋斗,才能创造辉煌。每一天的努力,都铸就美好未来的希望。相信自己,勇往直前,你将收获无限可能!

只有不断努力,才会收获辉煌的未来;只有持之以恒,才能攀登人生的高峰;只有坚定信念,才能战胜一切困难;只有挑战自我,才能超越自己的极限。奋斗吧,你就是无敌的!

猜你喜欢

转载自blog.csdn.net/m0_70102063/article/details/131457581