Function-scoped fixture run before session-scoped with unittest.TestCase
See original GitHub issueCurrently unittest.TestCase instances cannot use fixtures in their test specifications, reportedly due to “different design philosophies”.
Would it be possible to create a class decorator to enable this? See this example (runs both with python -m unittest
and pytest
):
import unittest
import pytest
def fixture_wrapper(fn, params):
# XXX discover fixture instead of hardcoding it here
# pytest seems to add extra @py_assert1@ and @py_format1@ stuff here.
#assert params == ('program',)
assert params[0] == 'program'
return lambda self, *args: fn(self, program())
def uses_fixtures(cls):
'''Wraps all unittest.TestCase methods in order to inject fixtures.'''
assert issubclass(cls, unittest.TestCase)
for name in dir(cls):
func = getattr(cls, name)
if not name.startswith('test') or not callable(func):
continue
if func.__code__.co_argcount <= 1:
# ignore methods which do not have fixture dependencies
continue
params = func.__code__.co_varnames[1:]
print(name, params)
setattr(cls, name, fixture_wrapper(func, params))
@pytest.fixture
def program():
return 'dummy'
class TestDemo(object):
def test_1(self, program):
assert program == 'dummy'
@uses_fixtures
class DemoTestCase(unittest.TestCase):
def test_2(self, program):
assert program == 'dummy'
The motivation is to provide a transition path for an existing unittest suite to pytest. Currently I use pytest as test runner for an existing project that otherwise does not depend on pytest. To fix some issues (inability to run part of the tests when some program dependencies are missing) I would like to use fixtures, but without adding a hard dependency on pytest for now. With such a decorator, migration to pytest will require less extensive changes (dropping a decorator vs changing every test function to use the parameter instead of a property that was configured via the unittest setUp method).
Edit: one motivation for using fixtures is the ability to skip tests from it. E.g. if “program” is not available, skip the test.
Issue Analytics
- State:
- Created 5 years ago
- Comments:10 (6 by maintainers)
Hi @Lekensteyn,
I wholeheartedly understand the desire of using fixtures in
unittest.TestCase
subclasses as a stop gap measure when working with existing unittest-based test suites, I’ve done this myself countless times.One approach that works out of the box is using
autouse
fixtures to inject other fixtures in the class:From that, it follows you can then use the same technique to obtain access to
request
and inject the fixtures into the methods:This is an interesting idea, and it can be made automatic using a
conftest.py
file or plugin:So the user doesn’t even need the
uses_fixture
decorator:I’m not sure how far we want to take it by adding this to the core, as the possibility of maintenance problems is very real, but this could be made into an external plugin very easily (we can even mention it in the official pytest docs).
Fixed by https://github.com/pytest-dev/pytest/pull/4091