7.pytest强大的fixture(中)

scope:在类/模块/整个测试中共享fixture实例

当fixture需要访问网络时,因为依赖于网络状况,通常是一个非常耗时的动作 。

扩展下上面的示例,我们可以将scope="module"参数添加到@pytest.fixture中,这样每个测试模块就只会调用一次smtp_connection的fixture函数(默认情况下时每个测试函数都调用一次)。因此,一个测试模块中的多个测试函数将使用同样的smtp_connection实例,从而节省了反复创建的时间。

scope可能的值为:function, class, module, package 和 session

下面的示例将fixture函数放在独立的conftest.py中,这样可以在多个测试模块中访问使用该测试fixture:

# conftest.py 
import pytest 
import smtplib 

@pytest.fixture(scope="module")
def smtp_connection(): 
	return smtplib.SMTP("smtp.qq.com", 587, timeout=5) 

fixture的名称依然为smtp_connection,你可以在任意的测试用例中通过该名称来调用该fixture(在conftest.py所在的目录及子目录下)

# test_module.py 

def test_ehlo(smtp_connection): 
	response, msg = smtp_connection.ehlo() 
	assert response == 250 assert b"smtp.qq.com" in msg 
	assert 0 # for debug 
	
def test_noop(smtp_connection): 
	response, msg = smtp_connection.noop() 
	assert response == 250 assert 0 # for debug 

我们故意添加了assert 0的断言来查看测试用例的运行情况:

(pytest) D:\study\auto-pytest>pytest test_module.py
======================= test session starts =======================
platform win32 -- Python 3.7.1, pytest-6.0.2, py-1.9.0, pluggy-0.13.1
rootdir: D:\study\auto-pytest
collected 2 items 

test_module.py FF [100%]

======================= FAILURES =======================
_______________________ test_ehlo _______________________

smtp_connection = <smtplib.SMTP object at 0x000001BDA449BB70>def test_ehlo(smtp_connection):response, msg = smtp_connection.ehlo()assert response == 250
> assert b"smtp.qq.com" in msg
E AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrsza5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME'

test_module.py:4: AssertionError
_______________________ test_noop _______________________

smtp_connection = <smtplib.SMTP object at 0x000001BDA449BB70>def test_noop(smtp_connection):response, msg = smtp_connection.noop()assert response == 250
> assert 0# for debug
E assert 0

test_module.py:11: AssertionError
======================= short test summary info =======================
FAILED test_module.py::test_ehlo - AssertionError: assert b'smtp.qq.com' in b'newxmesmtplogicsvrsza5.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAIL...

FAILED test_module.py::test_noop - assert 0
======================= 2 failed in 0.32s ======================= 

可以看到这两个用例都失败了,并且你可以在traceback中看到smtp_connection被传进了这两个测试函数中。这两个函数复用了同一个smtp_connection实例如果你需要一个session作用域的smtp_connection实例,你可以按照如下来定义:

@pytest.fixture(scope="session") 
def smtp_connection(): #该固件会在所有的用例中共享 

scope定义为class的话会创建一个在每个class中调用一次的fixture

注意: Pytest对于每个fixture只会缓存一个实例,这意味着如果使用参数化的fixture,pytest可能会比定义的作用域更多次的调用fixture函数(因为需要创建不同参数的fixture)

scope越大,实例化越早

当函数调用多个fixtures的时候,scope较大的(比如session)实例化早于scope较小的(比如function或者class)。同样scope的顺序则按照其在测试函数中定义的顺序及依赖关系来实例化。

@pytest.fixture(scope="session") 
def s1(): pass 

@pytest.fixture(scope="module") 
def m1(): pass 

@pytest.fixture 
def f1(tmpdir): pass 

@pytest.fixture 
def f2(): pass 

def test_foo(f1, m1, f2, s1): ... 

该函数所请求的fixtures的实例化顺序如下:

  • s1: 具有最大的scope(session)* m1: 第二高的scope(module)* tmpdir: f1需要使用该fixture,需要在f1之前实例化* f1:在function级的scope的fixtures中,在test_foo中处于第一个* f2:在function级的scope的fixtures中,在test_foo中处于最后一个fixture的调用结束/执行清理代码

pytest支持在fixture退出作用域的时候执行相关的清理/结束代码。使用yield而不是return关键字的时候,yield后面的语句将会在fixture退出作用域的时候被调用来清理测试用例

# conftest.py 
import smtplib 
import pytest 
@pytest.fixture(scope="module") 
def smtp_connection(): smtp_connection = smtplib.SMTP("smtp.qq.com", 587, timeout=5) yield smtp_connection print("teardown smtp") smtp_connection.close() 

无论测试是否发生了异常,print及smtp.close()语句将在module的最后一个测试函数完成之后被执行

$ pytest ‐s ‐q ‐‐tb=no 
FFteardown smtp 
2 failed in 0.12 seconds 

可以看到在两个测试函数完成后smtp_connection实例调用了相关的代码。注意如果我们定义scope为function级别(scope=‘function’),该部分代码会在每个测试函数结束后都会调用。测试函数本身并不需要关心fixture的实现的细节。

我们也可以在with语句中使用yield:

@pytest.fixture(scope="module") 
def smtp_connection(): with smtplib.SMTP("smtp.qq.com", 587, timeout=5) as smtp_connection: yield smtp_connection 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值