Use Session Scoped Fixture as Variable
I am writing tests in pytest and am using fixtures as variables.
Originally, this is how the fixtures looked:
@pytest.fixture(scope="class")
def user(request):
u = "Matt"
request.cls.u = u
return u
And then, there was another fixture to delete the user from the database once I finished with it.
In the tests, I used both fixtures like so @pytest.mark.usefixtures("user", "teardown fixture")
The teardown fixture was class scoped
, until I decided to change it to session scoped
, since I want to delete the user only after running all the tests.
The problem was that suddenly the teardown fixture couldn't access user, since user is class scoped
.
I changed the user to session scoped, however, I am not sure how to access, or export it now.
@pytest.fixture(scope="session")
def user(request):
u = "Matt"
# request.cls.user = u -> WHAT GOES HERE INSTEAD OF THIS?
return u
User is no longer recognized in the test functions.
The test is located inside of a class. The current function is something like this:
Class TestUser(OtherClassWhichInheritsFromBaseCase):
def test_user1(self, user1):
self.open("www.google.com")
print(user1)
When I try to run the code in pycharm I get the following error:
def _callTestMethod(self, method):
> method()
E TypeError: TestUser.test_user1() missing 1 required positional argument: 'user1'
Any advice?
I think you're approaching this from the wrong direction. If you need to clean up a fixture, you don't write a second fixture; you write your fixture as a context manager.
For example, you might write:
@pytest.fixture(scope="session")
def user():
u = User(name="Matt")
yield u
# cleanup goes here
And in your test code:
def test_something(user):
assert user.name == "Matt"
Here's a complete example. We start with this dummy user.py
, which simply creates files to demonstrate which methods were called:
from dataclasses import dataclass
@dataclass
class User:
name: str
def commit(self):
open("commit_was_called", "w")
def delete(self):
open("delete_was_called", "w")
Then here's our test:
import pytest
import user
@pytest.fixture(scope="session")
def a_user():
u = user.User(name="testuser")
u.commit()
yield u
u.delete()
class TestUserStuff:
def test_user(self, a_user):
assert a_user.name == "testuser"
We run it like this:
$ pytest
=============================================================================================== test session starts ===============================================================================================
platform linux -- Python 3.10.1, pytest-6.2.4, py-1.11.0, pluggy-0.13.1
rootdir: /home/lars/tmp/python
plugins: testinfra-6.5.0
collected 1 item
test_user.py . [100%]
================================================================================================ 1 passed in 0.00s ================================================================================================
After which we can confirm that both the commit
and delete
methods were called:
$ ls
commit_was_called
delete_was_called
test_user.py
user.py