Skip to content

Commit

Permalink
Refactor pytest plugin to not monkey patch call_runtest_hook. (#157)
Browse files Browse the repository at this point in the history
A previous refactor (#74) enabled this, but I didn't notice.
Previously, flaky stored information about test reruns inside a
CallInfo subclass. call_runtest_hook was monkey patched so that
flaky could ensure that subclass was created. #74 moved that info
into the plugin, so the monkey patch was no longer doing anything
special.

However, over time, flaky's implementation diverged from pytest's.
This caused #139 and #156.

This commit removes the monkey patch, and flaky now uses pytest's
implementation, which fixes those issues and is more future proof.
  • Loading branch information
Jeff-Meadows authored Aug 6, 2019
1 parent 8f848f8 commit 1613953
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 25 deletions.
3 changes: 3 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Release History
Upcoming
++++++++

**Bugfixes**
- Reraise ``KeyboardInterrupt`` when running tests under pytest.


3.6.0 (2019-06-25)
++++++++++++++++++
Expand Down
25 changes: 3 additions & 22 deletions flaky/flaky_pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import unicode_literals

from _pytest.runner import CallInfo # pylint:disable=import-error
from _pytest.runner import call_runtest_hook # pylint:disable=import-error

from flaky._flaky_plugin import _FlakyPlugin
from flaky.utils import ensure_unicode_string
Expand Down Expand Up @@ -126,7 +126,8 @@ def call_and_report(self, item, when, log=True, **kwds):
:type log:
`bool`
"""
call = self.call_runtest_hook(item, when, **kwds)
call = call_runtest_hook(item, when, **kwds)
self._call_infos[item][when] = call
hook = item.ihook
report = hook.pytest_runtest_makereport(item=item, call=call)
# Start flaky modifications
Expand Down Expand Up @@ -289,26 +290,6 @@ def _get_test_instance(item):
test_instance = item.parent.obj
return test_instance

def call_runtest_hook(self, item, when, **kwds):
"""
Monkey patched from the runner plugin. Responsible for running
the test. Had to be patched to pass additional info to the
CallInfo so the tests can be rerun if necessary.
:param item:
pytest wrapper for the test function to be run
:type item:
:class:`Function`
"""
hookname = "pytest_runtest_" + when
ihook = getattr(item.ihook, hookname)
call_info = getattr(CallInfo, "from_call", CallInfo)(
lambda: ihook(item=item, **kwds),
when=when,
)
self._call_infos[item][when] = call_info
return call_info

def add_success(self, item):
"""
Called when a test succeeds.
Expand Down
23 changes: 20 additions & 3 deletions test/test_pytest/test_flaky_pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
from mock import Mock, patch
# pylint:disable=import-error
import pytest
from _pytest.runner import CallInfo
# pylint:enable=import-error
from flaky import flaky
from flaky import _flaky_plugin
from flaky.flaky_pytest_plugin import (
CallInfo,
call_runtest_hook,
FlakyPlugin,
FlakyXdist,
PLUGIN,
Expand Down Expand Up @@ -54,7 +55,7 @@ def get_calls():


@pytest.fixture(params=['instance', 'module', 'parent'])
def flaky_test(request):
def flaky_test(request, mock_config):
def test_function():
pass
test_owner = Mock()
Expand All @@ -63,6 +64,7 @@ def test_function():
kwargs = {request.param: test_owner}
test = MockTestItem(**kwargs)
setattr(test, 'owner', test_owner)
setattr(test, 'config', mock_config)
return test


Expand Down Expand Up @@ -103,6 +105,21 @@ def runtest(self):
pass


class MockConfig(object):
def getvalue(self, key):
# pylint:disable=unused-argument,no-self-use
return False

def getoption(self, key, default):
# pylint:disable=unused-argument,no-self-use
return default


@pytest.fixture
def mock_config():
return MockConfig()


class MockFlakyCallInfo(CallInfo):
def __init__(self, item, when):
# pylint:disable=super-init-not-called
Expand Down Expand Up @@ -226,7 +243,7 @@ def error_raising_setup_function(item):
flaky_test.ihook = Mock()
flaky_test.ihook.pytest_runtest_setup = error_raising_setup_function
flaky_plugin._call_infos[flaky_test] = {} # pylint:disable=protected-access
call_info = flaky_plugin.call_runtest_hook(flaky_test, 'setup')
call_info = call_runtest_hook(flaky_test, 'setup')
assert flaky_test.ran_setup
assert string_io.getvalue() == mock_io.getvalue()
assert call_info.excinfo.type is ZeroDivisionError
Expand Down

0 comments on commit 1613953

Please sign in to comment.