python - 在 PyTest 中的测试模块结束时断开夹具的连接
问题描述
我有一个使用 PyTest 运行的测试模块。
夹具建立到 Redis 客户端的连接,并在每次测试结束时刷新所有内容:
@pytest.fixture
def redis_conn():
conn = redis.Redis(decode_responses=True, **config.redis_test_credentials)
yield conn
conn.flushall()
除此之外,我需要在模块的所有测试完成后调用它:
conn.connection.disconnect()
我考虑过的一些事情以及为什么它们不起作用:
我不能在
pytest.fixture(scope='module')
这里使用 a 因为 thenconn.flushall()
只会在该模块的测试全部完成后运行我也看不到如何使用
pytest_unconfigure()
,因为我看不到conn
从那里访问对象的方法。
如何确保conn.connection.disconnect()
在模块的所有测试完成后执行,同时conn.flushall()
在每次测试后保持?
- 编辑
我省略了一个额外的约束,即redis_conn
夹具用于函数级模拟:
@pytest.fixture
def mock_redis_conn(mocker, redis_conn):
""" Mock Redis connection """
mocker.patch("mymodule.api.redis_conn", new=redis_conn)
这个模拟mymodule.api.redis_conn
应该在每次测试运行后有效地调用flushall()
,这会阻止我将这个模拟范围限定到这个module
级别。
解决方案
您可以实现依赖于其他固定装置的固定装置。
from unittest.mock import MagicMock
import pytest
class RedisConn:
"""just stub for example"""
def flush(self):
raise NotImplementedError()
connection = RedisConn()
@pytest.fixture(scope="module")
def conn():
conn = MagicMock() # here you open connection to testing Redis instance
print("open connection")
yield conn
print("close connection")
@pytest.fixture(scope="function")
def flush(conn, mocker):
mocker.patch(f"{__name__}.connection", new=conn)
print("do nothing")
yield
print(f"flush {connection}")
connection.flush()
def test_main_1(flush):
assert isinstance(connection, MagicMock)
print("test 1 body")
def test_main_2(flush):
assert isinstance(connection, MagicMock)
print("test 2 body")
def test_main_3():
assert not isinstance(connection, MagicMock)
assert isinstance(connection, RedisConn)
if __name__ == "__main__":
pytest.main([__file__, "-s"])
印刷
open connection
do nothing
test 1 body
.
flush <MagicMock id='139710977083536'>
do nothing
test 2 body
.
flush <MagicMock id='139710977083536'>
.
close connection