diff --git a/CHANGELOG b/CHANGELOG index d859cad21..985681a1b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ Unreleased ----------------------------------- +- fix ordering when mock.patch or other standard decorator-wrappings + are used with test methods. This fixues issue346. Thanks to + Ronny Pfannschmidt and Donald Stufft for helping to isolate it. + - fix issue384 by removing the trial support code since the unittest compat enhancements allow trial to handle it on its own diff --git a/_pytest/main.py b/_pytest/main.py index 372a8019d..48084bab9 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -697,11 +697,4 @@ class Session(FSCollector): yield x node.ihook.pytest_collectreport(report=rep) -def getfslineno(obj): - # xxx let decorators etc specify a sane ordering - if hasattr(obj, 'place_as'): - obj = obj.place_as - fslineno = py.code.getfslineno(obj) - assert isinstance(fslineno[1], int), obj - return fslineno diff --git a/_pytest/python.py b/_pytest/python.py index c09fc6f36..d10100a99 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -3,7 +3,6 @@ import py import inspect import sys import pytest -from _pytest.main import getfslineno from _pytest.mark import MarkDecorator from _pytest.monkeypatch import monkeypatch from py._code.code import TerminalRepr @@ -15,6 +14,16 @@ NoneType = type(None) callable = py.builtin.callable +def getfslineno(obj): + # xxx let decorators etc specify a sane ordering + while hasattr(obj, "__wrapped__"): + obj = obj.__wrapped__ + if hasattr(obj, 'place_as'): + obj = obj.place_as + fslineno = py.code.getfslineno(obj) + assert isinstance(fslineno[1], int), obj + return fslineno + def getimfunc(func): try: return func.__func__ diff --git a/testing/python/integration.py b/testing/python/integration.py index 00e70df83..60002b83f 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -1,5 +1,6 @@ import pytest from _pytest import runner +from _pytest import python class TestOEJSKITSpecials: def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage @@ -55,6 +56,20 @@ class TestOEJSKITSpecials: assert not clscol.funcargs +def test_wrapped_getfslineno(): + def func(): + pass + def wrap(f): + func.__wrapped__ = f + func.patchings = ["qwe"] + return func + @wrap + def wrapped_func(x, y, z): + pass + fs, lineno = python.getfslineno(wrapped_func) + fs2, lineno2 = python.getfslineno(wrap) + assert lineno > lineno2, "getfslineno does not unwrap correctly" + class TestMockDecoration: def test_wrapped_getfuncargnames(self): from _pytest.python import getfuncargnames @@ -119,6 +134,28 @@ class TestMockDecoration: reprec = testdir.inline_run() reprec.assertoutcome(passed=2) + def test_mock_sorting(self, testdir): + pytest.importorskip("mock", "1.0.1") + testdir.makepyfile(""" + import os + import mock + + @mock.patch("os.path.abspath") + def test_one(abspath): + pass + @mock.patch("os.path.abspath") + def test_two(abspath): + pass + @mock.patch("os.path.abspath") + def test_three(abspath): + pass + """) + reprec = testdir.inline_run() + calls = reprec.getreports("pytest_runtest_logreport") + calls = [x for x in calls if x.when == "call"] + names = [x.nodeid.split("::")[-1] for x in calls] + assert names == ["test_one", "test_two", "test_three"] + class TestReRunTests: def test_rerun(self, testdir):