I'm currently following this py.test example and it works out when I do not use classes, however when I introduce test cases into classes I am failing.
The smallest case I managed to write is the following:
import unittest import pytest class FixtureTestCase(unittest.TestCase): @pytest.mark.parametrize("test_input,expected", [ ("3+5", 8), ("2+4", 6), ("6*9", 42), ]) def test_1(self, a, b): self.assertEqual(a, b)
unfortunately when I execute
py.test test_suite.py
I get the error message:
TypeError: test_1() takes exactly 3 arguments (1 given)
How can I do in order to generate a battery of test_1 tests?
mark. parametrize : parametrizing test functions. Parameter values are passed as-is to tests (no copy whatsoever). For example, if you pass a list or a dict as a parameter value, and the test case code mutates it, the mutations will be reflected in subsequent test case calls.
Being able to reuse fixtures in parametrized tests is a must when we want to avoid repetition. Unfortunately, pytest doesn't support that yet. On the other hand, we can make it happen either by using getfixturevalue in pytest or through a third-party library.
Repeating a test Each test collected by pytest will be run count times. If you want to override default tests executions order, you can use --repeat-scope command line option with one of the next values: session , module , class or function (default). It behaves like a scope of the pytest fixture.
If you subclass from unittest.TestCase
, your test methods cannot have additional arguments. If you simply subclass from object
, it will work (though you'll have to use regular assert
statements instead of the TestCase.assertEqual
methods.
import unittest import pytest class TestCase(object): @pytest.mark.parametrize("test_input,expected", [ ("3+5", 8), ("2+4", 6), ("6*9", 42), ]) def test_1(self, a, b): assert eval(a) == b
At that point though, it kind of begs the question why you're using classes instead of just defining functions, since the test will essentially be the same, but require less overall boilerplate and code.
I don't know if this was the case 5 years ago, but these days you can use parameterized (https://pypi.org/project/parameterized/) with pytest to decorate test methods on a test class, yes including unittest.TestCase, without having to resort to nose. E.g.:
from unittest import TestCase from parameterized import parameterized class SomeTestCase(TestCase): @parameterized.expand([ (1, 2), ('a', 'b') ]) def test_something(self, param1, param2): ...
The only gotcha, but you better remember this, is that the decorator will generate new test methods for each listed input parameter, so you will not be able to run your original test method directly by specifying it on the command line. E.g. pytest some_test.py::SomeTestCase::test_something
won't work anymore (because your test method now expects two parameters). However, you can call the generated methods directly, for which you can get the name from either the pytest error output when you run the whole TestCase or by doing a pytest --collect-only
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With