pytest之 fixture 实现机制

一、相同测试数据存放优化

在讲 fixture 实现机制之前,插入一段内容

上次有个小伙伴问我说,类似下面的用例代码情况,每条测试用例的数据都一样的,我们可以怎么进行优化吗?

当然是可以的

pytest之 fixture 实现机制

其实我们可以把这些用例的数据全部拿出来用列表的形式存放在datas,里面,然后遍历每一条数据进行判断

import pytest
from Day18_pytest_fixture.login import login_check datas = [
{"user":'python37', "passwd": 'lemonban', "check": {"code": 0, "msg": "登录成功"} },
{"user":'python37', "passwd": 'lemonban666', "check": {"code": 1, "msg": "账号或密码不正确"} },
{"user": 'python370', "passwd": 'lemonban', "check": {"code": 1, "msg": "账号或密码不正确"}},
{"user": None, "passwd": 'lemonban', "check": {"code": 1, "msg": "所有的参数不能为空"}},
{"user": 'python37', "passwd": None, "check": {"code": 1, "msg": "所有的参数不能为空"}}
]

# 第二步遍历每一条数据然后进行判断:
# 这种方法不太友好——只会执行一条用例,而且用例失败了就不能往下继续执行
# ——解决方法:pytest 框架自带的解决方法:@pytest.mark.parametrize("参数名",列表数据)
# class TestLogin:
# def test_login_success(self):
# for data in datas:
# actual = login_check(data["user"],data["passwd"])
# assert actual == data["check"]
# 解决:第二步遍历每一条数据然后进行判断的问题 class TestLogin: @pytest.mark.parametrize("case",datas) # 解决:第二步遍历每一条数据然后进行判断的问题
def test_login(self,case): #这里的case 要与上面装饰器的case 保持一致
actual = login_check(case["user"], case["passwd"])
assert actual == case["check"]

  

二、fixture 实现机制

通过@pytest.fixture 装饰器来定义fixture 。一个函数被@pytest.fixture 装饰,那么这个函数就是fixture。

使用fixture 时,分为两个部分: fixture 定义、fixture 调用。

除此之外,还有fixture 的共享机制,嵌套调用机制。

1、定义fixture

(1)fixture 通过函数实现

(2)使用@pytest.fixture 进行装饰

import pytest

@pytest.fixture
def init():
pass

2、fixture 的调用

在fixture定义好之后,可以明确:

1)fixture 处理了哪些前置准备工作、哪些后置清理工作

2)fixture 作用域(是测试函数?还是测试类,还是测试回话,还是测试模块?)

但是,注意一般情况下我们不会放在类里面去使用,一般是放在模块或者类外面使用的

 # (2)函数前面,要用@pytest.fixture来声明它是一个fixture
# autouse=True ——》有表示类下面的每条用例都会执行,没有表示整个类只执行一次, scope="class" : 表示设置作用域
@pytest.fixture(scope="class", autouse=True)
# (1)自定义一个函数名
def hello(self):
# 前置准备工作的代码
print("一条测试用例开始执行")
yield # yield之前的代码为:前置工作,yield之后的代码为:后置工作
# 后置清理工作的代码
print("一条测试用例执行结束")

  import pytest

from Day18_pytest_fixture.login import login_check

datas = [
{"user":'python37', "passwd": 'lemonban', "check": {"code": 0, "msg": "登录成功"} },
{"user":'python37', "passwd": 'lemonban666', "check": {"code": 1, "msg": "账号或密码不正确"} },
{"user": 'python370', "passwd": 'lemonban', "check": {"code": 1, "msg": "账号或密码不正确"}},
{"user": None, "passwd": 'lemonban', "check": {"code": 1, "msg": "所有的参数不能为空"}},
{"user": 'python37', "passwd": None, "check": {"code": 1, "msg": "所有的参数不能为空"}}
] # @pytest.fixture(scope="class",autouse=True)
@pytest.fixture(scope="class")
# (1)自定义一个函数名
def hello():# self 可以不要了,因为我们不是放在类里面了
# 前置准备工作的代码
print("一条测试用例开始执行")
print("======================================")
yield # yield之前的代码为:前置工作,yield之后的代码为:后置工作
# 后置清理工作的代码
print("一条测试用例执行结束") #可以同时调用多个
# @pytest.fixture(scope="class")
# def class_fix():
# # 前置准备工作的代码
# print("-----测试类下的用例开始执行------")
# yield
# # 后置清理工作的代码
# print("-----测试类下的用例执行结束------") #函数名可以随便取
# @pytest.mark.usefixtures("class_fix") # 调用函数名为class_fix的fixture.

@pytest.mark.usefixtures("hello") # 调用函数名为hello的fixture.,注意函数名不要写错了,写错了就会报错,因为程序找不到

#我们来思考一个问题,
类怎么去调用这个前后置模块的代码逻辑呢?——用例执行之前执行前置,用例执行之前后执行后置?——》@pytest.mark.usefixtures()
#@pytest.mark.usefixtures("hello") #pytest.mark.usefixtures("hello") 表示在执行当前类下的测试用例之前,会自动去寻找函数名叫hello的fixture并执行
class TestLogin:

@pytest.mark.parametrize("case",datas) # 解决:第二步遍历每一条数据然后进行判断的问题
def test_login(self,case): #这里的case 要与上面装饰器的case 保持一致
actual = login_check(case["user"], case["passwd"])
assert actual == case["check"]

# @pytest.mark.usefixtures("hello") #像这个是调用不了的,因为设置了作用域,只能类下面去调用

def test_hello_world():
print("我是模块下的测试用例")
 
上一篇:【Pytest03】全网最全最新的Pytest框架fixture应用篇(1)


下一篇:unittest的前置后置,pytest的fixture和共享机制conftest.py