Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use pytest fixtures with Unittest methods

Tags:

python

pytest

class MyTestCase(unittest.Testcase):
    def setUp(self):
        self.something = True

    @pytest.fixture(autouse=True)
    def MyTestMethod(self, frozentime):
        fn(self.something)  # self.something is NOT defined

If I use @pytest.fixture(autouse=True) I end up with some strange behavior from PyTest. Instead of calling my setUp method before the test method, PyTest skips the setUp and calls MyTestMethod as if it was a PyTest MyTestFunction which of course does not work very well.

How do I get MyTestMethod to use the frozentime fixture without ignoring the setUp method that should be called first.

class MyTestCase(unittest.Testcase):
    def setUp(self):
        self.something = True

    #@pytest.fixture(autouse=True)
    def MyTestMethod(self, frozentime): # Fails on call, because it needs too many arguments.
        fn(self.something)  
like image 887
boatcoder Avatar asked Jun 05 '18 22:06

boatcoder


People also ask

Can you use pytest fixtures with Unittest?

pytest supports running Python unittest -based tests out of the box. It's meant for leveraging existing unittest -based test suites to use pytest as a test runner and also allow to incrementally adapt the test suite to take full advantage of pytest's features.

How do you use pytest fixtures?

To access the fixture function, the tests have to mention the fixture name as input parameter. Pytest while the test is getting executed, will see the fixture name as input parameter. It then executes the fixture function and the returned value is stored to the input parameter, which can be used by the test.

Which is better pytest or Unittest?

Which is better – pytest or unittest? Although both the frameworks are great for performing testing in python, pytest is easier to work with. The code in pytest is simple, compact, and efficient. For unittest, we will have to import modules, create a class and define the testing functions within that class.


1 Answers

That's because the autouse fixtures are executed before the setUp/tearDown methods:

Note

Due to architectural differences between the two frameworks, setup and teardown for unittest-based tests is performed during the call phase of testing instead of in pytest‘s standard setup and teardown stages. This can be important to understand in some situations, particularly when reasoning about errors. For example, if a unittest-based suite exhibits errors during setup, pytest will report no errors during its setup phase and will instead raise the error during call.

Source

There's nothing you can do to work around this behaviour. You can either move the fixture-relevant code out of setUp/tearDown methods, for example: if self.flag is used in class-scoped fixtures, you can replace

class Tests(unittest.TestCase):

    def setUp(self):
        self.flag = True

    def tearDown(self):
        self.flag = False

    @pytest.fixture(autouse=True)
    def myfixture(self):
        print(self.flag)

with

class Tests(unittest.TestCase):

    @pytest.fixture(autouse=True)
    def prepare_flag(self):
        self.flag = True
        yield
        self.flag = False

    @pytest.fixture(autouse=True)
    def myfixture(self, prepare_flag):
        print(self.flag)

Or you can move all the setUp relevant code from fixtures:

class Tests(unittest.TestCase):

    def setUp(self):
        self.flag = True

    @pytest.fixture(autouse=True)
    def myfixture(self, somearg):
        fn(self.flag, somearg)

becomes

class Tests(unittest.TestCase):

    def setUp(self):
        self.flag = True
        fn(self.flag, self._somearg)

    @pytest.fixture(autouse=True)
    def assign_stuff(self, somearg):
        self._somearg = somearg
like image 188
hoefling Avatar answered Sep 20 '22 15:09

hoefling