[pypy-commit] pypy default: Merge branch 'testing-cleanup'

rlamy pypy.commits at gmail.com
Fri Jun 10 09:45:10 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: 
Changeset: r85078:18006cfc913c
Date: 2016-06-10 14:44 +0100
http://bitbucket.org/pypy/pypy/changeset/18006cfc913c/

Log:	Merge branch 'testing-cleanup'

	Simplify handling of interp-level tests and make it more forward-
	compatible.

diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -76,6 +76,20 @@
 def pytest_pycollect_makemodule(path, parent):
     return PyPyModule(path, parent)
 
+def is_applevel(item):
+    from pypy.tool.pytest.apptest import AppTestFunction
+    return isinstance(item, AppTestFunction)
+
+def pytest_collection_modifyitems(config, items):
+    if config.option.runappdirect:
+        return
+    for item in items:
+        if isinstance(item, py.test.Function):
+            if is_applevel(item):
+                item.add_marker('applevel')
+            else:
+                item.add_marker('interplevel')
+
 class PyPyModule(py.test.collect.Module):
     """ we take care of collecting classes both at app level
         and at interp-level (because we need to stick a space
@@ -110,9 +124,6 @@
             if name.startswith('AppTest'):
                 from pypy.tool.pytest.apptest import AppClassCollector
                 return AppClassCollector(name, parent=self)
-            else:
-                from pypy.tool.pytest.inttest import IntClassCollector
-                return IntClassCollector(name, parent=self)
 
         elif hasattr(obj, 'func_code') and self.funcnamefilter(name):
             if name.startswith('app_test_'):
@@ -120,11 +131,7 @@
                     "generator app level functions? you must be joking"
                 from pypy.tool.pytest.apptest import AppTestFunction
                 return AppTestFunction(name, parent=self)
-            elif obj.func_code.co_flags & 32: # generator function
-                return pytest.Generator(name, parent=self)
-            else:
-                from pypy.tool.pytest.inttest import IntTestFunction
-                return IntTestFunction(name, parent=self)
+        return super(PyPyModule, self).makeitem(name, obj)
 
 def skip_on_missing_buildoption(**ropts):
     __tracebackhide__ = True
@@ -153,28 +160,19 @@
 
 def pytest_runtest_setup(__multicall__, item):
     if isinstance(item, py.test.collect.Function):
-        appclass = item.getparent(PyPyClassCollector)
+        appclass = item.getparent(py.test.Class)
         if appclass is not None:
             # Make cls.space and cls.runappdirect available in tests.
             spaceconfig = getattr(appclass.obj, 'spaceconfig', None)
             if spaceconfig is not None:
                 from pypy.tool.pytest.objspace import gettestobjspace
                 appclass.obj.space = gettestobjspace(**spaceconfig)
+            else:
+                appclass.obj.space = LazyObjSpaceGetter()
             appclass.obj.runappdirect = option.runappdirect
 
     __multicall__.execute()
 
 
-class PyPyClassCollector(py.test.collect.Class):
-    # All pypy Test classes have a "space" member.
-    def setup(self):
-        cls = self.obj
-        if not hasattr(cls, 'spaceconfig'):
-            cls.space = LazyObjSpaceGetter()
-        else:
-            assert hasattr(cls, 'space') # set by pytest_runtest_setup
-        super(PyPyClassCollector, self).setup()
-
-
 def pytest_ignore_collect(path):
     return path.check(link=1)
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -458,14 +458,17 @@
         decl = str(decl) + "\n"
         yield self.st, decl, 'x', (1, 2, 3, 4)
 
+    def test_closure_error(self):
         source = """if 1:
         def f(a):
             del a
             def x():
                 a
         """
-        exc = py.test.raises(SyntaxError, self.run, source).value
-        assert exc.msg == "Can't delete variable used in nested scopes: 'a'"
+        with py.test.raises(SyntaxError) as excinfo:
+            self.run(source)
+        msg = excinfo.value.msg
+        assert msg == "Can't delete variable used in nested scopes: 'a'"
 
     def test_try_except_finally(self):
         yield self.simple_test, """
@@ -879,7 +882,20 @@
         """
         self.simple_test(source, 'ok', 1)
 
-    def test_remove_docstring(self):
+    @py.test.mark.parametrize('expr, result', [
+        ("f1.__doc__", None),
+        ("f2.__doc__", 'docstring'),
+        ("f2()", 'docstring'),
+        ("f3.__doc__", None),
+        ("f3()", 'bar'),
+        ("C1.__doc__", None),
+        ("C2.__doc__", 'docstring'),
+        ("C3.field", 'not docstring'),
+        ("C4.field", 'docstring'),
+        ("C4.__doc__", 'docstring'),
+        ("C4.__doc__", 'docstring'),
+        ("__doc__", None),])
+    def test_remove_docstring(self, expr, result):
         source = '"module_docstring"\n' + """if 1:
         def f1():
             'docstring'
@@ -903,19 +919,7 @@
         code_w.remove_docstrings(self.space)
         dict_w = self.space.newdict();
         code_w.exec_code(self.space, dict_w, dict_w)
-
-        yield self.check, dict_w, "f1.__doc__", None
-        yield self.check, dict_w, "f2.__doc__", 'docstring'
-        yield self.check, dict_w, "f2()", 'docstring'
-        yield self.check, dict_w, "f3.__doc__", None
-        yield self.check, dict_w, "f3()", 'bar'
-        yield self.check, dict_w, "C1.__doc__", None
-        yield self.check, dict_w, "C2.__doc__", 'docstring'
-        yield self.check, dict_w, "C3.field", 'not docstring'
-        yield self.check, dict_w, "C4.field", 'docstring'
-        yield self.check, dict_w, "C4.__doc__", 'docstring'
-        yield self.check, dict_w, "C4.__doc__", 'docstring'
-        yield self.check, dict_w, "__doc__", None
+        self.check(dict_w, expr, result)
 
     def test_assert_skipping(self):
         space = self.space
@@ -1111,7 +1115,7 @@
             return d['f'](5)
         """)
         assert 'generator' in space.str_w(space.repr(w_generator))
-        
+
     def test_list_comprehension(self):
         source = "def f(): [i for i in l]"
         source2 = "def f(): [i for i in l for j in l]"
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -671,13 +671,11 @@
 
 class AppTestSocketTCP:
     HOST = 'localhost'
-
-    def setup_class(cls):
-        cls.space = space
+    spaceconfig = {'usemodules': ['_socket', 'array']}
 
     def setup_method(self, method):
-        w_HOST = space.wrap(self.HOST)
-        self.w_serv = space.appexec([w_socket, w_HOST],
+        w_HOST = self.space.wrap(self.HOST)
+        self.w_serv =self.space.appexec([w_socket, w_HOST],
             '''(_socket, HOST):
             serv = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
             serv.bind((HOST, 0))
@@ -687,7 +685,7 @@
 
     def teardown_method(self, method):
         if hasattr(self, 'w_serv'):
-            space.appexec([self.w_serv], '(serv): serv.close()')
+            self.space.appexec([self.w_serv], '(serv): serv.close()')
             self.w_serv = None
 
     def test_timeout(self):
@@ -803,8 +801,7 @@
 
 
 class AppTestErrno:
-    def setup_class(cls):
-        cls.space = space
+    spaceconfig = {'usemodules': ['_socket']}
 
     def test_errno(self):
         from socket import socket, AF_INET, SOCK_STREAM, error
diff --git a/pypy/module/_vmprof/test/test__vmprof.py b/pypy/module/_vmprof/test/test__vmprof.py
--- a/pypy/module/_vmprof/test/test__vmprof.py
+++ b/pypy/module/_vmprof/test/test__vmprof.py
@@ -3,8 +3,9 @@
 from pypy.tool.pytest.objspace import gettestobjspace
 
 class AppTestVMProf(object):
+    spaceconfig = {'usemodules': ['_vmprof', 'struct']}
+
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['_vmprof', 'struct'])
         cls.w_tmpfilename = cls.space.wrap(str(udir.join('test__vmprof.1')))
         cls.w_tmpfilename2 = cls.space.wrap(str(udir.join('test__vmprof.2')))
 
@@ -17,7 +18,7 @@
         import struct, sys, gc
 
         WORD = struct.calcsize('l')
-        
+
         def count(s):
             i = 0
             count = 0
@@ -44,7 +45,7 @@
                 else:
                     raise AssertionError(ord(s[i]))
             return count
-        
+
         import _vmprof
         gc.collect()  # try to make the weakref list deterministic
         gc.collect()  # by freeing all dead code objects
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -13,14 +13,15 @@
 import sys
 import signal
 
+USEMODULES = ['binascii', 'posix', 'struct', 'time']
+if os.name != 'nt':
+    USEMODULES += ['fcntl']
+else:
+    # On windows, os.popen uses the subprocess module
+    USEMODULES += ['_rawffi', 'thread', 'signal']
+
 def setup_module(mod):
-    usemodules = ['binascii', 'posix', 'struct', 'time']
-    if os.name != 'nt':
-        usemodules += ['fcntl']
-    else:
-        # On windows, os.popen uses the subprocess module
-        usemodules += ['_rawffi', 'thread', 'signal']
-    mod.space = gettestobjspace(usemodules=usemodules)
+    mod.space = gettestobjspace(usemodules=USEMODULES)
     mod.path = udir.join('posixtestfile.txt')
     mod.path.write("this is a test")
     mod.path2 = udir.join('test_posix2-')
@@ -49,9 +50,10 @@
 
 
 class AppTestPosix:
+    spaceconfig = {'usemodules': USEMODULES}
 
     def setup_class(cls):
-        cls.space = space
+        space = cls.space
         cls.w_runappdirect = space.wrap(cls.runappdirect)
         cls.w_posix = space.appexec([], GET_POSIX)
         cls.w_path = space.wrap(str(path))
@@ -1145,14 +1147,10 @@
 
 class AppTestEnvironment(object):
     def setup_class(cls):
-        cls.space = space
-        cls.w_posix = space.appexec([], "(): import %s as m ; return m" % os.name)
-        cls.w_os = space.appexec([], "(): import os; return os")
         cls.w_path = space.wrap(str(path))
 
     def test_environ(self):
-        posix = self.posix
-        os = self.os
+        import posix
         assert posix.environ['PATH']
         del posix.environ['PATH']
         def fn(): posix.environ['PATH']
@@ -1160,7 +1158,7 @@
 
     if hasattr(__import__(os.name), "unsetenv"):
         def test_unsetenv_nonexisting(self):
-            os = self.os
+            import os
             os.unsetenv("XYZABC") #does not raise
             try:
                 os.environ["ABCABC"]
@@ -1178,8 +1176,6 @@
 
 class AppTestPosixUnicode:
     def setup_class(cls):
-        cls.space = space
-        cls.w_posix = space.appexec([], GET_POSIX)
         if cls.runappdirect:
             # Can't change encoding
             try:
@@ -1187,8 +1183,8 @@
             except UnicodeEncodeError:
                 py.test.skip("encoding not good enough")
         else:
-            cls.save_fs_encoding = space.sys.filesystemencoding
-            space.sys.filesystemencoding = "utf-8"
+            cls.save_fs_encoding = cls.space.sys.filesystemencoding
+            cls.space.sys.filesystemencoding = "utf-8"
 
     def teardown_class(cls):
         try:
@@ -1198,22 +1194,25 @@
 
     def test_stat_unicode(self):
         # test that passing unicode would not raise UnicodeDecodeError
+        import posix
         try:
-            self.posix.stat(u"ą")
+            posix.stat(u"ą")
         except OSError:
             pass
 
     def test_open_unicode(self):
         # Ensure passing unicode doesn't raise UnicodeEncodeError
+        import posix
         try:
-            self.posix.open(u"ą", self.posix.O_WRONLY)
+            posix.open(u"ą", posix.O_WRONLY)
         except OSError:
             pass
 
     def test_remove_unicode(self):
         # See 2 above ;)
+        import posix
         try:
-            self.posix.remove(u"ą")
+            posix.remove(u"ą")
         except OSError:
             pass
 
diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py
--- a/pypy/tool/pytest/apptest.py
+++ b/pypy/tool/pytest/apptest.py
@@ -13,7 +13,6 @@
 from pypy.interpreter.function import Method
 from pypy.tool.pytest import appsupport
 from pypy.tool.pytest.objspace import gettestobjspace
-from pypy.conftest import PyPyClassCollector
 from inspect import getmro
 
 
@@ -21,13 +20,8 @@
     def __init__(self, excinfo):
         self.excinfo = excinfo
 
-marker = py.test.mark.applevel
 
 class AppTestFunction(py.test.collect.Function):
-    def __init__(self, *args, **kwargs):
-        super(AppTestFunction, self).__init__(*args, **kwargs)
-        self._request.applymarker(marker)
-
     def _prunetraceback(self, traceback):
         return traceback
 
@@ -122,7 +116,7 @@
             self.w_instance = space.call_function(w_class)
 
 
-class AppClassCollector(PyPyClassCollector):
+class AppClassCollector(py.test.Class):
     Instance = AppClassInstance
 
     def setup(self):
diff --git a/pypy/tool/pytest/inttest.py b/pypy/tool/pytest/inttest.py
deleted file mode 100644
--- a/pypy/tool/pytest/inttest.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Collects and executes interpreter-level tests.
-#
-# Most pypy tests are of this kind.
-
-import py
-import sys
-from pypy.interpreter.error import OperationError
-from pypy.conftest import PyPyClassCollector
-
-
-def check_keyboard_interrupt(e):
-    # we cannot easily convert w_KeyboardInterrupt to KeyboardInterrupt
-    # in general without a space -- here is an approximation
-    try:
-        if e.w_type.name == 'KeyboardInterrupt':
-            tb = sys.exc_info()[2]
-            raise KeyboardInterrupt, KeyboardInterrupt(), tb
-    except AttributeError:
-        pass
-
-
-marker = py.test.mark.interplevel
-
-
-class IntTestFunction(py.test.collect.Function):
-    def __init__(self, *args, **kwargs):
-        super(IntTestFunction, self).__init__(*args, **kwargs)
-        self._request.applymarker(marker)
-
-    def runtest(self):
-        try:
-            super(IntTestFunction, self).runtest()
-        except OperationError as e:
-            check_keyboard_interrupt(e)
-            raise
-        except Exception as e:
-            cls = e.__class__
-            while cls is not Exception:
-                if cls.__name__ == 'DistutilsPlatformError':
-                    from distutils.errors import DistutilsPlatformError
-                    if isinstance(e, DistutilsPlatformError):
-                        py.test.skip('%s: %s' % (e.__class__.__name__, e))
-                cls = cls.__bases__[0]
-            raise
-
-
-class IntInstanceCollector(py.test.collect.Instance):
-    Function = IntTestFunction
-
-
-class IntClassCollector(PyPyClassCollector):
-    Instance = IntInstanceCollector
diff --git a/pypy/tool/pytest/test/test_appsupport.py b/pypy/tool/pytest/test/test_appsupport.py
--- a/pypy/tool/pytest/test/test_appsupport.py
+++ b/pypy/tool/pytest/test/test_appsupport.py
@@ -27,11 +27,11 @@
     result = testdir.runpytest("--collectonly")
     assert result.ret == 0
     result.stdout.fnmatch_lines([
-        "*IntTestFunction*test_func*",
-        "*IntClassCollector*TestClassInt*",
-        "*IntTestFunction*test_method*",
+        "*Function*test_func*",
+        "*Class*TestClassInt*",
+        "*Function*test_method*",
         "*AppClassCollector*AppTestClass*",
-        "*AppTestMethod*", 
+        "*AppTestMethod*",
     ])
 
 class TestSpaceConfig:
@@ -133,5 +133,5 @@
 
     x = 43
     info = raises(ZeroDivisionError, "x/0")
-    assert info.type is ZeroDivisionError    
-    assert isinstance(info.value, ZeroDivisionError)    
+    assert info.type is ZeroDivisionError
+    assert isinstance(info.value, ZeroDivisionError)
diff --git a/pypy/tool/pytest/test/test_conftest1.py b/pypy/tool/pytest/test/test_conftest1.py
--- a/pypy/tool/pytest/test/test_conftest1.py
+++ b/pypy/tool/pytest/test/test_conftest1.py
@@ -20,11 +20,3 @@
         assert not skipped and not failed
         assert "app_test_something" in passed[0].nodeid
         assert "test_method_app" in passed[1].nodeid
-
-    def test_appdirect(self, testdir):
-        sorter = testdir.inline_run(innertest, '-m', 'applevel', '--runappdirect')
-        passed, skipped, failed = sorter.listoutcomes()
-        assert len(passed) == 2
-        print passed
-        assert "app_test_something" in passed[0].nodeid
-        assert "test_method_app" in passed[1].nodeid


More information about the pypy-commit mailing list