[py-svn] pytest commit 809c2914a73d: introduce an option that avoids discovery of classes other than unittest.TestCase in modules

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Sat Nov 6 23:44:50 CET 2010


# HG changeset patch -- Bitbucket.org
# Project pytest
# URL http://bitbucket.org/hpk42/pytest/overview
# User holger krekel <holger at merlinux.eu>
# Date 1289083548 -3600
# Node ID 809c2914a73dd1604f9188842f13f9cb8f42a2ff
# Parent  c75f441489d31835abeeabd20c0f6cfd7441b269
introduce an option that avoids discovery of classes other than unittest.TestCase in modules
importing unittest.

--- a/testing/acceptance_test.py
+++ b/testing/acceptance_test.py
@@ -294,6 +294,7 @@ class TestInvocationVariants:
         assert not retcode
         out, err = capsys.readouterr()
         assert "--help" in out
+        pytest.raises(ValueError, lambda: pytest.main(retcode))
 
     def test_invoke_with_path(self, testdir, capsys):
         retcode = testdir.pytestmain(testdir.tmpdir)
@@ -330,3 +331,18 @@ class TestInvocationVariants:
         result.stderr.fnmatch_lines([
             "ERROR*file*or*package*not*found*",
         ])
+
+
+    def test_noclass_discovery_if_not_testcase(self, testdir):
+        testpath = testdir.makepyfile("""
+            import unittest
+            import py
+            class TestHello(object):
+                def test_hello(self):
+                    assert self.attr
+
+            class RealTest(TestHello, unittest.TestCase):
+                attr = 42
+        """)
+        reprec = testdir.inline_run(testpath)
+        reprec.assertoutcome(passed=1)

--- a/pytest/plugin/python.py
+++ b/pytest/plugin/python.py
@@ -59,6 +59,8 @@ def pytest_pycollect_makeitem(__multical
     if res is not None:
         return res
     if collector._istestclasscandidate(name, obj):
+        if hasattr(collector.obj, 'unittest'):
+            return # we assume it's a mixin class for a TestCase derived one
         return Class(name, parent=collector)
     elif collector.funcnamefilter(name) and hasattr(obj, '__call__'):
         if is_generator(obj):
@@ -124,6 +126,7 @@ class PyobjMixin(object):
         return self._fslineno
 
     def reportinfo(self):
+        # XXX caching?
         obj = self.obj
         if hasattr(obj, 'compat_co_firstlineno'):
             # nose compatibility

--- a/testing/plugin/test_assertion.py
+++ b/testing/plugin/test_assertion.py
@@ -161,6 +161,15 @@ def test_functional(testdir):
     result = testdir.runpytest("--no-assert")
     assert "3 == 4" not in result.stdout.str()
 
+def test_AssertionErrorIdentity(testdir):
+    testdir.makepyfile("""
+        def test_hello():
+            import exceptions
+            assert AssertionError is exceptions.AssertionError
+    """)
+    result = testdir.runpytest()
+    result.stdout.fnmatch_lines(["*1 passed*"])
+
 def test_triple_quoted_string_issue113(testdir):
     testdir.makepyfile("""
         def test_hello():

--- a/tox.ini
+++ b/tox.ini
@@ -52,5 +52,6 @@ commands=
 [pytest]
 minversion=2.0
 plugins=pytester
-addargs=-rfx
+addopts=-rfx --pyargs
 rsyncdirs=pytest testing
+

--- a/pytest/plugin/unittest.py
+++ b/pytest/plugin/unittest.py
@@ -1,12 +1,13 @@
-""" support discovery and running of traditional "unittest.py" style tests. """
+""" discovery and running of std-library "unittest" style tests. """
 import py
 import sys
 
 def pytest_pycollect_makeitem(collector, name, obj):
-    if 'unittest' not in sys.modules:
-        return # nobody derived unittest.TestCase
+    unittest = sys.modules.get('unittest')
+    if unittest is None:
+        return # nobody can have derived unittest.TestCase
     try:
-        isunit = issubclass(obj, py.std.unittest.TestCase)
+        isunit = issubclass(obj, unittest.TestCase)
     except KeyboardInterrupt:
         raise
     except Exception:

--- a/pytest/plugin/assertion.py
+++ b/pytest/plugin/assertion.py
@@ -3,6 +3,7 @@ support for presented detailed informati
 """
 import py
 import sys
+from pytest.plugin.monkeypatch import monkeypatch
 
 def pytest_addoption(parser):
     group = parser.getgroup("debugconfig")
@@ -15,25 +16,21 @@ def pytest_configure(config):
     # py._code._assertionnew to detect this plugin was loaded and in
     # turn call the hooks defined here as part of the
     # DebugInterpreter.
+    config._monkeypatch = m = monkeypatch()
     if not config.getvalue("noassert") and not config.getvalue("nomagic"):
         warn_about_missing_assertion()
-        config._oldassertion = py.builtin.builtins.AssertionError
-        config._oldbinrepr = py.code._reprcompare
-        py.builtin.builtins.AssertionError = py.code._AssertionError
         def callbinrepr(op, left, right):
             hook_result = config.hook.pytest_assertrepr_compare(
                 config=config, op=op, left=left, right=right)
             for new_expl in hook_result:
                 if new_expl:
                     return '\n~'.join(new_expl)
-        py.code._reprcompare = callbinrepr
+        m.setattr(py.builtin.builtins,
+                  'AssertionError', py.code._AssertionError)
+        m.setattr(py.code, '_reprcompare', callbinrepr)
 
 def pytest_unconfigure(config):
-    if hasattr(config, '_oldassertion'):
-        py.builtin.builtins.AssertionError = config._oldassertion
-        py.code._reprcompare = config._oldbinrepr
-        del config._oldassertion
-        del config._oldbinrepr
+    config._monkeypatch.undo()
 
 def warn_about_missing_assertion():
     try:

--- a/pytest/main.py
+++ b/pytest/main.py
@@ -403,7 +403,11 @@ def main(args=None, plugins=None):
     if args is None:
         args = sys.argv[1:]
     elif not isinstance(args, (tuple, list)):
-        args = py.std.shlex.split(str(args))
+        if isinstance(args, py.path.local):
+            args = str(args)
+        if not isinstance(args, str):
+            raise ValueError("not a string or argument list: %r" % (args,))
+        args = py.std.shlex.split(args)
     if _preinit:
        _pluginmanager = _preinit.pop(0)
     else: # subsequent calls to main will create a fresh instance



More information about the pytest-commit mailing list