Sometimes, in order to meet the needs of certain scenarios, we know that some test functions will definitely not execute at this point, or will fail if executed. So we can choose to skip this test function, so as not to affect the overall performance of the test function, you will not run many green test cases, add red failed or error to you.

For example, some test functions that run only on Windows will not work on a Linux platform, so you need to skip this test function. For example, if some test cases have dependencies on external resources, such as databases, the test function may need to be skipped if the database resources are not available.

A mechanism is provided in PyTest to skip test functions.

A, skip

It’s as simple as putting @pytest.mark.skip() on the test function you want to skip. You can pass reason as the reason for skipping, or leave it blank.

@pytest.mark.skip(reason=" no reason ") def test_the_unknown(): @pytest.mark.skip(reason=" no reason ") def test_the_unknown():...Copy the code

Running results:

Test_skipif. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1 skipped in 0.02 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = s skipped: There is no reason why you would not want to execute Process Finished with exit code 0Copy the code

As you can see, the test case was successfully skipped and there is the output of Reason. By default, pyTest does not display details of skipped test functions to avoid confusing the output with normal ones.

Second, pytest. Skip (reason)

1. Use in test functions or fixture functions

In addition to the above usage, you can also use pytest.skip(reason) to skip in test functions or setup functions. For example, if some of the parameters don’t match your expectations, skip subsequent execution.

Example code above:

import pytest @pytest.fixture() def demo_fixture(request): test_input = request.param if test_input == 3: Pytest. skip(" pass = 3 and skip it ") @pytest.mark.parametrize("demo_fixture", [1, 3], indirect=True) def test_the_unknown3(demo_fixture): ... if __name__ == "__main__": pytest.main(["-s", '-r' "test_skipif.py"])Copy the code

In the above code, I parameterized the test function test_the_unknown3 and got the parameter in the fixture function demo_fixture. Logically, 1 and 3 are parameterized, so the test function is executed twice.

I’ve added judgment to my fixture function to skip execution when I get an argument equal to 3. So the final run result should be 1 execute, 3 skip.

Test_skipif. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = 1 passed, 1 skipped in 0.09 s = = = = = = = = = = = = = = = = = = = = = = = = =. S skipped: If the value passed inis 3, Process finished with exit code 0 is skippedCopy the code

The results were in line with expectations.

This usage solves a real problem for me. That is, the test data used by many people in other groups to write cases will be passed through other cases or other interfaces after calling, so when there are problems with these dependencies, there will be problems in case operation, resulting in false positives. If you use pytest.skip(reason), you can alleviate the problem of case false positives.

2. Allow_module_level =True Skip the entire module

Allow_module_level =True if you want to skip the entire module if certain conditions are met.

import pytest a = 1 if a ! = 3: pytest.skip(" if a is not equal to 3, skip the whole file module ", allow_module_level=True) @pytest.fixture() def demo_fixture(request): test_input = request.param if test_input == 3: Pytest.skip (" pass = 3 and skip it ") @pytest.mark.parametrize("demo_fixture", [1, 3], indirect=True) def test_the_unknown1(demo_fixture): ... def test_the_unknown2(): ... def test_the_unknown3(): ...Copy the code

Run it:

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1 skipped in 0.02 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = skipped: If a does not equal 3, skip the entire file module Process finished with exit code 0Copy the code

Third, skipif

1. Skipif skips conditionally

As mentioned above, when a certain condition is met, the function pytest.skip can be skipped. In fact, skipIf can also be used directly to achieve the purpose of conditionally skipping some content.

Import sys.version_info < (4, 0), reason=" def test_function(): import sys.pytest.mark. skipif(sys.version_info < (4, 0), reason=") def test_function(): print(sys.version_info)Copy the code

Running results:

Test_module1. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1 skipped in 0.02 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = s skipped: Execution of Process Finished with exit code 0 is skipped after version 4.0Copy the code

2. The SKIP flag is shared between modules

For example, I now have two test modules, test_module1.py and test_module2.py. In test_module1.py, I define a skipif to share as a marker, not_equal_5. Import this marker in test_module2.py and use it directly.

# content of test_module1.py import pytest import sys version_judge = pytest.mark.skipif( sys.version_info < (4, 0), Reason =" version 4.0 is not executed ") @version_judge def test_the_unknown2():... if __name__ == "__main__": pytest.main(["-s", '-r' "test_module1.py"])Copy the code

Insert marker in test_module2.py, and the expected result should be test_the_unknown1 skipped execution.

# content of test_module2.py
import pytest
from interface.demo.test_module1 import version_judge


@version_judge
def test_the_unknown1():
    ...


def test_the_unknown2():
    ...


if __name__ == "__main__":
    pytest.main(["-s", '-r' "test_module2.py"])
Copy the code

Run test_module2. Py:

Test_module2. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = 1 passed, 1 skipped in 0.08 s = = = = = = = = = = = = = = = = = = = = = = = = = s skipped: After version 4.0,.process finished with exit code 0 is skippedCopy the code

Skip all test functions under a class or module

1. Skip all test functions under the class

If you place skipif on a class, all test functions under that class will be skipped.

import pytest import sys version_judge = pytest.mark.skipif( sys.version_info < (4, 0), Reason =" version_judge class TestDemo(): def test_the_unknown2(self):... def test_the_unknown3(self): ... def test_the_unknown1(): ... if __name__ == "__main__": pytest.main(["-s", '-r' "test_module1.py"])Copy the code

As a result, both test methods under the TestDemo class will be skipped.

Test_module1. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = 1 passed, 2 skipped in 0.09 s = = = = = = = = = = = = = = = = = = = = = = = = = s skipped: 2. To be Skipped over or Skipped over. 2. To be Skipped over or Skipped overCopy the code

2. Skip all test functions under the module

If you want to skip all test functions for a module, you can use the global variable PyTestmark:

import pytest import sys pytestmark = pytest.mark.skipif(sys.version_info < (4, 0), Class TestDemo(): def test_the_unknown2(self):... def test_the_unknown3(self): ... def test_the_unknown1(): ... if __name__ == "__main__": pytest.main(["-s", '-r' "test_module1.py"])Copy the code

Run, all three tests under the module will be skipped

Test_module1. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 3 skipped in 0.02 s = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = s skipped: To be Skipped over to be deflected or Skipped over: to be Skipped over or to be Skipped over: to be Skipped over or to be Skipped over by Process finished with exit code 0Copy the code

Also, if multiple SkipIF decorators are applied to the same test function, the function will be skipped as long as any of the conditions are true.

Skip files or directories

Sometimes you may need to skip an entire file or directory. For example, there is code in a file that you don’t want to execute. In this case, files and directories must be excluded from the collection collected by PyTest. For more information, see Customizing test Collections, which will be shared separately as appropriate.

Import dependency failure Skip

The pytest. importorSkip function can be used to skip dependencies that fail to be imported. You can also use it at the module level, in fixture functions, or in test functions.

import pytest

# docutils = pytest.importorskip("docutils")

class TestDemo():

    def test_the_unknown2(self):
        ...

    def test_the_unknown3(self):
        pytest.importorskip("docutils")

def test_the_unknown1():
    ...

if __name__ == "__main__":
    pytest.main(["-s", '-r' "test_module1.py"])
Copy the code

Skip one and execute two:

Test_module1. Py [100%] = = = = = = = = = = = = = = = = = = = = = = = = 2 passed, 1 skipped in 0.09 s = = = = = = = = = = = = = = = = = = = = = = = = =. S skipped: could not import 'docutils': No module named 'docutils' . Process finished with exit code 0Copy the code

The docutils in the code is a third-party library, which you can skip depending on the library version number:

Docutils = pytest. Importorskip (" docutils minversion = "0.3")Copy the code

The version is read from the __version__ attribute of the specified module, or skipped if the condition is not met.

Seven,

  1. Skip all tests in the module unconditionally
pytestmark = pytest.mark.skip("all tests still WIP")
Copy the code
  1. Skip all tests in the module based on certain conditions
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
Copy the code
  1. If some imports are missing, all tests in the module are skipped
pexpect = pytest.importorskip("pexpect")
Copy the code