[Zope3-checkins] SVN: zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/ savepoint

Godefroid Chapelle gotcha at bubblenet.be
Tue Mar 1 04:54:39 EST 2011


Log message for revision 120629:
  savepoint

Changed:
  A   zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/layerutils.py
  U   zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/runner.py
  U   zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/tests.py

-=-
Added: zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/layerutils.py
===================================================================
--- zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/layerutils.py	                        (rev 0)
+++ zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/layerutils.py	2011-03-01 09:54:38 UTC (rev 120629)
@@ -0,0 +1,157 @@
+##############################################################################
+#
+# Copyright (c) 2004-2008 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Layer helpers
+"""
+from zope.testing.testrunner.find import name_from_layer
+
+
+def order_by_bases(layers):
+    """Order the layers from least to most specific (bottom to top)
+
+    >>> class Base(object):
+    ...    __bases__ = ()
+    ...    @property
+    ...    def __name__(self):
+    ...        return self.__class__.__name__
+    ...    def __repr__(self):
+    ...        return self.__name__
+
+    A layer without any base:
+
+    >>> class Zero(Base):
+    ...     pass
+    >>> zero = Zero()
+
+    A layer with a single base:
+
+    >>> class One(Base):
+    ...    __bases__ = (zero, )
+    >>> one = One()
+
+    Less specific comes first:
+
+    >>> order_by_bases([one, zero])
+    [Zero, One]
+
+
+    Another layer with a single base:
+
+    >>> class OneBis(Base):
+    ...    __bases__ = (one, )
+    >>> one_bis = OneBis()
+
+    Less specific comes first:
+
+    >>> order_by_bases([one, zero, one_bis])
+    [Zero, One, OneBis]
+
+    Order of layers of identical specificity does not depend
+    on their order in the input:
+
+    >>> order_by_bases([one_bis, zero, one])
+    [Zero, One, OneBis]
+    >>> order_by_bases([one_bis, one, zero])
+    [Zero, One, OneBis]
+    >>> order_by_bases([zero, one_bis, one])
+    [Zero, One, OneBis]
+
+    Another layer with a single base:
+
+    >>> class OneTer(Base):
+    ...    __bases__ = (zero, )
+    >>> one_ter = OneTer()
+
+    Less specific still comes first:
+
+    >>> order_by_bases([one_bis, one_ter, one, zero])
+    [Zero, OneTer, One, OneBis]
+
+    Order of layers of identical specificity does still not depend
+    on their order in the input:
+
+    >>> order_by_bases([one_ter, one_bis, one, zero])
+    [Zero, OneTer, One, OneBis]
+    >>> order_by_bases([zero, one_ter, one_bis, one])
+    [Zero, OneTer, One, OneBis]
+
+    A layer with two bases of different specificity:
+
+    >>> class Two(Base):
+    ...    __bases__ = (zero, one)
+    >>> two = Two()
+
+    Ordered by inverse specificity:
+
+    >>> order_by_bases([two, one, zero])
+    [Zero, One, Two]
+    >>> order_by_bases([zero, two, one])
+    [Zero, One, Two]
+    >>> order_by_bases([two, zero, one])
+    [Zero, One, Two]
+
+    Another layer with two bases of different specificity:
+
+    >>> class TwoBis(Base):
+    ...    __bases__ = (zero, one_bis)
+    >>> two_bis = TwoBis()
+
+    >>> order_by_bases([two, two_bis, one, zero])
+    [Zero, One, Two, TwoBis]
+    >>> order_by_bases([two_bis, two, one, zero])
+    [Zero, One, Two, TwoBis]
+
+    >>> order_by_bases([one_bis, two_bis, two, one, zero])
+    [Zero, One, OneBis, Two, TwoBis]
+
+    >>> class Three(Base):
+    ...    __bases__ = (two, one_bis)
+    >>> three = Three()
+
+    >>> order_by_bases([one_bis, two_bis, three, two, one, zero])
+    [Zero, One, OneBis, Two, TwoBis, Three]
+    """
+    named_layers = [(name_from_layer(layer), layer) for layer in layers]
+    named_layers.sort()
+    named_layers.reverse()
+    # Store layers along with their specificity measured by numbers of
+    # sublayers.
+    all_layers = {}
+    for name, layer in named_layers:
+        gathered = []
+        gather_layers(layer, gathered)
+        index = len(gathered)
+        some_layers = all_layers.setdefault(index, [])
+        some_layers.append(gathered)
+    keys = all_layers.keys()
+    keys.sort()
+    # Gather them all starting by the least specific.
+    gathered = []
+    for key in keys:
+        for some_layers in all_layers[key]:
+            gathered.extend(some_layers)
+    seen = {}
+    result = []
+    for layer in gathered:
+        if layer not in seen:
+            seen[layer] = 1
+            if layer in layers:
+                result.append(layer)
+    return result
+
+
+def gather_layers(layer, result):
+    if layer is not object:
+        result.append(layer)
+    for b in layer.__bases__:
+        gather_layers(b, result)

Modified: zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/runner.py
===================================================================
--- zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/runner.py	2011-03-01 09:45:09 UTC (rev 120628)
+++ zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/runner.py	2011-03-01 09:54:38 UTC (rev 120629)
@@ -29,6 +29,7 @@
 import traceback
 import unittest
 
+from zope.testing.testrunner.layerutils import order_by_bases, gather_layers
 from zope.testing.testrunner.find import import_name
 from zope.testing.testrunner.find import name_from_layer, _layer_name_cache
 from zope.testing.testrunner.refcount import TrackRefs
@@ -206,7 +207,7 @@
         Returns True if there where failures or False if all tests passed.
 
         """
-        setup_layers = {}
+        setup_layers = []
         layers_to_run = list(self.ordered_layers())
         should_resume = False
 
@@ -592,27 +593,32 @@
 def tear_down_unneeded(options, needed, setup_layers, optional=False):
     # Tear down any layers not needed for these tests. The unneeded layers
     # might interfere.
-    unneeded = [l for l in setup_layers if l not in needed]
-    unneeded = order_by_bases(unneeded)
-    unneeded.reverse()
-    output = options.output
-    for l in unneeded:
-        output.start_tear_down(name_from_layer(l))
-        t = time.time()
+    unneeded = set([l for l in setup_layers if l not in needed])
+    while unneeded:
+        l = setup_layers[-1]
+        if l not in unneeded:
+            raise ValueError('Unexpected layer teardown order.')
         try:
-            try:
-                if hasattr(l, 'tearDown'):
-                    l.tearDown()
-            except NotImplementedError:
-                output.tear_down_not_supported()
-                if not optional:
-                    raise CanNotTearDown(l)
-            else:
-                output.stop_tear_down(time.time() - t)
+            tear_down_layer(options, l, optional)
         finally:
-            del setup_layers[l]
+            setup_layers.pop()
+            unneeded.remove(l)
 
 
+def tear_down_layer(options, l, optional):
+    output = options.output
+    output.start_tear_down(name_from_layer(l))
+    t = time.time()
+    try:
+        if hasattr(l, 'tearDown'):
+            l.tearDown()
+    except NotImplementedError:
+        output.tear_down_not_supported()
+        if not optional:
+            raise CanNotTearDown(l)
+    else:
+        output.stop_tear_down(time.time() - t)
+
 cant_pm_in_subprocess_message = """
 Can't post-mortem debug when running a layer as a subprocess!
 Try running layer %r by itself.
@@ -645,15 +651,11 @@
                     raise
 
         output.stop_set_up(time.time() - t)
-        setup_layers[layer] = 1
+        setup_layers.append(layer)
 
 
 class TestResult(unittest.TestResult):
 
-    # Handle unexpected success as failure:
-    # https://bugs.launchpad.net/zope.testrunner/+bug/719369
-    addUnexpectedSuccess = None
-
     def __init__(self, options, tests, layer_name=None):
         unittest.TestResult.__init__(self)
         self.options = options
@@ -777,33 +779,6 @@
                              % (module_name, module_layer_name))
 
 
-def order_by_bases(layers):
-    """Order the layers from least to most specific (bottom to top)
-    """
-    named_layers = [(name_from_layer(layer), layer) for layer in layers]
-    named_layers.sort()
-    named_layers.reverse()
-    gathered = []
-    for name, layer in named_layers:
-        gather_layers(layer, gathered)
-    gathered.reverse()
-    seen = {}
-    result = []
-    for layer in gathered:
-        if layer not in seen:
-            seen[layer] = 1
-            if layer in layers:
-                result.append(layer)
-    return result
-
-
-def gather_layers(layer, result):
-    if layer is not object:
-        result.append(layer)
-    for b in layer.__bases__:
-        gather_layers(b, result)
-
-
 class FakeInputContinueGenerator:
 
     def readline(self):

Modified: zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/tests.py
===================================================================
--- zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/tests.py	2011-03-01 09:45:09 UTC (rev 120628)
+++ zope.testing/branches/gotcha-test-layers/src/zope/testing/testrunner/tests.py	2011-03-01 09:54:38 UTC (rev 120629)
@@ -194,6 +194,7 @@
             optionflags=doctest.ELLIPSIS+doctest.NORMALIZE_WHITESPACE),
         doctest.DocTestSuite('zope.testing.testrunner.options'),
         doctest.DocTestSuite('zope.testing.testrunner.find'),
+        doctest.DocTestSuite('zope.testing.testrunner.layerutils'),
         ]
 
     if sys.platform == 'win32':



More information about the Zope3-Checkins mailing list