Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping tests in pytest: Classes vs plain functions

Tags:

python

pytest

I'm using pytest to test my app. pytest supports 2 approaches (that I'm aware of) of how to write tests:

  1. In classes:

test_feature.py -> class TestFeature -> def test_feature_sanity

  1. In functions:

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?

like image 849
NI6 Avatar asked Apr 25 '18 07:04

NI6


People also ask

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_*”.

What are benefits of writing test functions that can be run with pytest?

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 .

How do I run multiple tests in pytest?

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.

Can pytest be used for functional testing?

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.


2 Answers

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.

like image 173
George Avatar answered Oct 02 '22 11:10

George


This answer presents two compelling use-cases for a TestClass in pytest:

  • Joint parametrization of multiple test methods belonging to a given class.
  • Reuse of test data and test logic via subclass inheritance

Joint parametrization of multiple test methods belonging to a given class.

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 =================================================================== 

Reuse of test data and test logic via subclass inheritance

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.

like image 38
Jasha Avatar answered Oct 02 '22 11:10

Jasha