UnitTest:pytest&moto(用于mock)

1. 安装pytest

pip install pytest
pip install moto[all]  # 模拟aws环境或类/方法行为
pip install responses  # 模拟requests请求的响应
@pytest.fixture(scope='class', autouse=True)
autouse=True自动执行
scope=function装饰在def上,数据仅在def中有效;不装饰的话需要写在def的参数中;
scope=class装饰在class上,数据在class中所有def中有效(数据可以在多个def中共享);
scope=module,一般需要autouse=True 装饰不装饰都行,数据在本模块有效.py文件(数据可以在多个class/def中共享);

2. pycharm配置

1. 选择默认执行方式

1
点击OK

2. 配置执行的命令

2

3. 新增一条

3

4. 选择test的文件

注:1处:为目录时执行目录下所有的test_*.py;为文件时只运行单test文件。
4

3. 模拟AWS

import pytest
import boto3
import os
import unittest
from moto import mock_aws
from apis.auth.sso import get
from apis.auth.config import REGION_NAME


@pytest.fixture(scope="function")
def aws_credentials_f():
    """Mocked AWS Credentials for moto."""
    print('*' * 30)
    print('每个用例之前执行一次')
    os.environ["TT"] = "Function"
    print('设置环境变量TT')
    yield 'aws_credentials_f的返回值'
    print('每个用例之后执行一次')


# @pytest.fixture(scope='function', autouse=False, params=['第1次', '第2次', '第3次'], ids=['1', '2', '3'], name='exe_db')
@pytest.fixture(scope="function")
def aws_credentials_c():
    """Mocked AWS Credentials for moto."""
    print('*' * 30)
    os.environ["TT"] = "Class"
    print('设置环境变量TT')
    yield 'aws_credentials_c的返回值'  # 有params时可调用request.param(params中的某个元素),request为当前function的形参


class AwsTestCaseBase:

    def setup_class(self):
        print('每个类之前执行一次')

    def teardown_class(self):
        print('每个类之后执行一次')

    def setup_method(self):
        print('每个用例之前执行一次')

    def teardown_method(self):
        print('每个用例之后执行一次')


@pytest.mark.usefixtures("aws_credentials_c")
@mock_aws
class TestSso(AwsTestCaseBase):
    # 继承AwsTestCaseBase的话,每个test共享boto3中内容,而且test中可接受fixture的参数
    # 继承unittest.TestCase的话,每个test独立boto3中内容,而且test中不接受fixture的参数

    def test_get_sso_url(self):
    # def test_get_sso_url(self, aws_credentials_c):
        # print(aws_credentials_c)
        # get(1, 2)
        s3 = boto3.client('s3', region_name=REGION_NAME)
        s3.create_bucket(Bucket='bucket_by_function')
        result = boto3.client('s3', region_name=REGION_NAME).list_buckets()
        assert len(result["Buckets"]) == 1
        print('创建数量一致 by class')
        print('环境变量:' + os.environ.get('TT', 'None'))

    def test_s3_is_save(self):
        result = boto3.client("s3", region_name=REGION_NAME).list_buckets()
        print(f'当前buckets数量: {len(result["Buckets"])}')


@pytest.mark.usefixtures('aws_credentials_f')
@mock_aws
def test_22(aws_credentials_f):
    print(aws_credentials_f)  # 可以获取fixtures返回值
    get(1, 2)  # 调用方法
    result = boto3.client("s3", region_name=REGION_NAME).list_buckets()
    assert len(result["Buckets"]) == 1
    print('创建数量一致 by function')
    print('环境变量:' + os.environ.get('TT', 'None'))


4. 模拟类或方法行为

引入待测试的方法或类时,一定是引入截止到文件
例如:from auth import helper
不能是:from auth.helper import A, b # patch将不会覆盖原有函数

1. 模拟方法

# 假设 auth/helper.py 文件中有一个 b 函数  
# auth/helper.py  
# def b(x):  
#     return x  # 假设原始实现是这样的  
  
# 测试文件  
from unittest.mock import patch  
from auth import helper  # 

@pytest.fixture(scope='function')  # function时仅在def前创建,def结束时销毁(不会共享数据)
def ddddd():
	...
    yield
  
def test_b(ddddd):  
    with patch('auth.helper.b') as mock_b:  
        # 方式1
        mock_b.return_value = 10  
        # 这里调用的是 auth.helper 中的 b 函数,因为我们在 with 块内,并且通过 auth.helper 导入的  
        result = helper.b(5)  
        assert result == 10  # 这将通过  

2. 模拟类

# 假设 auth/helper.py 文件中有一个A 类  
# auth/helper.py  
# class A:
#    def __init__(self, y):
#        self.y = y
#    def add(self, x):
#        return x + self.y  
  
# 测试文件  
from unittest.mock import patch  
from auth import helper  # 

@pytest.fixture(scope='class')  # class时仅在class前创建,class结束时销毁(class中所有def共享数据)
def ddddd():
	...
    yield
  
def test_b(ddddd):  
    with patch('auth.helper.A') as mock_a:  
        mock_instance = MagicMock()
        mock_instance.a.return_value = 10
        mock_a.return_value = mock_instance
        # 这里调用的是 auth.helper 中的 A,因为我们在 with 块内,并且通过 auth.helper 导入的  
        aa = helper.A(5)
        assert aa.add(2) == 10  # 这将通过  

注意:这个测试函数需要在测试框架中运行,比如使用 pytest 或 unittest 如果你直接在脚本中运行这个 test_b 函数,它可能不会按预期工作,因为 patch 的上下文管理器不会在脚本结束时自动关闭

5. 模拟requests

import responses
import requests

def test_b():  
	url=OAUTH_JWKS_URL.format(tenant_id=tenant)
    responses.add(
    	responses.GET,  # 请求方式
    	url=url,  # url
    	json={"keys": [{"kid": 'kid', "kty": 'kty', 'use': 'use', 'n': '50', 'e': '30'}]}, # 返回参数
    	status=200,  # 返回状态码
    	match=[responses.matchers.query_param_matcher({})]  # 请求参数
    ) 
    res = requests.get(url)  # 返回值为以上定义的json
	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值