=== modified file 'CHANGES.txt' --- CHANGES.txt 2010-04-11 01:31:21 +0000 +++ CHANGES.txt 2010-04-11 02:17:01 +0000 @@ -4,6 +4,8 @@ 3.9.4 (unreleased) ================== +- LP #497871: Make testrunner run unit tests first. + - LP #399394: Added a ``--stop-on-error`` / ``--stop`` / ``-x`` option to the testrunner. === modified file 'src/zope/testing/testrunner/runner.py' --- src/zope/testing/testrunner/runner.py 2010-04-11 01:31:21 +0000 +++ src/zope/testing/testrunner/runner.py 2010-04-11 02:11:03 +0000 @@ -31,6 +31,7 @@ from zope.testing.testrunner.find import import_name from zope.testing.testrunner.find import name_from_layer, _layer_name_cache +from zope.testing.testrunner.layer import UnitTests from zope.testing.testrunner.refcount import TrackRefs from zope.testing.testrunner.options import get_options import zope.testing.testrunner.coverage @@ -784,6 +785,9 @@ gathered.reverse() seen = {} result = [] + if UnitTests in layers: + result.append(UnitTests) + gathered.remove(UnitTests) for layer in gathered: if layer not in seen: seen[layer] = 1 === modified file 'src/zope/testing/testrunner/tests.py' --- src/zope/testing/testrunner/tests.py 2010-04-06 02:02:54 +0000 +++ src/zope/testing/testrunner/tests.py 2010-04-11 02:10:41 +0000 @@ -163,8 +163,115 @@ sys.modules.update(test.globs['saved-sys-info'][2]) +class Test_order_by_bases(unittest.TestCase): + + def _callFUT(self, layers): + from zope.testing.testrunner.runner import order_by_bases + return order_by_bases(layers) + + def test_empty(self): + self.assertEqual(list(self._callFUT(())), []) + + def test_w_layer_no_bases(self): + class NoBases(object): + pass + result = self._callFUT([NoBases]) + self.assertEqual(len(result), 1) + self.failUnless(result[0] is NoBases) + + def test_w_layer_w_bases(self): + class OneBase(object): + pass + class AnotherBase(object): + pass + class Derived(OneBase, AnotherBase): + pass + result = self._callFUT([OneBase, AnotherBase, Derived]) + self.assertEqual(len(result), 3) + self.failUnless(result[0] is AnotherBase) + self.failUnless(result[1] is OneBase) + self.failUnless(result[2] is Derived) + + def test_unit_tests_first(self): + from zope.testing.testrunner.layer import UnitTests + class ALayer(object): + __module__ = 'a.b.c' + pass + class ZLayer(object): + __module__ = 'x.y.z' + pass + result = self._callFUT([ZLayer, ALayer, UnitTests]) + self.assertEqual(len(result), 3) + self.failUnless(result[0] is UnitTests) + self.failUnless(result[1] is ALayer) + self.failUnless(result[2] is ZLayer) + result = self._callFUT([UnitTests, ALayer, ZLayer]) + self.assertEqual(len(result), 3) + self.failUnless(result[0] is UnitTests) + self.failUnless(result[1] is ALayer) + self.failUnless(result[2] is ZLayer) + result = self._callFUT([ALayer, ZLayer, UnitTests]) + self.assertEqual(len(result), 3) + self.failUnless(result[0] is UnitTests) + self.failUnless(result[1] is ALayer) + self.failUnless(result[2] is ZLayer) + +class Test_gather_layers(unittest.TestCase): + + def _callFUT(self, layer, result): + from zope.testing.testrunner.runner import gather_layers + return gather_layers(layer, result) + + def test_w_object(self): + result = [] + self._callFUT(object, result) + self.assertEqual(len(result), 0) + + def test_w_layer_no_bases(self): + class NoBases(object): + pass + result = [] + self._callFUT(NoBases, result) + self.assertEqual(len(result), 1) + self.failUnless(result[0] is NoBases) + + def test_w_layer_w_bases(self): + class OneBase(object): + pass + class AnotherBase(object): + pass + class Derived(OneBase, AnotherBase): + pass + result = [] + self._callFUT(Derived, result) + self.assertEqual(len(result), 3) + self.failUnless(result[0] is Derived) + self.failUnless(result[1] is OneBase) + self.failUnless(result[2] is AnotherBase) + + def test_w_layer_w_diamond(self): + class Base(object): + pass + class Ammonia(Base): + pass + class Lye(Base): + pass + class Boom(Ammonia, Lye): + pass + result = [] + self._callFUT(Boom, result) + self.assertEqual(len(result), 5) + self.failUnless(result[0] is Boom) + self.failUnless(result[1] is Ammonia) + self.failUnless(result[2] is Base) + self.failUnless(result[3] is Lye) + self.failUnless(result[4] is Base) + + def test_suite(): suites = [ + unittest.makeSuite(Test_order_by_bases), + unittest.makeSuite(Test_gather_layers), doctest.DocFileSuite( 'testrunner-arguments.txt', 'testrunner-coverage.txt',