Pytest fixture always returns a function

I want to be able to return the value from the device to several tests / test classes, but the value that is passed is a function.

Here is my code:

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' 

Output:

 =================================== 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 =========================== 

But if I rewrote my test so that it does not use the usefixtures decorator, it works as expected:

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

Any ideas why it doesn't work when I try to use the decorator method?

+6
source share
2 answers

When you use the @pytest.mark.usefixtures marker, you still need to provide a similar input argument if you want this device to be introduced into your test function.

As described in py.test docs for fixtures :

The name of the binding function can be specified later to call it before starting the tests ... Test functions can directly use the device names as input arguments, in which case the fixture instance returned from the device function will be entered.

Therefore, just using the @pytest.mark.usefixtures decorator will only call the function. Providing an input argument will give you the result of this function.

You really need to use @pytest.mark.usefixtures when you want to use the tool but don't want it to be an input argument to your test. As described in py.test docs .

The reason you get an exception talking about user_setup as a function is because inside your function test_user name user_setup actually refers to the function defined earlier in the file. To make your code work as you expect, you will need to add an argument to the test_user function:

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

Now, from the point of view of the test_user function, the name user_setup will refer to the function argument, which will be the returned device value entered by py.test.

But actually you just don't need to use the @pytest.mark.usefixtures decorator at all.

+13
source

In both cases, the global scope user_setup refers to a function. The difference is that in your version of nonfixture you create a parameter with the same name, which is the classic recipe for confusion.

In this nonfixture version, within test_user , your user_setup identifier refers to the fact that you are passing it, and not to the global scope function.

I think you probably want to call user_setup and sign the result, for example

 assert user_setup()['name'] == 'chad' 
-1
source

Source: https://habr.com/ru/post/974521/


All Articles