pytest fixture 总是返回一个函数
我想从一个固定装置(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 个回答
在这两种情况下,全局范围内的 user_setup
都是指向一个函数。区别在于,在你没有使用fixture的版本中,你创建了一个同名的参数,这样很容易让人混淆。
在那个没有fixture的版本中,在 test_user
的范围内,你的 user_setup
指代的是你传入的内容,而不是全局范围中的函数。
我想你可能是想调用 user_setup
并对结果进行下标操作,就像这样:
assert user_setup()['name'] == 'chad'
当你使用 @pytest.mark.usefixtures
这个标记时,如果你想把某个“夹具”(fixture)注入到你的测试函数里,你仍然需要提供一个同名的输入参数。
夹具函数的名字可以在运行测试之前被引用来调用它…… 测试函数可以直接使用夹具的名字作为输入参数,这样夹具函数返回的实例就会被注入。
所以,仅仅使用 @pytest.mark.usefixtures
装饰器只会调用这个函数。如果你提供了一个输入参数,就会得到这个函数的返回结果。
你只有在想调用一个夹具,但又不想把它作为测试的输入参数时,才需要使用 @pytest.mark.usefixtures
。这在 py.test 文档中有说明。
你收到的关于 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 注入的夹具返回的值。
但其实你根本不需要使用 @pytest.mark.usefixtures
装饰器。