diff options
author | Robert Collins <robertc@robertcollins.net> | 2010-01-08 21:57:03 +1100 |
---|---|---|
committer | Robert Collins <robertc@robertcollins.net> | 2010-01-08 21:57:03 +1100 |
commit | 68cb743c43a74c0473b6f6d0ccf9b77a85bab39b (patch) | |
tree | 27fcae5a3f0763ce84157eefecf61ac8d2851e28 | |
parent | 0d7c3c2904fac03989f3b0c2bd7affcc86a6b9bc (diff) | |
download | testrepository-git-68cb743c43a74c0473b6f6d0ccf9b77a85bab39b.tar.gz |
Add ui.output_results().
-rw-r--r-- | testrepository/tests/test_ui.py | 10 | ||||
-rw-r--r-- | testrepository/tests/ui/test_cli.py | 28 | ||||
-rw-r--r-- | testrepository/ui/__init__.py | 19 | ||||
-rw-r--r-- | testrepository/ui/cli.py | 33 | ||||
-rw-r--r-- | testrepository/ui/model.py | 3 |
5 files changed, 93 insertions, 0 deletions
diff --git a/testrepository/tests/test_ui.py b/testrepository/tests/test_ui.py index 7a243fb..67352ce 100644 --- a/testrepository/tests/test_ui.py +++ b/testrepository/tests/test_ui.py @@ -82,6 +82,16 @@ class TestUIContract(ResourcedTestCase): ui.set_command(cmd) self.assertRaises(KeyError, ui.iter_streams, 'subunit') + def test_output_results(self): + # output_results can be called and takes a thing that can be 'run'. + ui = self.ui_factory() + cmd = commands.Command(ui) + ui.set_command(cmd) + class Case(ResourcedTestCase): + def method(self): + pass + ui.output_results(Case('method')) + def test_output_values(self): # output_values can be called and takes a list of things to output. ui = self.ui_factory() diff --git a/testrepository/tests/ui/test_cli.py b/testrepository/tests/ui/test_cli.py index 09d0387..031ec53 100644 --- a/testrepository/tests/ui/test_cli.py +++ b/testrepository/tests/ui/test_cli.py @@ -14,8 +14,11 @@ """Tests for UI support logic and the UI contract.""" +import doctest from cStringIO import StringIO +from testtools.matchers import DocTestMatches + from testrepository import commands from testrepository.ui import cli from testrepository.tests import ResourcedTestCase @@ -51,6 +54,31 @@ class TestCLIUI(ResourcedTestCase): ui.set_command(cmd) self.assertEqual('/nowhere/', ui.here) + def test_outputs_results_to_stdout(self): + stdout = StringIO() + stdin = StringIO() + stderr = StringIO() + ui = cli.UI([], stdin, stdout, stderr) + cmd = commands.Command(ui) + ui.set_command(cmd) + class Case(ResourcedTestCase): + def method(self): + self.fail('quux') + ui.output_results(Case('method')) + self.assertThat(stdout.getvalue(),DocTestMatches( + """====================================================================== +FAIL: testrepository.tests.ui.test_cli.Case.method +---------------------------------------------------------------------- +Text attachment: traceback +------------ +Traceback (most recent call last): +... + File "...test_cli.py", line ..., in method + self.fail(\'quux\') +AssertionError: quux +------------ +""", doctest.ELLIPSIS)) + def test_outputs_values_to_stdout(self): stdout = StringIO() stdin = StringIO() diff --git a/testrepository/ui/__init__.py b/testrepository/ui/__init__.py index 4226b74..74bd349 100644 --- a/testrepository/ui/__init__.py +++ b/testrepository/ui/__init__.py @@ -73,6 +73,25 @@ class AbstractUI(object): """Helper for iter_streams which subclasses should implement.""" raise NotImplementedError(self._iter_streams) + def output_values(self, values): + """Show values to the user. + + :param values: An iterable of (label, value). + """ + raise NotImplementedError(self.output_values) + + def output_results(self, suite_or_test): + """Show suite_or_test to the user by 'running' it. + + This expects the run to be fast/cheap. + + :param suite_or_test: A suite or test to show to the user. This should + obey the 'TestCase' protocol - it should have a method run(result) + that causes all the tests contained in the object to be handed to + the result object. + """ + raise NotImplementedError(self.output_results) + def set_command(self, cmd): """Inform the UI what command it is running. diff --git a/testrepository/ui/cli.py b/testrepository/ui/cli.py index 2a704d9..d5f630c 100644 --- a/testrepository/ui/cli.py +++ b/testrepository/ui/cli.py @@ -17,8 +17,33 @@ from optparse import OptionParser import os +import testtools + from testrepository import ui +class CLITestResult(testtools.TestResult): + """A TestResult for the CLI.""" + + def __init__(self, stream): + """Construct a CLITestResult writing to stream.""" + super(CLITestResult, self).__init__() + self.stream = stream + self.sep1 = '=' * 70 + '\n' + self.sep2 = '-' * 70 + '\n' + + def _show_list(self, label, error_list): + for test, output in error_list: + self.stream.write(self.sep1) + self.stream.write("%s: %s\n" % (label, test.id())) + self.stream.write(self.sep2) + self.stream.write(output) + + def stopTestRun(self): + self._show_list('ERROR', self.errors) + self._show_list('FAIL', self.failures) + super(CLITestResult, self).stopTestRun() + + class UI(ui.AbstractUI): """A command line user interface.""" @@ -44,6 +69,14 @@ class UI(ui.AbstractUI): outputs.append('%s: %s' % (label, value)) self._stdout.write('%s\n' % ' '.join(outputs)) + def output_results(self, suite_or_test): + result = CLITestResult(self._stdout) + result.startTestRun() + try: + suite_or_test.run(result) + finally: + result.stopTestRun() + def set_command(self, cmd): ui.AbstractUI.set_command(self, cmd) parser = OptionParser() diff --git a/testrepository/ui/model.py b/testrepository/ui/model.py index a287a1b..dd7d9f6 100644 --- a/testrepository/ui/model.py +++ b/testrepository/ui/model.py @@ -56,3 +56,6 @@ class UI(ui.AbstractUI): def output_values(self, values): self.outputs.append(('values', values)) + + def output_results(self, suite_or_test): + self.outputs.append(('results', suite_or_test)) |