目录
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. 选择默认执行方式
点击OK
2. 配置执行的命令
3. 新增一条
4. 选择test的文件
注:1处:为目录时执行目录下所有的test_*.py;为文件时只运行单test文件。
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