pytest fixture总是返回一个函数

时间:2014-08-28 22:55:52

标签: python testing fixtures pytest

我希望能够将一个值从fixture返回到多个测试/测试类,但传递的值是一个函数。

这是我的代码:

import pytest

@pytest.fixture()
def user_setup():
    user = {
        'name': 'chad',
        'id': 1
    }
    return user

@pytest.mark.usefixtures('user_setup')
class TestThings:
    def test_user(self):
        assert user_setup['name'] == 'chad'

输出结果为:

=================================== FAILURES ===================================
_____________________________ TestThings.test_user _____________________________

self = <tests.test_again.TestThings instance at 0x10aed6998>

    def test_user(self):
>       assert user_setup['name'] == 'chad'
E       TypeError: 'function' object has no attribute '__getitem__'

tests/test_again.py:14: TypeError
=========================== 1 failed in 0.02 seconds ===========================

但是如果我重写我的测试以便它不使用usefixtures装饰器,它会按预期工作:

def test_user(user_setup):
    assert user_setup['name'] == 'chad'

当我尝试使用装饰器方法时,为什么它不起作用的任何想法?

2 个答案:

答案 0 :(得分:14)

当您使用@pytest.mark.usefixtures标记时,如果您希望将该fixture添加到测试函数中,则仍需要提供类似命名的输入参数。

py.test docs for fixtures

中所述
  

以后可以引用fixture函数的名称来引起它   在运行测试之前调用...测试函数可以直接使用   夹具名称作为输入参数,在这种情况下夹具实例   从夹具函数返回将被注入。

所以只使用@pytest.mark.usefixtures装饰器只会调用该函数。提供输入参数将为您提供该函数的结果。

当你想要调用一个fixture但你不想将它作为测试的输入参数时,你真的需要使用@pytest.mark.usefixtures。如py.test docs中所述。

你得到一个关于user_setup作为函数的异常的原因是因为在你的test_user函数中,名称user_setup实际上是指你之前在文件中定义的函数。要使代码按预期工作,您需要在test_user函数中添加一个参数:

@pytest.mark.usefixtures('user_setup')
class TestThings:
    def test_user(self, user_setup):
        assert user_setup['name'] == 'chad'

现在从test_user函数的角度来看,名称user_setup将引用函数参数,该参数将是py.test注入的fixture的返回值。

但实际上你根本不需要使用@pytest.mark.usefixtures装饰器。

答案 1 :(得分:-1)

在这两种情况下,在全局范围user_setup中引用该函数。不同之处在于,在你的nonfixture版本中,你正在创建一个具有相同名称的参数,这是一个混淆的经典方法。

在该非修复版本中,在test_user范围内,您的user_setup标识符指的是您传递它的任何内容,而不是全局范围内的函数。

我认为您可能打算调用user_setup并将结果下标为

assert user_setup()['name'] == 'chad'