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:
6
NEWS
6
NEWS
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user