Honour stdout on TestProgram more fully.

We were failing to pass it into the runner, and this causes hilarity
for child runners which then end up with sys.stdout in their test
  suite, rather than their stub streams.

Change-Id: I19984102547f92493f330059928f7e0b3897c38c
This commit is contained in:
Robert Collins
2014-08-24 17:05:39 +12:00
parent 7683940260
commit 07543a19b6
5 changed files with 48 additions and 12 deletions

6
NEWS
View File

@@ -10,6 +10,12 @@ NEXT
Changes
-------
* ``stdout`` is now correctly honoured on ``run.TestProgram`` - before the
runner objects would be created with no stdout parameter. If construction
fails, the previous parameter list is attempted, permitting compatibility
with Runner classes that don't accept stdout as a parameter.
(Robert Collins)
* The ``ExtendedToStreamDecorator`` now handles content objects with one less
packet - the last packet of the source content is sent with EOF set rather
than an empty packet with EOF set being sent after the last packet of the

View File

@@ -26,7 +26,7 @@ class TestCommand(Command):
def __init__(self, dist):
Command.__init__(self, dist)
self.runner = TestToolsTestRunner(sys.stdout)
self.runner = TestToolsTestRunner(stdout=sys.stdout)
def initialize_options(self):

View File

@@ -73,6 +73,8 @@ class TestToolsTestRunner(object):
:param stdout: Stream to use for stdout.
"""
self.failfast = failfast
if stdout is None:
stdout = sys.stdout
self.stdout = stdout
def list(self, test):
@@ -89,7 +91,7 @@ class TestToolsTestRunner(object):
def run(self, test):
"Run the given test case or test suite."
result = TextTestResult(
unicode_output_stream(sys.stdout), failfast=self.failfast)
unicode_output_stream(self.stdout), failfast=self.failfast)
result.startTestRun()
try:
return test.run(result)
@@ -185,6 +187,7 @@ class TestProgram(object):
argv = sys.argv
if stdout is None:
stdout = sys.stdout
self.stdout = stdout
self.exit = exit
self.failfast = failfast
@@ -224,7 +227,7 @@ class TestProgram(object):
runner.list(self.test)
else:
for test in iterate_tests(self.test):
stdout.write('%s\n' % test.id())
self.stdout.write('%s\n' % test.id())
def usageExit(self, msg=None):
if msg:
@@ -378,14 +381,22 @@ class TestProgram(object):
try:
testRunner = self.testRunner(verbosity=self.verbosity,
failfast=self.failfast,
buffer=self.buffer)
buffer=self.buffer,
stdout=self.stdout)
except TypeError:
# didn't accept the verbosity, buffer or failfast arguments
# didn't accept the verbosity, buffer, failfast or stdout arguments
# Try with the prior contract
try:
testRunner = self.testRunner()
testRunner = self.testRunner(verbosity=self.verbosity,
failfast=self.failfast,
buffer=self.buffer)
except TypeError:
# it is assumed to be a TestRunner instance
testRunner = self.testRunner
# Now try calling it with defaults
try:
testRunner = self.testRunner()
except TypeError:
# it is assumed to be a TestRunner instance
testRunner = self.testRunner
return testRunner

View File

@@ -61,8 +61,8 @@ class TestCommandTest(TestCase):
dist.cmdclass = {'test': TestCommand}
dist.command_options = {
'test': {'test_module': ('command line', 'testtools.runexample')}}
cmd = dist.reinitialize_command('test')
with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
cmd = dist.reinitialize_command('test')
dist.run_command('test')
self.assertThat(
stdout.getDetails()['stdout'].as_text(),
@@ -83,8 +83,8 @@ OK
'test': {
'test_suite': (
'command line', 'testtools.runexample.test_suite')}}
cmd = dist.reinitialize_command('test')
with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
cmd = dist.reinitialize_command('test')
dist.run_command('test')
self.assertThat(
stdout.getDetails()['stdout'].as_text(),

View File

@@ -13,9 +13,13 @@ import testtools
from testtools import TestCase, run
from testtools.compat import (
_b,
_u,
StringIO,
)
from testtools.matchers import Contains
from testtools.matchers import (
Contains,
MatchesRegex,
)
if fixtures:
@@ -235,12 +239,27 @@ testtools.resourceexample.TestFoo.test_foo
self.fail('a')
def test_b(self):
self.fail('b')
runner = run.TestToolsTestRunner(failfast=True)
with fixtures.MonkeyPatch('sys.stdout', stdout.stream):
runner = run.TestToolsTestRunner(failfast=True)
runner.run(TestSuite([Failing('test_a'), Failing('test_b')]))
self.assertThat(
stdout.getDetails()['stdout'].as_text(), Contains('Ran 1 test'))
def test_stdout_honoured(self):
self.useFixture(SampleTestFixture())
tests = []
out = StringIO()
exc = self.assertRaises(SystemExit, run.main,
argv=['prog', 'testtools.runexample.test_suite'],
stdout=out)
self.assertEqual((0,), exc.args)
self.assertThat(
out.getvalue(),
MatchesRegex(_u("""Tests running...
Ran 2 tests in \\d.\\d\\d\\ds
OK
""")))
def test_suite():