Skip to content

Pytest 3.3: cannot mock root logger #2974

@CaselIT

Description

@CaselIT

Pytest 3.3.0 uses the root logger in each test so it can no longer be mocked with monkeypatch

import logging
import pytest
from unittest.mock import MagicMock
@pytest.fixture
def setup(monkeypatch):
    mock = MagicMock()
    monkeypatch.setattr('logging.getLogger', lambda: mock) 
    return mock
def test_x(setup, monkeypatch):
    assert id(setup) == id(logging.getLogger())

raires

TypeError: <lambda>() takes 0 positional arguments but 1 was given
<python-path>\lib\contextlib.py:81: TypeError

changing the lambda to lambda _: mock raises

TypeError: '<' not supported between instances of 'int' and 'MagicMock'
<python-path>\lib\contextlib.py:81: TypeError

Moving the monkeypatch call in the function does not help since the second error is always raised.
The error is raised in <python-path>\lib\site-packages\_pytest\logging.py on line 102 or 110

Using the --no-print-logs flag does not change the output

Pytest 3.2.5 does not have this problem

Also if there are subsequent tests after the one that caused the previous error, pytest crashes completely: appending

def test_y():
    assert True

after test_x in the example above results in the following error when running pytest without filters

x_test.py FE                                                             [100%]
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\main.py", line 103, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\main.py", line 141, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 617, in __call__
INTERNALERROR>     return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 222, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 216, in <lambda>
INTERNALERROR>     firstresult=hook.spec_opts.get('firstresult'),
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 201, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 76, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 180, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\main.py", line 164, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 617, in __call__
INTERNALERROR>     return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 222, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 216, in <lambda>
INTERNALERROR>     firstresult=hook.spec_opts.get('firstresult'),
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 201, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 76, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 180, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\runner.py", line 63, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\runner.py", line 71, in runtestprotocol
INTERNALERROR>     rep = call_and_report(item, "setup", log)
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\runner.py", line 159, in call_and_report
INTERNALERROR>     report = hook.pytest_runtest_makereport(item=item, call=call)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 617, in __call__
INTERNALERROR>     return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 222, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\__init__.py", line 216, in <lambda>
INTERNALERROR>     firstresult=hook.spec_opts.get('firstresult'),
INTERNALERROR>   File "<python-path>\lib\site-packages\pluggy\callers.py", line 196, in _multicall
INTERNALERROR>     gen.send(outcome)
INTERNALERROR>   File "<python-path>\lib\site-packages\_pytest\skipping.py", line 264, in pytest_runtest_makereport
INTERNALERROR>     elif item._skipped_by_mark and rep.skipped and type(rep.longrepr) is tuple:
INTERNALERROR> AttributeError: 'Function' object has no attribute '_skipped_by_mark'

Selecting only test_x does not raises the AttributeError
I'm on windows 10 with python 3.6.3, but I've confirmed the same bug on linux under python 3.5 and 3.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: loggingrelated to the logging builtin plugintype: regressionindicates a problem that was introduced in a release which was working previously

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions