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
|
||||
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
|
||||
-----
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ tags: feature
|
|||
|
||||
- introduce pytest.mark.nocollect for not considering a function for
|
||||
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.
|
||||
|
||||
introduce pytest.mark.importorskip
|
||||
|
|
|
@ -384,12 +384,13 @@ class PyobjMixin(PyobjContext):
|
|||
def reportinfo(self):
|
||||
# XXX caching?
|
||||
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
|
||||
fspath = sys.modules[obj.__module__].__file__
|
||||
if fspath.endswith(".pyc"):
|
||||
fspath = fspath[:-1]
|
||||
lineno = obj.compat_co_firstlineno
|
||||
lineno = compat_co_firstlineno
|
||||
else:
|
||||
fspath, lineno = getfslineno(obj)
|
||||
modpath = self.getmodpath()
|
||||
|
@ -405,7 +406,10 @@ class PyCollector(PyobjMixin, pytest.Collector):
|
|||
""" Look for the __test__ attribute, which is applied by the
|
||||
@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):
|
||||
return self._matches_prefix_or_glob_option('python_classes', name)
|
||||
|
|
|
@ -469,7 +469,7 @@ def skip(msg=""):
|
|||
skip.Exception = Skipped
|
||||
|
||||
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
|
||||
and no python traceback will be reported.
|
||||
|
|
|
@ -544,7 +544,11 @@ def build_summary_stats_line(stats):
|
|||
if val:
|
||||
key_name = key_translation.get(key, key)
|
||||
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:
|
||||
color = 'red'
|
||||
|
|
|
@ -573,7 +573,7 @@ class _MultiCall:
|
|||
|
||||
# XXX note that the __multicall__ argument is supported only
|
||||
# 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
|
||||
# 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::
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -386,7 +386,7 @@ are expected.
|
|||
|
||||
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
|
||||
|
|
|
@ -880,6 +880,21 @@ class TestReportInfo:
|
|||
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):
|
||||
testdir.makeini("""
|
||||
|
|
|
@ -283,6 +283,35 @@ class TestNoselikeTestAttribute:
|
|||
assert len(call.items) == 1
|
||||
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
|
||||
class TestParameterize:
|
||||
|
|
|
@ -779,10 +779,10 @@ def test_terminal_summary(testdir):
|
|||
("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
|
||||
|
||||
# Likewise if no tests were found at all
|
||||
("yellow", "", {}),
|
||||
("yellow", "no tests ran", {}),
|
||||
|
||||
# Test the empty-key special case
|
||||
("yellow", "", {"": (1,)}),
|
||||
("yellow", "no tests ran", {"": (1,)}),
|
||||
("green", "1 passed", {"": (1,), "passed": (1,)}),
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue