[Python-Dev] Avoiding cascading test failures

Alexandre Vassalotti alexandre at peadrop.com
Sun Aug 26 02:23:02 CEST 2007


On 8/25/07, Gregory P. Smith <greg at krypto.org> wrote:
> I like this idea.

Yay! Now, I ain't the only one. ;)

> Be sure to have an option to ignore dependancies and run all tests.

Yes, I planned to add a such option.

> Also when skipping tests because a depedancy failed have unittest
> print out an indication that a test was skipped due to a dependancy
> rather than silently running fewer tests.  Otherwise it could be
> deceptive and appear that only one test was affected.

However, that was never planned.

I added the ignore_dependencies option. Also, I fixed the sub-optimal
dependency resolution algorithm that was in my original example
implementation.

-- Alexandre

--- dep.py.old  2007-08-25 19:54:27.000000000 -0400
+++ dep.py      2007-08-25 20:02:55.000000000 -0400
@@ -2,8 +2,9 @@
 class CycleError(Exception):
     pass

+class TestGraph:

-class TestCase:
+    ignore_dependencies = False

     def __init__(self):
         self.graph = {}
@@ -19,16 +20,16 @@
         graph = self.graph
         toskip = set()
         msgs = []
-        while graph:
+        if self.ignore_dependencies:
+            for test in graph:
+                graph[test].clear()
             # find tests without any pending dependencies
-            source = [test for test, deps in graph.items() if not deps]
-            if not source:
-                raise CycleError
-            for testname in source:
+        queue = [test for test, deps in graph.items() if not deps]
+        while queue:
+            testname = queue.pop()
                 if testname in toskip:
                     msgs.append("%s... skipped" % testname)
-                    resolvedeps(graph, testname)
-                    del graph[testname]
+                queue.extend(resolve(graph, testname))
                     continue
                 test = getattr(self, testname)
                 try:
@@ -42,8 +43,9 @@
                 else:
                     msgs.append("%s... ok" % testname)
                 finally:
-                    resolvedeps(graph, testname)
-                    del graph[testname]
+                queue.extend(resolve(graph, testname))
+        if graph:
+            raise CycleError
         for msg in sorted(msgs):
             print(msg)

@@ -60,10 +62,15 @@
             rdeps.update(getrevdeps(graph, x))
     return rdeps

- def resolvedeps(graph, testname):
+def resolve(graph, testname):
+    toqueue = []
     for test in graph:
         if testname in graph[test]:
             graph[test].remove(testname)
+            if not graph[test]:
+                toqueue.append(test)
+    del graph[testname]
+    return toqueue

 def depends(*args):
     def decorator(test):
@@ -75,7 +82,9 @@
     return decorator


-class MyTest(TestCase):
+class MyTest(TestGraph):
+
+    ignore_dependencies = True

    @depends('test_foo')
    def test_nah(self):
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dep.py
Type: text/x-python
Size: 2884 bytes
Desc: not available
Url : http://mail.python.org/pipermail/python-dev/attachments/20070825/df266f1e/attachment.py 


More information about the Python-Dev mailing list