[py-svn] r61721 - py/branch/pytestplugin/py/test/plugin

hpk at codespeak.net hpk at codespeak.net
Wed Feb 11 13:19:12 CET 2009


Author: hpk
Date: Wed Feb 11 13:19:12 2009
New Revision: 61721

Added:
   py/branch/pytestplugin/py/test/plugin/pytest_unittest.py   (contents, props changed)
Modified:
   py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py
   py/branch/pytestplugin/py/test/plugin/pytest_pytester.py
Log:
port unittest-support conftest to become a plugin 
add a bit of plugin testing support code 


Modified: py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_plugintester.py	Wed Feb 11 13:19:12 2009
@@ -51,7 +51,7 @@
         while methods:
             name, method = methods.popitem()
             if name not in hooks:
-                print "definition of unknown hook: %s" % name 
+                print "found unknown hook: %s" % name 
                 fail = True
             else:
                 hook = hooks[name]
@@ -112,6 +112,10 @@
             function has been executed (i.e. pyfuncitem.execute() returns). 
         """ 
 
+    def pytest_pymodule_makeitem(self, modcol, name, obj):
+        """ return custom item/collector or None.  """
+
+
     # from pytest_terminal plugin
     def pytest_report_teststatus(self, event):
         """ return shortletter and verbose word. """

Modified: py/branch/pytestplugin/py/test/plugin/pytest_pytester.py
==============================================================================
--- py/branch/pytestplugin/py/test/plugin/pytest_pytester.py	(original)
+++ py/branch/pytestplugin/py/test/plugin/pytest_pytester.py	Wed Feb 11 13:19:12 2009
@@ -4,6 +4,9 @@
 
 import py
 
+from py.__.test import event
+
+
 class RunResult:
     def __init__(self, ret, outlines, errlines):
         self.ret = ret
@@ -35,6 +38,15 @@
         if not impname in self._plugins:
             self._plugins.append(impname)
 
+    def parse_and_run(self, *args):
+        config = self.parseconfig(*args)
+        config.pluginmanager.configure(config)
+        session = config.initsession()
+        sorter = EventSorter(config, session)
+        session.main()
+        config.pluginmanager.unconfigure(config)
+        return sorter
+
     def parseconfig(self, *args):
         return py.test.config._reparse(list(args))
 
@@ -186,3 +198,63 @@
             tmpdir = py.test.ensuretemp("_".join(pyfuncitem.listnames()))
             fstester = FSTester(tmpdir)
             return fstester, None
+
+class EventSorter(object):
+    def __init__(self, config, session=None):
+        self.config = config
+        self.session = session
+        self.cls2events = d = {}
+        def app(event):
+            print "[event]", event
+            for cls in py.std.inspect.getmro(event.__class__):
+                if cls is not object: 
+                    d.setdefault(cls, []).append(event) 
+        session.bus.subscribe(app)
+
+    def get(self, cls):
+        return self.cls2events.get(cls, [])
+
+    def listoutcomes(self):
+        passed = []
+        skipped = []
+        failed = []
+        for ev in self.get(event.ItemTestReport):
+            if ev.passed: 
+                passed.append(ev) 
+            elif ev.skipped: 
+                skipped.append(ev) 
+            elif ev.failed:
+                failed.append(ev) 
+        return passed, skipped, failed 
+
+    def countoutcomes(self):
+        return map(len, self.listoutcomes())
+
+    def assertoutcome(self, passed=0, skipped=0, failed=0):
+        realpassed, realskipped, realfailed = self.listoutcomes()
+        assert passed == len(realpassed)
+        assert skipped == len(realskipped)
+        assert failed == len(realfailed)
+
+    def getfailedcollections(self):
+        l = []
+        for ev in self.get(event.CollectionReport):
+            if ev.failed:
+               l.append(ev) 
+        return l
+
+    def getreport(self, inamepart): 
+        """ return a testreport whose dotted import path matches """
+        __tracebackhide__ = True
+        l = []
+        for rep in self.get(event.ItemTestReport):
+            if inamepart in rep.colitem.listnames():
+                l.append(rep)
+        if not l:
+            raise ValueError("could not find test report matching %r: no test reports at all!" %
+                (inamepart,))
+        if len(l) > 1:
+            raise ValueError("found more than one testreport matching %r: %s" %(
+                             inamepart, l))
+        return l[0]
+            

Added: py/branch/pytestplugin/py/test/plugin/pytest_unittest.py
==============================================================================
--- (empty file)
+++ py/branch/pytestplugin/py/test/plugin/pytest_unittest.py	Wed Feb 11 13:19:12 2009
@@ -0,0 +1,123 @@
+"""
+automatically collect and run traditional "unittest.py" style tests. 
+
+you can mix unittest TestCase subclasses and 
+py.test style tests in one test module. 
+
+XXX consider user-specified test_suite() 
+
+this code is somewhat derived from Guido Wesdorps 
+
+    http://johnnydebris.net/svn/projects/py_unittest
+
+$HeadURL: https://codespeak.net/svn/py/branch/pytestplugin/contrib/py_unittest/conftest.py $
+$Id: conftest.py 60979 2009-01-14 22:29:32Z hpk $
+"""
+import py
+
+class Unittest:
+    """ Plugin for discovering and integrating traditional Python Unittest tests. 
+    """
+    def pytest_pymodule_makeitem(self, modcol, name, obj):
+        if py.std.inspect.isclass(obj) and issubclass(obj, py.std.unittest.TestCase):
+            return UnitTestCase(name, parent=modcol)
+
+class UnitTestCase(py.test.collect.Class):
+    def collect(self):
+        return [UnitTestCaseInstance("()", self)]
+
+    def setup(self):
+        pass
+
+    def teardown(self):
+        pass
+
+_dummy = object()
+class UnitTestCaseInstance(py.test.collect.Instance):
+    def collect(self):
+        loader = py.std.unittest.TestLoader()
+        names = loader.getTestCaseNames(self.obj.__class__)
+        l = []
+        for name in names:
+            callobj = getattr(self.obj, name)
+            if callable(callobj):
+                l.append(UnitTestFunction(name, parent=self))
+        return l
+
+    def _getobj(self):
+        x = self.parent.obj
+        return self.parent.obj(methodName='run')
+        
+class UnitTestFunction(py.test.collect.Function):
+    def __init__(self, name, parent, args=(), obj=_dummy, sort_value=None):
+        super(UnitTestFunction, self).__init__(name, parent)
+        self._args = args
+        if obj is not _dummy:
+            self._obj = obj
+        self._sort_value = sort_value
+
+    def runtest(self):
+        target = self.obj
+        args = self._args
+        target(*args)
+
+    def setup(self):
+        instance = self.obj.im_self
+        instance.setUp()
+
+    def teardown(self):
+        instance = self.obj.im_self
+        instance.tearDown()
+
+
+def test_generic(plugintester):
+    plugintester.apicheck()
+
+def test_simple_unittest(fstester):
+    test_one = fstester.makepyfile(test_one="""
+        import unittest
+        pytest_plugins = "pytest_unittest" # XXX 
+        class MyTestCase(unittest.TestCase):
+            def testpassing(self):
+                self.assertEquals('foo', 'foo')
+            def test_failing(self):
+                self.assertEquals('foo', 'bar')
+    """)
+    sorter = fstester.parse_and_run(test_one)
+    assert sorter.getreport("testpassing").passed
+    assert sorter.getreport("test_failing").failed 
+
+def test_setup(fstester):
+    test_one = fstester.makepyfile(test_two="""
+        import unittest
+        pytest_plugins = "pytest_unittest" # XXX 
+        class MyTestCase(unittest.TestCase):
+            def setUp(self):
+                self.foo = 1
+            def test_setUp(self):
+                self.assertEquals(1, self.foo)
+    """)
+    sorter = fstester.parse_and_run(test_one)
+    rep = sorter.getreport("test_setUp")
+    assert rep.passed
+
+def test_teardown(fstester):
+    testpath = fstester.makepyfile(test_three="""
+        import unittest
+        pytest_plugins = "pytest_unittest" # XXX 
+        class MyTestCase(unittest.TestCase):
+            l = []
+            def test_one(self):
+                pass
+            def tearDown(self):
+                self.l.append(None)
+        class Second(unittest.TestCase):
+            def test_check(self):
+                self.assertEquals(MyTestCase.l, [None])
+    """)
+    sorter = fstester.parse_and_run(testpath)
+    passed, skipped, failed = sorter.countoutcomes()
+    assert passed + skipped + failed == 2
+    assert failed == 0, failed
+    assert passed == 2
+



More information about the pytest-commit mailing list