Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the restriction on usability for tests only #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

janhn
Copy link

@janhn janhn commented Feb 1, 2023

In some cases it may be expensive to run fixtures for every test while running them once per module may be good enough.

In order to do that, we had to remove the restrictions that force function scope and test_ function name prefix.

@horejsek
Copy link
Owner

You can define the scope on the fixture. This is just helper which is not doing any work. I believe you are using this tool wrong. Can you share your example what are you trying to achieve?

@janhn
Copy link
Author

janhn commented Feb 15, 2023

Hi Michal,
thanks for taking a look. Yes, maybe we're not using it exactly as was intended.

If I should just take the example from the module documentation:

  • let's say that Client does something that takes a while in it's __init__()
  • you don't want to use ClientTest.client_data and @use_data(client_data={'foo': 'baz'}) for each test, because all of the tests in the module will use the same data (client_data = {'name': 'Sheldon', 'age': 30} in this case)
  • there's a lot of tests, so you care about not running the costly operation for each of them
  • you'd create a module-scoped version of the fixture
@pytest.fixture(scope="module")
def client_module(request):
    ...
  • and you mark the tests to use the fixture with pytestmark = pytest.mark.usefixtures(("client_module",)) because for some reason you don't actually need the client object in the test body

The last bullet is probably where it stops making sense in this simple example. The real usecase is more like that the fixture is preparing data in some data store (e.g. database) and the test is querying an application (via an api), which then accesses that data.

@janhn
Copy link
Author

janhn commented Feb 15, 2023

Looking at it again, I probably do not need to remove the assert in use_data.

@horejsek
Copy link
Owner

This library is about providing data for fixtures, but you should still use fixtures as you need. So if you want to have fixture in module scope to run it only once, you would do something like this:

@pytest.fixture(scope='module')
def client(request):
    client_data = get_data(request, 'client_data', {'name': 'Jerry', 'address': 'somewhere'})
    return Client(client_data)

But then it doesn't make much sense to use it with pytest-data, as if you init Client per module once, you cannot change the data per test. What you could do is to split the init and seeding if its possible. Something like this:

@pytest.fixture(scope="module")
def client(request):
    return Client()  # <-- here is the heavy operation done once per module

@pytest.fixture
def client_with_data(request, client):
    client_data = get_data(request, 'client_data', {'name': 'Jerry', 'address': 'somewhere'})
    client.set(client_data)  # <-- here the client is updated for each test
    return client

@janhn
Copy link
Author

janhn commented Feb 16, 2023

I think that your first snippet is where things blow up, because get_data doesn't work for module scope (tries accessing request.cls and request.function), hence my suggested changes in the function.

We do use @use_data with a lot of tests and we'll keep that, but having the freedom to choose whether the data will be initiated once for the whole module, or for each individual test, seems very useful because of performance reasons.

Using the already present approach with get_data is more convenient and makes more sense than writing something new aside to do practically the same thing, especially if that would be just to work around the limitation.

@janhn
Copy link
Author

janhn commented Feb 16, 2023

Anyway, this is just a suggestion resulting from practical use and feel free to decline it if you don't believe it makes sense for the library.
😎

@horejsek
Copy link
Owner

You are right, the first example cannot probably work, and it is a bit weird too. That's why I think the second option makes more sense. The problem is, if you have a module-scoped fixture and you use_data on multiple test functions, it will not change for every test, and it will be a surprise for you to find there is actually something else than what you expect. Or am I missing anything? Maybe I don't follow how you use exactly use_data and what makes the performance issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants