diff --git a/master/buildbot/steps/subunit.py b/master/buildbot/steps/subunit.py index 1bbacb72a8c..f4f0ca19c4c 100644 --- a/master/buildbot/steps/subunit.py +++ b/master/buildbot/steps/subunit.py @@ -24,11 +24,15 @@ class SubunitShellCommand(ShellCommand): def __init__(self, failureOnNoTests=False, *args, **kwargs): ShellCommand.__init__(self, *args, **kwargs) self.failureOnNoTests = failureOnNoTests + self.addFactoryArguments(failureOnNoTests=failureOnNoTests) + # importing here gets around an import loop from buildbot.process import 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 @@ -49,10 +53,9 @@ def commandComplete(self, cmd): (total, total == 1 and "test" or "tests"), "passed"] - elif self.failureOnNoTests: - results = FAILURE - text += ["no test is found"] else: + if self.failureOnNoTests: + results = FAILURE text += ["no tests", "run"] else: results = FAILURE @@ -65,7 +68,7 @@ def commandComplete(self, cmd): text.append("%d %s" % \ (errors, errors == 1 and "error" or "errors")) - text2 = "%d tes%s" % (count, (count == 1 and 't' or 'ts')) + text2 = "%d %s" % (count, (count == 1 and 'test' or 'tests')) if skips: diff --git a/master/buildbot/test/unit/test_steps_subunit.py b/master/buildbot/test/unit/test_steps_subunit.py new file mode 100644 index 00000000000..a639b071a58 --- /dev/null +++ b/master/buildbot/test/unit/test_steps_subunit.py @@ -0,0 +1,86 @@ +# This file is part of Buildbot. Buildbot is free software: you can +# redistribute it and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright Buildbot Team Members + +import mock +import StringIO +from zope.interface import implements +from twisted.trial import unittest +from buildbot import interfaces +from buildbot.steps import subunit +from buildbot.process import subunitlogobserver +from buildbot.status.results import SUCCESS, FAILURE +from buildbot.test.fake.remotecommand import ExpectShell +from buildbot.test.util import steps + +class StubLogObserver(mock.Mock): + implements(interfaces.ILogObserver) + +class TestSetPropertiesFromEnv(steps.BuildStepMixin, unittest.TestCase): + + def setUp(self): + self.logobserver = StubLogObserver() + self.logobserver.failures = [] + self.logobserver.errors = [] + self.logobserver.skips = [] + self.logobserver.testsRun = 0 + self.logobserver.warningio = StringIO.StringIO() + self.patch(subunitlogobserver, 'SubunitLogObserver', + lambda : self.logobserver) + return self.setUpBuildStep() + + def tearDown(self): + return self.tearDownBuildStep() + + def test_empty(self): + self.setupStep(subunit.SubunitShellCommand(command='test')) + self.expectCommands( + ExpectShell(workdir='wkdir', usePTY='slave-config', + command="test") + + 0 + ) + self.expectOutcome(result=SUCCESS, + status_text=["shell", "no tests", "run"]) + return self.runStep() + + def test_empty_error(self): + self.setupStep(subunit.SubunitShellCommand(command='test', + failureOnNoTests=True)) + self.expectCommands( + ExpectShell(workdir='wkdir', usePTY='slave-config', + command="test") + + 0 + ) + self.expectOutcome(result=FAILURE, + status_text=["shell", "no tests", "run"]) + return self.runStep() + + def test_warnings(self): + self.setupStep(subunit.SubunitShellCommand(command='test')) + self.expectCommands( + ExpectShell(workdir='wkdir', usePTY='slave-config', + command="test") + + 0 + ) + self.logobserver.warnings.append('not quite up to snuff (list)') + self.logobserver.warningio.write('not quite up to snuff (io)\n') + self.logobserver.testsRun = 3 + self.expectOutcome(result=SUCCESS, # N.B. not WARNINGS + status_text=["shell", "3 tests", "passed"]) + # note that the warnings list is ignored.. + self.expectLogfile('warnings', 'not quite up to snuff (io)\n') + return self.runStep() + + # TODO: test text2 generation? + # TODO: tests are represented as objects?!