passing a py.test fixture between test files in a module
Asked Answered
S

1

19

I have a common py.test fixture that I want to use generically in different test files within the same module. After reading the py.test documentation, the suggestion was to add the fixture to a conftest.py file which should make the fixture available to all files in the module. But for some reason, I can't seem to get this common fixture to work with my test class.

#In conftest.py

import pytest

@pytest.fixture
def mock_data(scope="module"):
    return ({'number_of_females_1': 14,
             'number_of_females_2': 3,
             'number_of_females_3': 19,
             'number_of_males_1': 37)} 

Then in my test class file I have

Import pytest
from unittest import TestCase    

@pytest.mark.usefixtures('mgmt_data')
class Test_param_sweeps(TestCase):

    def test_Base_model(self, mgmt_data):
        from pyugend.pyugend.Models import Base_model
        t = Base_model(**mgmt_data)
        assert isinstance(t, Base_model)

The documentation said that I did not have to import the mgmt_data fixture or anything.

The error I get when running this test case is:

self = <pyugend.tests.test_param_sweeps.Test_param_sweeps testMethod=test_Base_model>
result = <TestCaseFunction 'test_Base_model'>

    def run(self, result=None):
        orig_result = result
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            if startTestRun is not None:
                startTestRun()

        result.startTest(self)

        testMethod = getattr(self, self._testMethodName)
        if (getattr(self.__class__, "__unittest_skip__", False) or
            getattr(testMethod, "__unittest_skip__", False)):
            # If the class or method was skipped.
            try:
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                self._addSkip(result, self, skip_why)
            finally:
                result.stopTest(self)
            return
        expecting_failure_method = getattr(testMethod,
                                           "__unittest_expecting_failure__", False)
        expecting_failure_class = getattr(self,
                                          "__unittest_expecting_failure__", False)
        expecting_failure = expecting_failure_class or expecting_failure_method
        outcome = _Outcome(result)
        try:
            self._outcome = outcome

            with outcome.testPartExecutor(self):
                self.setUp()
            if outcome.success:
                outcome.expecting_failure = expecting_failure
                with outcome.testPartExecutor(self, isTest=True):
>                   testMethod()
E                   TypeError: test_Base_model() missing 1 required positional argument: 'mgmt_data'

/home/krishnab/anaconda3/envs/py35_gu/lib/python3.5/unittest/case.py:600: TypeError

I am not sure that the error is? It says that I am missing a positional argument, but mgmt_data() does not take any arguments and the Base_model() class takes only one argument which is the **mgmt_data.

Shoran answered 28/3, 2017 at 5:15 Comment(2)
You forgot to include mgmt_data in your arguments.Muscle
Oh, I tried it that way as well. But the error is just different. I updated the OP with the new error message. This new message is even more confusing.Shoran
S
30

I figured out the answer. The issue was that I was using a Unittest type class instead of a py.test type class. Technically both can work with py.test but only py.test type classes can access fixtures.

So I just changed:

from unittest import TestCase    

@pytest.mark.usefixtures('mgmt_data')
class Test_param_sweeps(TestCase):

in the OP, to the following:

import pytest

@pytest.mark.usefixtures('mgmt_data')
class Test_param_sweeps:

    def test_Base_model(self, mgmt_data):
        from pyugend.pyugend.Models import Base_model
        t = Base_model(**mgmt_data)
        assert isinstance(t, Base_model)

Problem solved.

Shoran answered 28/3, 2017 at 6:13 Comment(7)
So removing the class inheritance completely worked? Won't pytest just fail to recognize this class as a test case now? You still need to inherit from some kind of TestCase class in order to have pytest recognize that it needs to run those, I believeElnoraelnore
@Elnoraelnore Yeah, I think that the pytest package has its own TestCase class. Importing pytest will search for all the functions or classes that begin with test and then pytest proceeds from there.Shoran
You're a life-saver! Spent more than 2h trying to figure out what went wrong..Akmolinsk
@Akmolinsk glad that it helped. I have been there before, so I understand the frustrations :).Shoran
@Shoran is it still working for you ? I'm having trouble to setup your solution I get a missing argument error in my test using the fixture :/Geomorphology
In case it helps someone, I was getting this with Pycharm incorrectly identifying the test as a unittest one instead of a pytest one (which you can see from the message it prints at the start). I deleted my test configurations and reran, and it worked.Villegas
I had a similar issue, and fixed it the same way (above). One difference is that I did not need to use @pytest.mark.usefixtures('mgmt_data') at all. The test finds the fixture during runtime anyway.Irrespective

© 2022 - 2024 — McMap. All rights reserved.