Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable pytest plugins for single tests

I've installed new pytest plugin (pytest-catchlog==1.2.2) and as much as I like it, it breaks my unit tests for logging module (e.g ValueError: I/O operation on closed file).

I would like to disable that plugin for test_logging.py file (or even a class or method), but I can't find any information on it.

The only option I found so far is to execute pytest twice: first time for test_logging.py onlywith catchlog disabled (py.test -p no:catchlog test_logging.py), and second time for all other test files.

Please let me know if I missed a pytest decorator, or any other way of disabling plugins in runtime.

like image 454
Jovik Avatar asked Jun 20 '16 13:06

Jovik


People also ask

What are Pytest plugins?

pytest comes with a plugin named pytester that helps you write tests for your plugin code. The plugin is disabled by default, so you will have to enable it before you can use it. Alternatively you can invoke pytest with the -p pytester command line option.

What is Pytest Hookimpl?

If the hook method is labeled as hookwrapper=True , pytest will execute the part before yield first and then execute other same type hook methods. After these methods executed, the part after yield will be executed. (This feature is just like pytest fixtures.)


1 Answers

You cannot selectively disable arbitrary plugins for selected tests. The plugins are loaded at a much earlier stage — when the pytest starts. And the plugins actually define what pytest does and how (i.e., command line options, test collection, filtering, etc).

In other words, it is too late to redefine the pytest's internal structure when it gets to the test execution.

Your best case is, indeed, to mark your tests with @pytest.mark.nocatchlog, and execute them separately:

pytest -m 'nocatchlog' -p no:catchlog  # problematic tests with no plugin
pytest -m 'not nocatchlog`             # all other tests

If those tests not under your control, i.e. if you cannot add marks, then you can only filter by expressions like -k test_logging or -k 'not test_logging' (i.e. by part of their node id).


Specifically for this pytest-catchlog plugin, you can make the same hooks as it does, and remove its log handler from the root logger (assuming that no other loggers were used explicitly):

conftest.py:

import pytest

def _disable_catchlog(item):
    logger = logging.getLogger()
    if item.catch_log_handler in logger.handlers:
        logger.handlers.remove(item.catch_log_handler)

@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_setup(item):
    _disable_catchlog(item)
    yield

@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_call(item):
    _disable_catchlog(item)
    yield

@pytest.hookimpl(hookwrapper=True, trylast=True)
def pytest_runtest_teardown(item):
    _disable_catchlog(item)
    yield
like image 105
Sergey Vasilyev Avatar answered Oct 16 '22 14:10

Sergey Vasilyev