Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parametrize class tests with pytest

I have an array of objects that I need to run for each test inside my test class. I want to parametrize every test function in a TestClass. The end goal is to have something resembling:

@pytest.mark.parametrize('test_input', [1, 2, 3, 4])
class TestClass:
    def test_something1(self, test_input):
        # test code here, runs each time for the parametrize

But from my understanding, you can't pass input parameters, or at least call @pytest.mark.parametrize on a class, those markers are meant for defs not classs

What I have now:

class TestClass:
    def test_something1(self):
        for i in stuff:
            # test code here

    def test_something2(self):
        for i in stuff:
            # test code here
    ...

Is there a way to pass the parametrize a class itself or every function inside the TestClass? Maybe a @pytest.mark.parametrize inside a @pytest.fixture...(autouse=True).

I want to keep my tests organized as a class because it mirrors the file that I'm testing. Because I loop through these objects in at least a dozen different tests, it would be easier to call a loop of the class than in each def.

like image 650
Comradsky Avatar asked Aug 02 '16 19:08

Comradsky


People also ask

What is parametrize in pytest?

parametrize allows one to define multiple sets of arguments and fixtures at the test function or class. pytest_generate_tests allows one to define custom parametrization schemes or extensions.

How does pytest Mark parametrize work?

mark. parametrize() decorator lets you parameterize arguments of the testing function independent of fixtures you created. Now I can pass a list of invalid arguments and use pytest. raises(AssertionError) to assert that the invalid terms result in the expected exception.

Should pytest tests be in class?

Pytests may be written either as functions or as methods in classes – unlike unittest, which forces tests to be inside classes. Test classes must be named “Test*”, and test functions/methods must be named “test_*”.


1 Answers

You CAN apply parametrize to classes. From the docs:

@pytest.mark.parametrize allows one to define multiple sets of arguments and fixtures at the test function or class.

The same data will be sent to all test methods in the class.

@pytest.mark.parametrize('test_input', [1, 2, 3, 4])
class TestClass:
    def test_something1(self, test_input):
        pass


    def test_something2(self, test_input):
        pass

If you run the test with the following using pytest -v you will have the following output:

=========================================================================================== test session starts ============================================================================================
platform darwin -- Python 3.7.3, pytest-4.4.2, py-1.8.0, pluggy-0.11.0 -- /Users/user/.local/share/virtualenvs/stack-overlfow-pycharm-L-07rBZ9/bin/python3.7
cachedir: .pytest_cache
rootdir: /Users/user/Documents/spikes/stack-overlfow-pycharm
collected 8 items

test_class.py::TestClass::test_something1[1] PASSED                                                                                                                                                  [ 12%]
test_class.py::TestClass::test_something1[2] PASSED                                                                                                                                                  [ 25%]
test_class.py::TestClass::test_something1[3] PASSED                                                                                                                                                  [ 37%]
test_class.py::TestClass::test_something1[4] PASSED                                                                                                                                                  [ 50%]
test_class.py::TestClass::test_something2[1] PASSED                                                                                                                                                  [ 62%]
test_class.py::TestClass::test_something2[2] PASSED                                                                                                                                                  [ 75%]
test_class.py::TestClass::test_something2[3] PASSED                                                                                                                                                  [ 87%]
test_class.py::TestClass::test_something2[4] PASSED                                                                                                                                                  [100%]

========================================================================================= 8 passed in 0.03 seconds =========================================================================================

and this is exactly what you want.

like image 156
lmiguelvargasf Avatar answered Sep 22 '22 00:09

lmiguelvargasf