Skip to content

Commit

Permalink
improved subunit support:
Browse files Browse the repository at this point in the history
properly report how many tests are executed if success, otherwise how
many error/fail tests
  • Loading branch information
tp committed Jun 17, 2010
1 parent 74d8970 commit 9a81f0d
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 13 deletions.
32 changes: 22 additions & 10 deletions master/buildbot/process/subunitlogobserver.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

from unittest import TestResult
from buildbot.process import buildstep

class DiscardStream:
"""A trivial thunk used to discard passthrough content."""

def write(self, bytes):
pass

from StringIO import StringIO

class SubunitLogObserver(buildstep.LogLineObserver, TestResult):
"""Observe a log that may contain subunit output.
Expand All @@ -25,17 +19,30 @@ def __init__(self):
except ImportError:
raise ImportError("subunit is not importable, but is required for "
"SubunitLogObserver support.")
self.protocol = TestProtocolServer(self, DiscardStream())
self.warningio = StringIO()
self.protocol = TestProtocolServer(self, self.warningio)
self.skips = []
self.seen_tags = set() #don't yet know what tags does in subunit

def outLineReceived(self, line):
"""Process a received line."""
"""Process a received stdout line."""
# Impedance mismatch: subunit wants lines, observers get lines-no\n
self.protocol.lineReceived(line + '\n')

def errLineReceived(self, line):
"""same for stderr line."""
self.protocol.lineReceived(line + '\n')

def startTest(self, test):
TestResult.startTest(self, test)
self.step.setProgress('tests', self.testsRun)

def addSkip(self, test, detail):
if hasattr(TestResult,'addSkip'):
TestResult.addSkip(self, test, detail)
else:
self.skips.append((test, detail))

def addError(self, test, err):
TestResult.addError(self, test, err)
self.issue()
Expand All @@ -46,7 +53,12 @@ def addFailure(self, test, err):

def issue(self):
"""An issue - failing, erroring etc test."""
self.step.setProgress('tests failed', len(self.failures) + len(self.errors))
self.step.setProgress('tests failed', len(self.failures) +
len(self.errors))

def tags(self, new_tags, gone_tags):
"""Accumulate the seen tags."""
self.seen_tags.update(new_tags)

# this used to be referenced here, so we keep a link for old time's sake
import buildbot.steps.subunit
Expand Down
70 changes: 67 additions & 3 deletions master/buildbot/steps/subunit.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,15 +1,79 @@

from buildbot.steps.shell import ShellCommand
from buildbot.status.builder import SUCCESS, FAILURE, WARNINGS, SKIPPED

class SubunitShellCommand(ShellCommand):
"""A ShellCommand that sniffs subunit output.
Ideally not needed, and thus here to be trivially deleted. See issue #615
"""

def __init__(self, *args, **kwargs):
ShellCommand.__init__(self, *args, **kwargs)
# importing here gets around an import loop
from buildbot.process import subunitlogobserver
self.addLogObserver('stdio', subunitlogobserver.SubunitLogObserver())
self.ioObverser = subunitlogobserver.SubunitLogObserver()
self.addLogObserver('stdio', self.ioObverser)
self.progressMetrics = self.progressMetrics + ('tests', 'tests failed')
def commandComplete(self, cmd):
# figure out all statistics about the run
ob = self.ioObverser
failures = len(ob.failures)
errors = len(ob.errors)
skips = len(ob.skips)
total = ob.testsRun

count = failures + errors

text = []
text2 = ""

if not count:
results = SUCCESS
if total:
text += ["%d %s" % \
(total,
total == 1 and "test" or "tests"),
"passed"]
else:
text += ["no tests", "run"]
else:
results = FAILURE
text.append("tests")
if failures:
text.append("%d %s" % \
(failures,
failures == 1 and "failure" or "failures"))
if errors:
text.append("%d %s" % \
(errors,
errors == 1 and "error" or "errors"))
text2 = "%d tes%s" % (count, (count == 1 and 't' or 'ts'))


if skips:
text.append("%d %s" % (skips,
skips == 1 and "skip" or "skips"))

#TODO: expectedFailures/unexpectedSuccesses

self.results = results
self.text = text
self.text2 = [text2]

def evaluateCommand(self, cmd):
return self.results

def createSummary(self, loog):
ob = self.ioObverser
problems = ""
for test, err in ob.errors + ob.failures:
problems += "%s\n%s" % (test, err)
if problems:
self.addCompleteLog("problems", problems)
warnings = ob.warningio.getvalue()
if warnings:
self.addCompleteLog("warnings", warnings)

def getText(self, cmd, results):
return self.text
def getText2(self, cmd, results):
return self.text2

0 comments on commit 9a81f0d

Please sign in to comment.