Skip to content

Function-scoped fixture run before session-scoped with unittest.TestCase #4143

Closed
@Lekensteyn

Description

@Lekensteyn

Currently 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: unittestrelated to the unittest integration builtin plugintopic: fixturesanything involving fixtures directly or indirectlytype: bugproblem that needs to be addressed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions