[pypy-svn] r52706 - in pypy/build/bot: . test

fijal at codespeak.net fijal at codespeak.net
Tue Mar 18 21:33:38 CET 2008


Author: fijal
Date: Tue Mar 18 21:33:37 2008
New Revision: 52706

Modified:
   pypy/build/bot/pypy_status.py
   pypy/build/bot/pypybuilders.py
   pypy/build/bot/test/test_mysession.py
Log:
(exarkun, fijal) Create a custom view.


Modified: pypy/build/bot/pypy_status.py
==============================================================================
--- pypy/build/bot/pypy_status.py	(original)
+++ pypy/build/bot/pypy_status.py	Tue Mar 18 21:33:37 2008
@@ -8,6 +8,18 @@
 from buildbot.interfaces import LOG_CHANNEL_STDOUT
 from buildbot.status.web.base import ICurrentBox, HtmlResource, map_branches, build_get_class
 
+class LogMixin:
+    def getLog(self, build, name):
+        for log in build.getLogs():
+            if log.name.endswith(name):
+                stdout = ''.join(
+                    log.getChunks(channels=[LOG_CHANNEL_STDOUT],
+                                  onlyText=True))
+                return stdout
+        return ''
+
+
+
 def body(self, request):
     status = self.getStatus(request)
     builderNames = status.getBuilderNames()
@@ -88,17 +100,26 @@
         testResultsTable])
 
 
-class RecentlyFailingTests(HtmlResource):
-    oldBuildCount = 10
+class Summary(HtmlResource, LogMixin):
+    def body(self, request):
+        failedTests = {}
+        status = self.getStatus(request)
+        for builderName in status.getBuilderNames():
+            builder = status.getBuilder(builderName)
+            for build in builder.generateFinishedBuilds(branches=[None],
+                                                        num_builds=1):
+                log = self.getLog(build, "failedtotal.log")
+                testNames = log.splitlines()
+                failedTests.update(dict.fromkeys(testNames))
+        return flatten(tags.div[[
+            tags.div[tags.a(href="faillog/" + test,
+                            style='color: red; font-weight: bold')['F'],
+                     ' ', test]
+            for test in failedTests]])
 
-    def getLog(self, build, name):
-        for log in build.getLogs():
-            if log.name.endswith(name):
-                stdout = ''.join(
-                    log.getChunks(channels=[LOG_CHANNEL_STDOUT],
-                                  onlyText=True))
-                return stdout
-        return ''
+
+class RecentlyFailingTests(HtmlResource, LogMixin):
+    oldBuildCount = 10
 
     def body(self, request):
         # Avoid having to restart the master to manually exercise each code

Modified: pypy/build/bot/pypybuilders.py
==============================================================================
--- pypy/build/bot/pypybuilders.py	(original)
+++ pypy/build/bot/pypybuilders.py	Tue Mar 18 21:33:37 2008
@@ -6,7 +6,9 @@
 from buildbot.steps.transfer import FileUpload, FileDownload
 from buildbot.steps.python_twisted import Trial
 
-from netstring import netstringparser
+from bot.netstring import netstringparser
+from twisted.spread.banana import decode, encode
+from twisted.spread.jelly import unjelly, jelly
 
 class Translate(ShellCommand):
     name = "translate"
@@ -23,6 +25,20 @@
         self.command = self.command + translationArgs + [self.translationTarget] + targetArgs
         ShellCommand.__init__(self, workdir, *a, **kw)
 
+def create_summary(stdout, logcreator):
+    stuff = list(netstringparser(stdout))
+    events = [(name, unjelly(decode(item))) for name, item in
+              zip(*[iter(stuff)]*2)]
+    failed_names = []
+    for name, event in events:
+        if name == 'ReceivedItemOutcome':
+            (tp, name), outcome = event
+            if outcome.excinfo:
+                # failed test
+                fullname = '.'.join(name)
+                logcreator(fullname, encode(jelly(outcome.excinfo)))
+                failed_names.append(fullname)
+    logcreator('failedtotal.log', "\n".join(failed_names))
 
 class PyTest(ShellCommand):
     name = "py.test pypy"
@@ -51,19 +67,14 @@
 
 
     def createSummary(self, log):
-        """
-        43:foo.test.test_foo.py.AppTestFoo.().test_foo
-        6:passed
-        43:foo.test.test_foo.py.AppTestFoo.().test_bar
-        6:failed
-        17:assert foo == bar
-        43:foo.test.test_foo.py.AppTestFoo.().test_baz
-        7:skipped
-        """
-        stdout = ''.join(
-            log.getChunks(channels=[LOG_CHANNEL_STDOUT],
-                          onlyText=True))
+        stdout = ''.join(log.getChunks(channels=[LOG_CHANNEL_STDOUT],
+                                       onlyText=True))
+        create_summary(stdout, self.addCompleteLog)
+        return
 
+
+
+        
         resultLists = {
             'passed': [],
             'failed': [],

Modified: pypy/build/bot/test/test_mysession.py
==============================================================================
--- pypy/build/bot/test/test_mysession.py	(original)
+++ pypy/build/bot/test/test_mysession.py	Tue Mar 18 21:33:37 2008
@@ -5,6 +5,8 @@
 from twisted.spread.banana import decode
 from twisted.spread.jelly import unjelly
 from bot import netstring
+from bot.pypybuilders import create_summary
+from bot.pypy_status import Summary
 
 testfile = py.code.Source("""
 def test_one():
@@ -14,6 +16,52 @@
     1/0
 """)
 
+
+class MockLog(object):
+    def __init__(self, name, contents):
+        self.name = name
+        self.contents = contents
+
+    def getChunks(self, channels, onlyText):
+        return [self.contents]
+
+
+class MockBuild(object):
+    def __init__(self, logs):
+        self.logs = logs
+
+    def getLogs(self):
+        return iter(self.logs)
+
+
+class MockBuilder(object):
+    def __init__(self, name, builds):
+        self.name = name
+        self.builds = builds
+
+    def generateFinishedBuilds(self, branches, num_builds):
+        return iter(self.builds)
+
+
+class MockStatus(object):
+    def __init__(self, builders):
+        self.builders = builders
+
+    def getBuilderNames(self):
+        return iter(self.builders)
+
+    def getBuilder(self, name):
+        return self.builders[name]
+
+
+class MockSummary(Summary):
+    def __init__(self, status):
+        self.status = status
+
+    def getStatus(self, request):
+        return self.status
+
+
 class XTestReporter(MyReporter):
     def __init__(self, *args, **kwds):
         out = kwds.pop('stringio')
@@ -21,7 +69,7 @@
         self.out = out
         out.write("\n")
 
-def test_mysession():
+def _create_output():
     tmpdir = py.test.ensuretemp('mysession')
     fobj = tmpdir.ensure('test_xxx.py')
     fobj.write(testfile)
@@ -29,7 +77,11 @@
     session = config.initsession()
     stringio = StringIO()
     session.main(XTestReporter(config, [], stringio=stringio))
-    stuff = list(netstring.netstringparser(stringio.getvalue()))
+    return stringio.getvalue()
+
+def test_mysession():
+    output = _create_output()
+    stuff = list(netstring.netstringparser(output))
     events = [(name, unjelly(decode(item))) for name, item in
               zip(*[iter(stuff)]*2)]
     assert events[0][0] == 'TestStarted'
@@ -46,5 +98,21 @@
     assert outcomes[1][1][1].excinfo.typename == 'ZeroDivisionError'
     assert outcomes[1][1][1].excinfo.traceback[0].lineno == 5
 
-
-    
+def test_createsummary():
+    output = _create_output()
+    logger = {}
+    create_summary(output, logger.__setitem__)
+    assert logger['failedtotal.log'] == 'mysession.test_xxx.py.test_two'
+    excinfo = unjelly(decode(logger['mysession.test_xxx.py.test_two']))
+    assert excinfo.typename == 'ZeroDivisionError'
+
+def test_viewsummary():
+    output = _create_output()
+    logger = {}
+    create_summary(output, logger.__setitem__)
+    build = MockBuild([MockLog(name, logger[name]) for name in logger])
+    builder = MockBuilder("tests", [build])
+    status = MockStatus({builder.name: builder})
+    mocksum = MockSummary(status)
+    view = mocksum.body(None)
+    assert view == '<div><div><a style="color: red; font-weight: bold" href="faillog/mysession.test_xxx.py.test_two">F</a> mysession.test_xxx.py.test_two</div></div>'



More information about the Pypy-commit mailing list