Merge remote-tracking branch 'upstream/master' into pastebin-py3
This commit is contained in:
commit
a54e4e64cd
|
@ -9,6 +9,12 @@
|
||||||
- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
|
- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
|
||||||
Mehdy Khoshnoody for the PR.
|
Mehdy Khoshnoody for the PR.
|
||||||
|
|
||||||
|
- fix #1204: another error when collecting with a nasty __getattr__().
|
||||||
|
Thanks Florian Bruhin for the PR.
|
||||||
|
|
||||||
|
- fix the summary printed when no tests did run.
|
||||||
|
Thanks Florian Bruhin for the PR.
|
||||||
|
|
||||||
2.8.3
|
2.8.3
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ tags: feature
|
||||||
|
|
||||||
- introduce pytest.mark.nocollect for not considering a function for
|
- introduce pytest.mark.nocollect for not considering a function for
|
||||||
test collection at all. maybe also introduce a pytest.mark.test to
|
test collection at all. maybe also introduce a pytest.mark.test to
|
||||||
explicitely mark a function to become a tested one. Lookup JUnit ways
|
explicitly mark a function to become a tested one. Lookup JUnit ways
|
||||||
of tagging tests.
|
of tagging tests.
|
||||||
|
|
||||||
introduce pytest.mark.importorskip
|
introduce pytest.mark.importorskip
|
||||||
|
|
|
@ -384,12 +384,13 @@ class PyobjMixin(PyobjContext):
|
||||||
def reportinfo(self):
|
def reportinfo(self):
|
||||||
# XXX caching?
|
# XXX caching?
|
||||||
obj = self.obj
|
obj = self.obj
|
||||||
if hasattr(obj, 'compat_co_firstlineno'):
|
compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)
|
||||||
|
if isinstance(compat_co_firstlineno, int):
|
||||||
# nose compatibility
|
# nose compatibility
|
||||||
fspath = sys.modules[obj.__module__].__file__
|
fspath = sys.modules[obj.__module__].__file__
|
||||||
if fspath.endswith(".pyc"):
|
if fspath.endswith(".pyc"):
|
||||||
fspath = fspath[:-1]
|
fspath = fspath[:-1]
|
||||||
lineno = obj.compat_co_firstlineno
|
lineno = compat_co_firstlineno
|
||||||
else:
|
else:
|
||||||
fspath, lineno = getfslineno(obj)
|
fspath, lineno = getfslineno(obj)
|
||||||
modpath = self.getmodpath()
|
modpath = self.getmodpath()
|
||||||
|
@ -405,7 +406,10 @@ class PyCollector(PyobjMixin, pytest.Collector):
|
||||||
""" Look for the __test__ attribute, which is applied by the
|
""" Look for the __test__ attribute, which is applied by the
|
||||||
@nose.tools.istest decorator
|
@nose.tools.istest decorator
|
||||||
"""
|
"""
|
||||||
return safe_getattr(obj, '__test__', False)
|
# We explicitly check for "is True" here to not mistakenly treat
|
||||||
|
# classes with a custom __getattr__ returning something truthy (like a
|
||||||
|
# function) as test classes.
|
||||||
|
return safe_getattr(obj, '__test__', False) is True
|
||||||
|
|
||||||
def classnamefilter(self, name):
|
def classnamefilter(self, name):
|
||||||
return self._matches_prefix_or_glob_option('python_classes', name)
|
return self._matches_prefix_or_glob_option('python_classes', name)
|
||||||
|
|
|
@ -469,7 +469,7 @@ def skip(msg=""):
|
||||||
skip.Exception = Skipped
|
skip.Exception = Skipped
|
||||||
|
|
||||||
def fail(msg="", pytrace=True):
|
def fail(msg="", pytrace=True):
|
||||||
""" explicitely fail an currently-executing test with the given Message.
|
""" explicitly fail an currently-executing test with the given Message.
|
||||||
|
|
||||||
:arg pytrace: if false the msg represents the full failure information
|
:arg pytrace: if false the msg represents the full failure information
|
||||||
and no python traceback will be reported.
|
and no python traceback will be reported.
|
||||||
|
|
|
@ -544,7 +544,11 @@ def build_summary_stats_line(stats):
|
||||||
if val:
|
if val:
|
||||||
key_name = key_translation.get(key, key)
|
key_name = key_translation.get(key, key)
|
||||||
parts.append("%d %s" % (len(val), key_name))
|
parts.append("%d %s" % (len(val), key_name))
|
||||||
line = ", ".join(parts)
|
|
||||||
|
if parts:
|
||||||
|
line = ", ".join(parts)
|
||||||
|
else:
|
||||||
|
line = "no tests ran"
|
||||||
|
|
||||||
if 'failed' in stats or 'error' in stats:
|
if 'failed' in stats or 'error' in stats:
|
||||||
color = 'red'
|
color = 'red'
|
||||||
|
|
|
@ -573,7 +573,7 @@ class _MultiCall:
|
||||||
|
|
||||||
# XXX note that the __multicall__ argument is supported only
|
# XXX note that the __multicall__ argument is supported only
|
||||||
# for pytest compatibility reasons. It was never officially
|
# for pytest compatibility reasons. It was never officially
|
||||||
# supported there and is explicitely deprecated since 2.8
|
# supported there and is explicitly deprecated since 2.8
|
||||||
# so we can remove it soon, allowing to avoid the below recursion
|
# so we can remove it soon, allowing to avoid the below recursion
|
||||||
# in execute() and simplify/speed up the execute loop.
|
# in execute() and simplify/speed up the execute loop.
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ For an example on how to add and work with markers from a plugin, see
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
It is recommended to explicitely register markers so that:
|
It is recommended to explicitly register markers so that:
|
||||||
|
|
||||||
* there is one place in your test suite defining your markers
|
* there is one place in your test suite defining your markers
|
||||||
|
|
||||||
|
|
|
@ -386,7 +386,7 @@ are expected.
|
||||||
|
|
||||||
For an example, see `newhooks.py`_ from :ref:`xdist`.
|
For an example, see `newhooks.py`_ from :ref:`xdist`.
|
||||||
|
|
||||||
.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default
|
.. _`newhooks.py`: https://github.com/pytest-dev/pytest-xdist/blob/974bd566c599dc6a9ea291838c6f226197208b46/xdist/newhooks.py
|
||||||
|
|
||||||
|
|
||||||
Optionally using hooks from 3rd party plugins
|
Optionally using hooks from 3rd party plugins
|
||||||
|
|
|
@ -880,6 +880,21 @@ class TestReportInfo:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def test_reportinfo_with_nasty_getattr(self, testdir):
|
||||||
|
# https://github.com/pytest-dev/pytest/issues/1204
|
||||||
|
modcol = testdir.getmodulecol("""
|
||||||
|
# lineno 0
|
||||||
|
class TestClass:
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return "this is not an int"
|
||||||
|
|
||||||
|
def test_foo(self):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
classcol = testdir.collect_by_name(modcol, "TestClass")
|
||||||
|
instance = classcol.collect()[0]
|
||||||
|
fspath, lineno, msg = instance.reportinfo()
|
||||||
|
|
||||||
|
|
||||||
def test_customized_python_discovery(testdir):
|
def test_customized_python_discovery(testdir):
|
||||||
testdir.makeini("""
|
testdir.makeini("""
|
||||||
|
|
|
@ -283,6 +283,35 @@ class TestNoselikeTestAttribute:
|
||||||
assert len(call.items) == 1
|
assert len(call.items) == 1
|
||||||
assert call.items[0].cls.__name__ == "TC"
|
assert call.items[0].cls.__name__ == "TC"
|
||||||
|
|
||||||
|
def test_class_with_nasty_getattr(self, testdir):
|
||||||
|
"""Make sure we handle classes with a custom nasty __getattr__ right.
|
||||||
|
|
||||||
|
With a custom __getattr__ which e.g. returns a function (like with a
|
||||||
|
RPC wrapper), we shouldn't assume this meant "__test__ = True".
|
||||||
|
"""
|
||||||
|
# https://github.com/pytest-dev/pytest/issues/1204
|
||||||
|
testdir.makepyfile("""
|
||||||
|
class MetaModel(type):
|
||||||
|
|
||||||
|
def __getattr__(cls, key):
|
||||||
|
return lambda: None
|
||||||
|
|
||||||
|
|
||||||
|
BaseModel = MetaModel('Model', (), {})
|
||||||
|
|
||||||
|
|
||||||
|
class Model(BaseModel):
|
||||||
|
|
||||||
|
__metaclass__ = MetaModel
|
||||||
|
|
||||||
|
def test_blah(self):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
reprec = testdir.inline_run()
|
||||||
|
assert not reprec.getfailedcollections()
|
||||||
|
call = reprec.getcalls("pytest_collection_modifyitems")[0]
|
||||||
|
assert not call.items
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.issue351
|
@pytest.mark.issue351
|
||||||
class TestParameterize:
|
class TestParameterize:
|
||||||
|
|
|
@ -779,10 +779,10 @@ def test_terminal_summary(testdir):
|
||||||
("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
|
("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
|
||||||
|
|
||||||
# Likewise if no tests were found at all
|
# Likewise if no tests were found at all
|
||||||
("yellow", "", {}),
|
("yellow", "no tests ran", {}),
|
||||||
|
|
||||||
# Test the empty-key special case
|
# Test the empty-key special case
|
||||||
("yellow", "", {"": (1,)}),
|
("yellow", "no tests ran", {"": (1,)}),
|
||||||
("green", "1 passed", {"": (1,), "passed": (1,)}),
|
("green", "1 passed", {"": (1,), "passed": (1,)}),
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue