Pytest call setup() before fixture - python

I am having difficulty using fixtures with my pytest unit tests.
I am using a test class like this:
class TestMyApp(object):
def setup(self):
self.client = mock_client()
#pytest.fixture
def client_item(self):
return self.client.create_item('test_item')
def test_something1(self, client_item):
# Test here.
pass
When I run the above test I get the following exception:
AttributeError: 'TestMyApp' object has no attribute 'client'
I believe this is because the client_item() fixture function is being called before the setup() function.
Am I using fixtures incorrectly? Or is there some way I can force setup() to be called before the fixture functions?
Thanks in advance.

Fixtures can use other fixtures, so you can use fixtures all the way down:
class TestMyApp(object):
#pytest.fixture
def client(self):
return mock_client()
#pytest.fixture
def client_item(self, client):
return client.create_item('test_item')
def test_something1(self, client_item):
# Test here.
pass
The documentation subtly recommends fixtures over xUnit style setup/teardown methods:
While these setup/teardown methods are simple and familiar to those coming from a unittest or nose background, you may also consider using pytest’s more powerful fixture mechanism which leverages the concept of dependency injection, allowing for a more modular and more scalable approach for managing test state, especially for larger projects and for functional testing.
It goes on to say that the two styles can be mixed, but isn't clear about the order in which things will happen.

Related

Run setup_class() class after class scope fixture defined in conftest

So, I have fixtures defined in conftest.py file with scope="class" as I want to run them before each test class is invoked. The conftest file is placed inside project root directory for it to be visible to every test module.
Now in one of the test modules, I have another setup function which I want to run once for that module only. But the problem is setup_class() method is called before running fixtures defined in conftest.py. Is this expected? I wanted it to be opposite because I want to use something done in the fixtures defined in conftest. How to do that?
Code -
conftest.py:
#pytest.fixture(scope="class")
def fixture1(request):
#set a
#pytest.fixture(scope="class")
def fixture1(request):
test_1.py:
#pytest.mark.usefixtures("fixture_1", "fixture_2")
class Test1():
#need this to run AFTER the fixture_1 & fixture_2
def setup_class():
#setup
#get a set in fixture_1
def test_1()
.....
I know that I could simply define a fixture in the test file instead of setup_class but then I will have to specify it in arguments of every test method in order it to be invoked by pytest. But suggestions are welcome!
I have exactly the same problem. Only now I have realized that the problem might be taht the setup_class is called before the fixture >-/
I think that this question is similar to this one
Pytest - How to pass an argument to setup_class?
And the problem is mixing the unittest and pytest methods.
I kind of did what they suggested - I ommitted the setup_class and created a new fixture within the particular test file,
calling the fixture in the conftest.py.
It works so far.
M.
The problem is that you can use the result of a fixture only in test function (or method) which is run by pytest. Here I can suggest a workaround. But of course I'm not sure if it suites your needs.
The workaround is to call the function from a test method:
conftest.py
#pytest.fixture(scope='class')
def fixture1():
yield 'MYTEXT'
test_1.py
class Test1:
def setup_class(self, some_var):
print(some_var)
def test_one(self, fixture1):
self.setup_class(fixture1)
Fixtures and setup_class are two different paradigms to initialize test functions (and classes). In this case, mixing the two creates a problem: The class-scoped fixtures run when the individual test functions (methods) run. On the other hand, setup_class runs before they do. Hence, it is not possible to access a fixture value (or fixture-modified state) from setup_class.
One of the solutions is to stop using setup_class entirely and stick with a fixtures-only solution which is the preferred way in pytest nowadays (see the note at the beginning).
# conftest.py or the test file:
#pytest.fixture(scope="class")
def fixture_1(request):
print('fixture_1')
# the test file:
class Test1():
#pytest.fixture(scope="class", autouse=True)
def setup(self, fixture_1, request):
print('Test1.setup')
def test_a(self):
print('Test1.test_a')
def test_b(self):
print('Test1.test_b')
Note that the setup fixture depends on fixture_1 and hence can access it.

Using fixtures inside test function

I am using multiple fixtures inside a use fixture decorator as below:
#pytest.mark.usefixtures(fixture1, fixture2)
def test_me:
Fixtures file:
#pytest.fixture
def fixture1:
#pytest.fixture
def fixture2:
The problem is that I need these two fixtures to be triggered at a specific line in my code snippet, but these two fixtures triggers simultaneously.
How can this be achieved?
The fixtures are not triggers simultaneously, but both are triggered before the test when you use them as arguments, which is the expected behavior. You can also see it in the error message if you try to call the fixture from the test
def test_me():
fixture1()
Fixture "fixture1" called directly. Fixtures are not meant to be
called directly, but are created automatically when test functions
request them as parameters.
If all your tests require the fixtures in test run time don't use regular functions and not fixtures. If this usecase is unique you can add another function that can be called from the fixture and from the tests
def fixture1_implementation():
...
#pytest.fixture
def fixture1():
fixture1_implementation()
def test_me():
fixture1_implementation()
# or
#pytest.mark.usefixtures('fixture1')
def test_example():
...

Pytest fixture with scope "class" running on every method

I'm trying to create a test environment with Pytest. The idea is to group test methods into classes.
For every class/group, I want to attach a config fixture that is going to be parametrized. So that I can run all the tests with "configuration A" and then all tests with "configuration B" and so on.
But also, I want a reset fixture, that can be executed before specific methods or all methods of a class.
The problem I have there is, once I apply my reset fixture (to a method or to a whole class), the config fixture seems to work in the function scope instead of the class scope. So, once I apply the reset fixture, the config fixture is called before/after every method in the class.
The following piece of code reproduces the problem:
import pytest
from pytest import *
#fixture(scope='class')
def config(request):
print("\nconfiguring with %s" % request.param)
yield
print("\ncleaning up config")
#fixture(scope='function')
def reset():
print("\nreseting")
#mark.parametrize("config", ["config-A", "config-B"], indirect=True)
##mark.usefixtures("reset")
class TestMoreStuff(object):
def test_a(self, config):
pass
def test_b(self, config):
pass
def test_c(self, config):
pass
The test shows how the config fixture should work, being executed only once for the whole class. If you uncomment the usefixtures decoration, you can notice that the config fixture will be executed in every test method. Is it possible to use the reset fixture without triggering this behaviour?
As I mentioned in a comment, that seems to be a bug in Pytest 3.2.5.
There's a workaround, which is to "force" the scope of a parametrization. So, in this case if you include the scope="class" in the parametrize decorator, you get the desired behaviour.
import pytest
from pytest import *
#fixture(scope='class')
def config(request):
print("\nconfiguring with %s" % request.param)
yield
print("\ncleaning up config")
#fixture(scope='function')
def reset():
print("\nreseting")
#mark.parametrize("config", ["config-A", "config-B"], indirect=True, scope="class")
#mark.usefixtures("reset")
class TestMoreStuff(object):
def test_a(self, config):
pass
def test_b(self, config):
pass
def test_c(self, config):
pass
It depends on which version of pytest you are using.
There are some semantical problems to implement this in older versions of pytest. So, this idea is not yet implemented in older pytest. Someone has already given suggestion to implement the same. you can refer this
"Fixture scope doesn't work when parametrized tests use parametrized fixtures".
This was the bug.
You can refer this
This issue has been resolved in latest version of pytest. Here's the commit for the same with pytest 3.2.5
Hope it would help you.

Python unittest setUp function

I am relatively new to Python. According to unittest.setUp documentation:
setUp()
Method called to prepare the test fixture. This is called immediately before calling the test method; any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.
My question about setUp is as follows:
In our testing code base, I have seen that we customized the Python testing framework by inheriting from unittest.TestCase. Originally, unittest.TestCase has names setUp and tearDown.In the customized class, we have setUpTestCase and tearDownTestCase. So each time those two functions will be called instead of those original counterparts.
My questions are:
How are those setUp and tearDown functions being called by the underlying test runner?
Is it required that those functions used to set up test cases should start with setUp and functions used to tear down test cases should start with tearDown? Or it can be named as any valid identifier?
Thank you.
setUp() and tearDown() methods are automatically used when they are available in your classes inheriting from unittest.TestCase.
They should be named setUp() and tearDown(), only those are used when test methods are executed.
Example:
class MyTestCase(unittest.TestCase):
def setUp(self):
self.setUpMyStuff()
def tearDown(self):
self.tearDownMyStuff()
class TestSpam(MyTestCase):
def setUpMyStuff(self):
# called before execution of every method named test_...
self.cnx = # ... connect to database
def tearDownMyStuff(self):
# called after execution of every method named test_...
self.cnx.close()
def test_get_data(self):
cur = self.cnx.cursor()
...

How can I create a class-scoped test fixture in pyUnit?

I am unit testing mercurial integration and have a test class which currently creates a repository with a file and a clone of that repository in its setUp method and removes them in its tearDown method.
As you can probably imagine, this gets quite performance heavy very fast, especially if I have to do this for every test individually.
So what I would like to do is create the folders and initialize them for mercurial on loading the class, so each and every unittest in the TestCase class can use these repositories. Then when all the tests are run, I'd like to remove them. The only thing my setUp and tearDown methods then have to take care of is that the two repositories are in the same state between each test.
Basically what I'm looking for is a python equivalent of JUnit's #BeforeClass and #AfterClass annotations.
I've now done it by subclassing the TestSuite class, since the standard loader wraps all the test methods in an instance of the TestCase in which they're defined and puts them together in a TestSuite. I have the TestSuite call the before() and after() methods of the first TestCase. This of course means that you can't initialize any values to your TestCase object, but you probably want to do this in your setUp anyway.
The TestSuite looks like this:
class BeforeAfterSuite(unittest.TestSuite):
def run(self, result):
if len(self._tests) < 1:
return unittest.TestSuite.run(self, result)
first_test = self._tests[0]
if "before" in dir(first_test):
first_test.before()
result = unittest.TestSuite.run(self, result)
if "after" in dir(first_test):
first_test.after()
return result
For some slightly more finegrained control I also created the custom TestLoader which makes sure the BeforeAfterSuite is only used to wrap test-method-TestCase objects in, which looks like this:
class BeforeAfterLoader(unittest.TestLoader):
def loadTestsFromTestCase(self, testCaseClass):
self.suiteClass = BeforeAfterSuite
suite = unittest.TestLoader.loadTestsFromTestCase(self, testCaseClass)
self.suiteClass = unittest.TestLoader.suiteClass
return suite
Probably missing here is a try/except block around the before and after which could fail all the testcases in the suite or something.
from the Python unittest documentation :
setUpClass() :
A class method called before tests in an individual class run. setUpClass is called with the class as the only argument and must be decorated as a classmethod():
#classmethod
def setUpClass(cls):
...
New in version 2.7.
tearDownClass() :
A class method called after tests in an individual class have run. tearDownClass is called with the class as the only argument and must be decorated as a classmethod():
#classmethod
def tearDownClass(cls):
...

Categories

Resources