You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using class scope with parametrized fixtures, if the first class to be collected has only one method that uses that fixture, then the scope value is not honored. Instead objects are created and cleaned up for every test method execution as if the scope value was set to 'function'
#!python
# parametrized_fixtures.py
import pytest
class Person:
population = 0
def __init__(self, name):
self.name = name
print("\nNew Object for %s : %s" % (name, self))
Person.population += 1
def __del__(self):
print 'Object for %s is deleted.' % self.name
Person.population -= 1
def getName(self):
return self.name
def sayHello(self):
return 'Hello! my name is %s.' % self.name
def count(self):
return Person.population
@pytest.fixture(params=["John", "Doe"], scope="class")
def human(request):
name = request.param
human = Person(name)
def finalizer():
print("\nFinalizer called for %s" % human)
request.addfinalizer(finalizer)
return human
class TestGreetings:
def test_hello(self, human):
assert human.sayHello()
#def test_bye(self, human):
# pass
class TestMetrics:
def test_name_length(self, human):
assert len(human.getName()) > 0
def test_population_count(self, human):
assert human.count() >= 0
When running the above code with the command py.test -s -v parametrized_fixtures.py the output is
#!python
=
platform linux2 -- Python 2.7.3 -- pytest-2.4.2 -- /usr/bin/python
plugins: xdist
collected 6 items
parametrized_fixtures.py:44: TestGreetings.test_hello[Doe]
New Object for Doe : <parametrized_fixtures.Person instance at 0x2492dd0>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2492dd0>
parametrized_fixtures.py:52: TestMetrics.test_name_length[John]
New Object for John : <parametrized_fixtures.Person instance at 0x24994d0>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x24994d0>
parametrized_fixtures.py:52: TestMetrics.test_name_length[Doe]
New Object for Doe : <parametrized_fixtures.Person instance at 0x2499908>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2499908>
parametrized_fixtures.py:55: TestMetrics.test_population_count[John]
New Object for John : <parametrized_fixtures.Person instance at 0x24998c0>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x24998c0>
parametrized_fixtures.py:55: TestMetrics.test_population_count[Doe]
New Object for Doe : <parametrized_fixtures.Person instance at 0x2499fc8>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2499fc8>
parametrized_fixtures.py:44: TestGreetings.test_hello[John]
New Object for John : <parametrized_fixtures.Person instance at 0x2499950>
PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2499950>
=======================6 passed in 0.02 seconds ======================
Object for John is deleted.
Object for Doe is deleted.
Object for John is deleted.
Object for Doe is deleted.
Object for John is deleted.
Object for Doe is deleted.
Instead** if the class 'TestGreetings' has 2 methods** that take the fixture 'human' as input argument,** then things work fine as expected**. For each object returned by the fixture function, all the test methods in a class get executed before repeating the same for the next object.
#!python
=
platform linux2 -- Python 2.7.3 -- pytest-2.4.2 -- /usr/bin/python
plugins: xdist
collected 8 items
parametrized_fixtures.py:44: TestGreetings.test_hello[John]
New Object for John : <parametrized_fixtures.Person instance at 0x2672ea8>
PASSED
parametrized_fixtures.py:47: TestGreetings.test_bye[John] PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2672ea8>
parametrized_fixtures.py:44: TestGreetings.test_hello[Doe]
New Object for Doe : <parametrized_fixtures.Person instance at 0x2672f38>
PASSED
parametrized_fixtures.py:47: TestGreetings.test_bye[Doe] PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2672f38>
parametrized_fixtures.py:52: TestMetrics.test_name_length[John]
New Object for John : <parametrized_fixtures.Person instance at 0x26724d0>
PASSED
parametrized_fixtures.py:55: TestMetrics.test_population_count[John] PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x26724d0>
parametrized_fixtures.py:52: TestMetrics.test_name_length[Doe]
New Object for Doe : <parametrized_fixtures.Person instance at 0x2672b48>
PASSED
parametrized_fixtures.py:55: TestMetrics.test_population_count[Doe] PASSED
Finalizer called for <parametrized_fixtures.Person instance at 0x2672b48>
======================== 8 passed in 0.03 seconds ========================
Object for John is deleted.
Object for Doe is deleted.
Object for John is deleted.
Object for Doe is deleted.
I observe the same issue when using the scope value with metafunc.parametrize and setting** indirect=True** to perform setup of a test during the test execution phase instead of test collection phase. I have attached the test file that shows the problem.
Also, I tried to debug using the source code and I think after the tests are collected, the function 'parametrize_sorted' is called which changes the order.
Original comment byholger krekel (BitBucket: hpk42, GitHub: hpk42):
Confirmed, it's probably the sorting that is at fault -- which is somewhat intricate code, unfortunately. I could fix your issue by modifying that but it made some other tests fail so i am afraid it needs some careful analysis first.
Originally reported by: BitBucket: rajaram_s, GitHub: rajaram_s
When using class scope with parametrized fixtures, if the first class to be collected has only one method that uses that fixture, then the scope value is not honored. Instead objects are created and cleaned up for every test method execution as if the scope value was set to 'function'
When running the above code with the command py.test -s -v parametrized_fixtures.py the output is
Instead** if the class 'TestGreetings' has 2 methods** that take the fixture 'human' as input argument,** then things work fine as expected**. For each object returned by the fixture function, all the test methods in a class get executed before repeating the same for the next object.
I observe the same issue when using the scope value with metafunc.parametrize and setting** indirect=True** to perform setup of a test during the test execution phase instead of test collection phase. I have attached the test file that shows the problem.
Also, I tried to debug using the source code and I think after the tests are collected, the function 'parametrize_sorted' is called which changes the order.
The text was updated successfully, but these errors were encountered: