在 PyTest 中的测试模块结束时断开夹具的连接
Disconnect fixture's connection at the end of test module in 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')
因为只有在这个模块的测试全部完成后 conn.flushall()
才会 运行
我也不知道如何使用 pytest_unconfigure()
,因为我看不到从那里访问 conn
对象的方法。
如何确保在模块中的所有测试完成后执行 conn.connection.disconnect()
,同时在每次测试后保持 conn.flushall()
?
-- 编辑
我省略了一个附加约束,即 redis_conn
fixture 用于函数级模拟:
@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
我有一个测试模块运行 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')
因为只有在这个模块的测试全部完成后conn.flushall()
才会 运行我也不知道如何使用
pytest_unconfigure()
,因为我看不到从那里访问conn
对象的方法。
如何确保在模块中的所有测试完成后执行 conn.connection.disconnect()
,同时在每次测试后保持 conn.flushall()
?
-- 编辑
我省略了一个附加约束,即 redis_conn
fixture 用于函数级模拟:
@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