Skip to main content
 首页 » 编程设计

python之覆盖pytest中的子 fixture

2025年05月04日21powertoolsteam

我将 pytest 与一些复杂的依赖注入(inject)装置一起使用。我有使用长链中其他固定装置的固定装置。我希望能够更改链中间的一些固定装置以进行特定测试。

给定这些(简化的)固定装置:

@pytest.fixture 
def cache(): 
    return Cache() 
 
# Use cache fixture in a new fixture. 
@pytest.fixture 
def resource(cache): 
    return Resource(cache=cache, working=True) 
 
# Use resource fixture in a new fixture. 
@pytest.fixture 
def service(resource): 
    return Service(resource=resource) 

还有一些测试:

def test_service_when_resource_working(service): 
    assert service.status == "good" 
 
def test_service_when_resource_broken(service): 
    assert service.status == "bad" 

我怎样才能重写 resource fixture,让它变成这样:

@pytest.fixture 
def broken_resource(cache): 
    return Resource(cache=cache, working=False) 

...但仅针对 test_service_when_resource_broken 测试用例?我可以创建一个使用 broken_resource 的 broken_service,但实际情况是依赖链很长,我想重新使用所有 fixture,但有选择地更改一些他们在中间进行选定的测试。

我想做这样的事情(伪代码):

@pytest.override_fixture('resource', 'broken_resource') 
def test_service_when_resource_broken(service): 
    # service should have been instantiated with broken_resource instead of resource. 
    assert service.status == "bad" 

请您参考如下方法:

您可以使用 markers在你的测试中达到你的期望。 基本上,您标记需要不同行为的测试。在 fixture 方法中,从请求的测试上下文和过程中查找该标记。

这里是你如何做到的。

@pytest.fixture 
def cache(): 
    return Cache() 
 
# Use cache fixture in a new fixture. 
 
 
@pytest.fixture 
def resource(request, cache): 
    working = True 
    marker = request.node.get_marker("broken") 
    if marker: 
        working = False 
 
    return Resource(cache=cache, working=working) 
 
 
# Use resource fixture in a new fixture. 
@pytest.fixture 
def service(resource): 
    return Service(resource=resource) 
 
 
def test_service_when_resource_working(service): 
    assert service.status == "good" 
 
 
@pytest.mark.broken 
def test_service_when_resource_broken(service): 
    assert service.status == "bad"