I'm using pytest to test my app. pytest supports 2 approaches (that I'm aware of) of how to write tests:
test_feature.py -> class TestFeature -> def test_feature_sanity
test_feature.py -> def test_feature_sanity
Is the approach of grouping tests in a class needed? Is it allowed to backport unittest builtin module? Which approach would you say is better and why?
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_*”.
With pytest , common tasks require less code and advanced tasks can be achieved through a variety of time-saving commands and plugins. It'll even run your existing tests out of the box, including those written with unittest .
Run Multiple Tests From a Specific File and Multiple Files To run all the tests from all the files in the folder and subfolders we need to just run the pytest command. This will run all the filenames starting with test_ and the filenames ending with _test in that folder and subfolders under that folder.
Pytest: Best among all Python testing frameworks, Pytest is a Python testing framework which provides a single solution for Unit, Functional and Acceptance testing. It is popular than the other available frameworks because of its attractive features.
There are no strict rules regarding organizing tests into modules vs classes. It is a matter of personal preference. Initially I tried organizing tests into classes, after some time I realized I had no use for another level of organization. Nowadays I just collect test functions into modules (files).
I could see a valid use case when some tests could be logically organized into same file, but still have additional level of organization into classes (for instance to make use of class scoped fixture). But this can also be done just splitting into multiple modules.
This answer presents two compelling use-cases for a TestClass in pytest:
The pytest parametrization decorator, @pytest.mark.parametrize
, can be used to make inputs available to multiple methods within a class. In the code below, the inputs param1
and param2
are available to each of the methods TestGroup.test_one
and TestGroup.test_two
.
"""test_class_parametrization.py""" import pytest @pytest.mark.parametrize( "param1,param2", [ ("a", "b"), ("c", "d"), ], ) class TestGroup: """A class with common parameters, `param1` and `param2`.""" @pytest.fixture def fixt(self): """This fixture will only be available within the scope of TestGroup""" return 123 def test_one(self, param1, param2, fixt): print("\ntest_one", param1, param2, fixt) def test_two(self, param1, param2): print("\ntest_two", param1, param2)
$ pytest -s test_class_parametrization.py ================================================================== test session starts ================================================================== platform linux -- Python 3.8.6, pytest-6.2.1, py-1.10.0, pluggy-0.13.1 rootdir: /home/jbss plugins: pylint-0.18.0 collected 4 items test_class_parametrization.py test_one a b 123 . test_one c d 123 . test_two a b . test_two c d . =================================================================== 4 passed in 0.01s ===================================================================
I'll use a modified version of code taken from another answer to demonstrate the usefulness of inheriting class attributes/methods from TestClass
to TestSubclass
:
# in file `test_example.py` class TestClass: VAR = 3 DATA = 4 def test_var_positive(self): assert self.VAR >= 0 class TestSubclass(TestClass): VAR = 8 def test_var_even(self): assert self.VAR % 2 == 0 def test_data(self): assert self.DATA == 4
Running pytest
on this file causes four tests to be run:
$ pytest -v test_example.py =========== test session starts =========== platform linux -- Python 3.8.2, pytest-5.4.2, py-1.8.1 collected 4 items test_example.py::TestClass::test_var_positive PASSED test_example.py::TestSubclass::test_var_positive PASSED test_example.py::TestSubclass::test_var_even PASSED test_example.py::TestSubclass::test_data PASSED
In the subclass, the inherited test_var_positive
method is run using the updated value self.VAR == 8
, and the newly defined test_data
method is run against the inherited attribute self.DATA == 4
. Such method and attribute inheritance gives a flexible way to re-use or modify shared functionality between different groups of test-cases.
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