[pypy-svn] r74641 - pypy/branch/py131/py/_plugin

hpk at codespeak.net hpk at codespeak.net
Fri May 21 18:10:50 CEST 2010


Author: hpk
Date: Fri May 21 18:10:48 2010
New Revision: 74641

Modified:
   pypy/branch/py131/py/_plugin/pytest_mark.py
   pypy/branch/py131/py/_plugin/pytest_skipping.py
Log:
update to py-trunk 1.3.1a1 - fixing skipping/xfailing if specified
multiple times


Modified: pypy/branch/py131/py/_plugin/pytest_mark.py
==============================================================================
--- pypy/branch/py131/py/_plugin/pytest_mark.py	(original)
+++ pypy/branch/py131/py/_plugin/pytest_mark.py	Fri May 21 18:10:48 2010
@@ -34,38 +34,43 @@
 
 .. _`scoped-marking`:
 
-Marking classes or modules 
+Marking whole classes or modules 
 ----------------------------------------------------
 
-To mark all methods of a class set a ``pytestmark`` attribute like this::
+If you are programming with Python2.6 you may use ``py.test.mark`` decorators
+with classes to apply markers to all its test methods::
+
+    @py.test.mark.webtest
+    class TestClass:
+        def test_startup(self):
+            ...
+
+This is equivalent to directly applying the decorator to the
+``test_startup`` function. 
+
+To remain compatible with Python2.5 you can instead set a 
+``pytestmark`` attribute on a TestClass like this::
 
     import py
 
     class TestClass:
         pytestmark = py.test.mark.webtest
 
-You can re-use the same markers that you would use for decorating
-a function - in fact this marker decorator will be applied
-to all test methods of the class. 
+or if you need to use multiple markers::
+
+    import py
+
+    class TestClass:
+        pytestmark = [py.test.mark.webtest, pytest.mark.slowtest]
 
 You can also set a module level marker::
 
     import py
     pytestmark = py.test.mark.webtest
 
-in which case then the marker decorator will be applied to all functions and 
+in which case then it will be applied to all functions and 
 methods defined in the module.  
 
-The order in which marker functions are called is this::
-
-    per-function (upon import of module already) 
-    per-class
-    per-module 
-
-Later called markers may overwrite previous key-value settings. 
-Positional arguments are all appended to the same 'args' list 
-of the Marker object. 
-
 Using "-k MARKNAME" to select tests
 ----------------------------------------------------
 
@@ -105,15 +110,23 @@
         """ if passed a single callable argument: decorate it with mark info. 
             otherwise add *args/**kwargs in-place to mark information. """
         if args:
-            if len(args) == 1 and hasattr(args[0], '__call__'):
-                func = args[0]
-                holder = getattr(func, self.markname, None)
-                if holder is None:
-                    holder = MarkInfo(self.markname, self.args, self.kwargs)
-                    setattr(func, self.markname, holder)
+            func = args[0]
+            if len(args) == 1 and hasattr(func, '__call__') or \
+               hasattr(func, '__bases__'):
+                if hasattr(func, '__bases__'):
+                    l = func.__dict__.setdefault("pytestmark", [])
+                    if not isinstance(l, list):
+                       func.pytestmark = [l, self]
+                    else: 
+                       l.append(self)
                 else:
-                    holder.kwargs.update(self.kwargs)
-                    holder.args.extend(self.args)
+                    holder = getattr(func, self.markname, None)
+                    if holder is None:
+                        holder = MarkInfo(self.markname, self.args, self.kwargs)
+                        setattr(func, self.markname, holder)
+                    else:
+                        holder.kwargs.update(self.kwargs)
+                        holder.args.extend(self.args)
                 return func
             else:
                 self.args.extend(args)
@@ -147,6 +160,10 @@
         func = getattr(func, 'im_func', func)  # py2
         for parent in [x for x in (mod, cls) if x]:
             marker = getattr(parent.obj, 'pytestmark', None)
-            if isinstance(marker, MarkDecorator):
-                marker(func)
+            if marker is not None:
+                if not isinstance(marker, list):
+                    marker = [marker]
+                for mark in marker:
+                    if isinstance(mark, MarkDecorator):
+                        mark(func)
     return item

Modified: pypy/branch/py131/py/_plugin/pytest_skipping.py
==============================================================================
--- pypy/branch/py131/py/_plugin/pytest_skipping.py	(original)
+++ pypy/branch/py131/py/_plugin/pytest_skipping.py	Fri May 21 18:10:48 2010
@@ -60,6 +60,19 @@
             #
 
 The ``pytestmark`` decorator will be applied to each test function.
+If your code targets python2.6 or above you can equivalently use 
+the skipif decorator on classes::
+
+    @py.test.mark.skipif("sys.platform == 'win32'")
+    class TestPosixCalls:
+    
+        def test_function(self):
+            # will not be setup or run under 'win32' platform
+            #
+
+It is fine in general to apply multiple "skipif" decorators
+on a single function - this means that if any of the conditions
+apply the function will be skipped. 
 
 .. _`whole class- or module level`: mark.html#scoped-marking
 
@@ -144,17 +157,20 @@
     def istrue(self):
         if self.holder:
             d = {'os': py.std.os, 'sys': py.std.sys, 'config': self.item.config}
-            self.result = True
-            for expr in self.holder.args:
-                self.expr = expr
-                if isinstance(expr, str):
-                    result = cached_eval(self.item.config, expr, d)
-                else:
-                    result = expr
-                if not result:
-                    self.result = False
+            if self.holder.args:
+                self.result = False
+                for expr in self.holder.args:
                     self.expr = expr
-                    break
+                    if isinstance(expr, str):
+                        result = cached_eval(self.item.config, expr, d)
+                    else:
+                        result = expr
+                    if result:
+                        self.result = True
+                        self.expr = expr
+                        break
+            else:
+                self.result = True
         return getattr(self, 'result', False)
 
     def get(self, attr, default=None):



More information about the Pypy-commit mailing list