前言

在之前的介绍中,我们已经介绍了fixture的简单用法,但其实fixture还提供了两种非常优雅高效的写法,来完成测试执行前的处理操作与执行后的处理操作,即使用yield或addfinalizer来实现。本文我们将介绍使用yield来实现操作。

yield

在fixture中的关键字yield主要有两个作用:

yield代替return进行参数的传递起到代码的分割作用,yield之前的代码为setup的作用,yield之后的代码为teardown的作用

yield 与 return

在 pytest 的fixture函数中可以使用yield代替return进行返回,示例如下:

import pytest

@pytest.fixture(autouse=True)

def fixture_one():

print("执行fixture_one")

yield 1

def test_e(fixture_one):

print("执行test_e")

print(fixture_one)

assert fixture_one == 1

if __name__ == '__main__':

pytest.main(["-s"])

----------------

执行结果如下:

test_case_4.py::test_e

执行fixture_one

PASSED [100%]执行test_e

1

============================== 1 passed in 0.12s ==============================

从运行结果我们能看到fixture_one会返回1并传递给test_e,与return的作用完全一致。但如果仅仅只是这样使用的话,毫无意义,因为使用return足够了。所以,在实际的使用过程中我们一般会在yield后面加上teardown的代码。

yield 与 teardown

yield不进行参数传递

对于不需要在前置操作中返回数据的 fixture 函数,加入yield,那么yield之前的代码为用例执行之前的操作(即setup),yield之后的代码为用例执行之后的操作(即teardown)。示例如下:

import pytest

@pytest.fixture()

def fixture_demo():

# setup

print("\n连接数据库")

yield

# teardown

print("清空脏数据")

def test_case(fixture_demo):

print("执行test_case")

assert True

if __name__ == '__main__':

pytest.main(["-s"])

--------------------

运行结果如下:

============================= test session starts =============================

collecting ... collected 1 item

test_demo01.py::test_case

连接数据库

PASSED [100%]执行test_case

清空脏数据

============================== 1 passed in 0.02s ==============================

从结果中我们可以看出来,先执行了setup部分,再执行测试用例,最后执行teardown部分。

yield进行参数传递

yield可以将参数传递给测试用例。

假设有这样一个场景,需要用到接口1的返回参数作为接口2的请求参数,即接口2依赖接口1,我们需要写一条测试用例对接口2进行测试,这个时候可以将接口1的请求写在前置中,如果是unittest框架则代码如下:

import unittest

import requests

class TestDemo(unittest.TestCase):

def setup(self):

print("请求接口1")

self.res_1 = requests.get(url=url_1, params=params_1)

def test_api_2(self):

print("验证接口2")

# 将接口1的返回值self.res_1作为请求参数,请求接口2

res = requests.post(url=url_2, data=self.res_1)

# 断言

self.assertEqual(res, "接口2预期的返回结果")

def teardown(self):

print("清空脏数据")

在pytest框架中使用fixture+yield则可编写如下:

@pytest.fixture()

def get_api_1_result():

# setup

res_1 = requests.get(url=url_1, params=params_1)

yield res_1

# teardown

print("清空脏数据")

def test_api_2(get_api_1_result):

print("验证接口2")

# 将接口1的返回值res_1作为请求参数,请求接口2

res = requests.post(url=url_2, data=get_api_1_result)

# 断言

assert res == "接口2预期的返回结果"

其中,fixture 会先通过yield返回res_1,并传入测试用例test_api_2中,test_api_2运行完成后再去执行yield后面的代码,即执行print("清空脏数据")。

通过以上对比unittest中setup、teardown以及参数的传递,我们就能很直观的看出pytest中yield的使用方式,此处代码仅为示例。

yield 的执行顺序

有时候我们会遇到一个fixture函数调用另一个或多个fixture函数,且这些函数中可能含有yield,我们先看示例,代码如下:

import pytest

@pytest.fixture

def fixture_1():

print("\n执行fixture_1")

yield 1

print("\n执行fixture_1的teardown代码")

@pytest.fixture

def fixture_2(fixture_1):

print("\n执行fixture_2")

yield 2

print("\n执行fixture_2的teardown代码")

@pytest.fixture

def fixture_add(fixture_1, fixture_2):

print("\n执行fixture_add")

result = fixture_1 + fixture_2

yield result

print("\n执行fixture_add的teardown代码")

def test_demo(fixture_add):

print("\n执行测试函数test_demo")

assert fixture_add == 3

if __name__ == '__main__':

pytest.main(["-s"])

-----------

执行结果如下:

collecting ... collected 1 item

test_case_4.py::test_demo

执行fixture_1

执行fixture_2

执行fixture_add

PASSED [100%]

执行测试函数test_demo

执行fixture_add的teardown代码

执行fixture_2的teardown代码

执行fixture_1的teardown代码

============================== 1 passed in 0.12s ==============================

从结果可以看出:

test_demo·测试函数执行之前:先执行了 fixture_1,再执行fixture_2,最后执行fixture_add,注意此时都是执行yield之前的的代码;

test_demo 测试函数执行之后:先执行了 fixture_add,再执行fixture_2,最后执行fixture_1,注意此时都是执行yield之后的的代码。

因此,当一个fixture函数调用另一个或多个fixture函数,且fixture函数中含有yield时,被测试函数调用时有如下执行顺序:

测试函数执行之前,pytest会根据fixture函数之间的线性关系顺序调用,即依次执行yield之前的代码。 而测试函数执行结束后,pytest会根据之前的顺序反方向执行fixture函数中yield之后的代码。

总结

总的来说,yield 关键字为 Pytest fixture 提供了一种优雅的方式来处理资源管理、测试环境设置和清理工作,使得测试代码更加健壮和可靠。希望本文能够帮到大家!

获取更多技术资料,请点击!

推荐

Python全栈开发与自动化测试开发班 由浅入深实战进阶,从小白到高手

以Python全栈开发为基础,深入教授自动化测试技能,为学员打造全面的技术能力。通过系统学习和实际项目实战,学员将具备在职场中脱颖而出的竞争力。不仅能够灵活运用Python进行开发,还能够保障项目质量通过自动化测试手段。这是一个全面提升职业竞争力的机会。

课程详情 Python开发必备基础技能与项目实战 Pvthon 编程语言/算法和数据结构/面向对象编程Web后端开发/前端开发/测试管理平台项目实战

人工智能ChatGPT实战 人工智能辅助学习各种开发和测试技能/Pytorch深度学框架/平台开发实战

数据分析与自动化办公 数据采集/Pandas与数据处理技术/ECharts与数据可视化技术/爬虫实战/自动化办公/批量文件处理

UI自动化测试与高级项目实战 Web自动化测试/App自动化测试/ PageObject设计模式

接口自动化测试 接口协议分析/Mock实战/服务端接口测试

性能测试 性能测试流程与方法/JMeter 脚本参数化/Grafana监控系统搭建

简历指导与模拟面试 1V1简历指导/模拟真实面试/测试开发岗面试全攻略名企私教服务 名企专家1v1辅导/行业专家技术指导/针对性解决工作难题/绩效提升辅导与晋升复盘

课程亮点 名企私教服务 先学习后付费 高额奖学金 专属社群+晚自习在线答疑 5V1全方位辅导作业+考试强化学习效果 简历修改 模拟面试 就业内推 面试复盘

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: