Merge lp:~lifeless/tribunal/testrepository into lp:tribunal

Proposed by Robert Collins
Status: Merged
Approved by: Martin Pool
Approved revision: no longer in the revision history of the source branch.
Merge reported by: Martin Pool
Merged at revision: not available
Proposed branch: lp:~lifeless/tribunal/testrepository
Merge into: lp:tribunal
Diff against target: 204 lines (+144/-8)
2 files modified
bin/tribunal-subunit (+37/-8)
tribunal/trui.py (+107/-0)
To merge this branch: bzr merge lp:~lifeless/tribunal/testrepository
Reviewer Review Type Date Requested Status
Martin Pool Approve
Review via email: mp+20321@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

This hooks up testr run to the reload button in tribunal-subunit.

So, if you have a .testr.conf for a project, and hit reload, it will run the projects tests. I've tested this by starting with a clean environment, breaking a test, hitting reload, waiting - et voila, the errors showed up. I then fixed them, hit reload, and they went away.

\o/ success.

Revision history for this message
Martin Pool (mbp) wrote :

Great feature, though the reload button does not seem like the right place for it.

What's trui?

review: Needs Fixing
Revision history for this message
Martin Pool (mbp) wrote :

(discussed offline)

I'll tweak and merge.

review: Approve
lp:~lifeless/tribunal/testrepository updated
121. By Martin Pool

Alternate success and failure in emit-tests

122. By Martin Pool

Update todos

Revision history for this message
Martin Pool (mbp) wrote :

this is now actually merged; I don't know why Launchpad doesn't think so

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/tribunal-subunit'
--- bin/tribunal-subunit 2010-02-19 08:16:29 +0000
+++ bin/tribunal-subunit 2010-02-28 22:05:24 +0000
@@ -37,6 +37,7 @@
3737
38import errno38import errno
39import optparse39import optparse
40import os.path
40import sys41import sys
4142
42import gobject43import gobject
@@ -80,8 +81,9 @@
80 saying whether they should be shown81 saying whether they should be shown
81 """82 """
82 83
83 def __init__(self, glade_xml):84 def __init__(self, glade_xml, opts):
84 self.glade = glade_xml85 self.glade = glade_xml
86 self.opts = opts # An OptParse options object.
85 for i in [87 for i in [
86 'result_frame',88 'result_frame',
87 'result_frame_label',89 'result_frame_label',
@@ -260,6 +262,27 @@
260 self.model_filter.refilter()262 self.model_filter.refilter()
261263
262 def reload_stream(self):264 def reload_stream(self):
265 if self.opts.testr:
266 # run the test suite again.
267 from testrepository.commands import run
268 from tribunal import trui
269 # Work around bug in testrepository (just filed, no # yet).
270 url = os.path.expanduser(self.opts.testr)
271 ui = trui.GTKUI(self, url)
272 cmd = run.run(ui)
273 # Work around 'testr run' loading to the wrong repo.
274 here = os.getcwd()
275 os.chdir(url)
276 try:
277 res = cmd.execute()
278 finally:
279 os.chdir(here)
280 # Ignoring detail of exit code: the subunit parsing + ui error
281 # methods will inform the user.
282 if res == 3:
283 # But if it went badly wrong, don't both doing work in the UI.
284 return
285 self._last_input_file = testrepository_last_stream(self.opts)
263 try:286 try:
264 self._last_input_file.seek(0)287 self._last_input_file.seek(0)
265 except IOError, e:288 except IOError, e:
@@ -286,7 +309,7 @@
286309
287 def _construct_and_show_window(self):310 def _construct_and_show_window(self):
288 glade_xml = load_glade()311 glade_xml = load_glade()
289 self._window = SubunitWindow(glade_xml)312 self._window = SubunitWindow(glade_xml, self.opts)
290 glade_xml.signal_autoconnect(self)313 glade_xml.signal_autoconnect(self)
291 self._set_default_icons()314 self._set_default_icons()
292 self._window.show_all()315 self._window.show_all()
@@ -307,13 +330,10 @@
307 parser.add_option('--testr',330 parser.add_option('--testr',
308 help='read from a testrepository in the given directory')331 help='read from a testrepository in the given directory')
309332
310 opts, args = parser.parse_args(argv)333 self.opts, args = parser.parse_args(argv)
311334
312 if opts.testr:335 if self.opts.testr:
313 import testrepository.repository.file336 stream = testrepository_last_stream(self.opts)
314 factory = testrepository.repository.file.RepositoryFactory()
315 repo = factory.open(opts.testr)
316 stream = repo.get_test_run(repo.latest_id()).get_subunit_stream()
317 elif args == ['-']:337 elif args == ['-']:
318 stream = sys.stdin338 stream = sys.stdin
319 elif len(args) == 1:339 elif len(args) == 1:
@@ -345,6 +365,15 @@
345 return '\n'.join(bits)365 return '\n'.join(bits)
346366
347367
368def testrepository_last_stream(opts):
369 import testrepository.repository.file
370 factory = testrepository.repository.file.RepositoryFactory()
371 # Work around bug in testrepository (just filed, no # yet).
372 url = os.path.expanduser(opts.testr)
373 repo = factory.open(url)
374 return repo.get_test_run(repo.latest_id()).get_subunit_stream()
375
376
348if __name__ == '__main__':377if __name__ == '__main__':
349 app = ViewSubunitApp(GtkLoop())378 app = ViewSubunitApp(GtkLoop())
350 app.run(sys.argv[1:])379 app.run(sys.argv[1:])
351380
=== added file 'tribunal/trui.py'
--- tribunal/trui.py 1970-01-01 00:00:00 +0000
+++ tribunal/trui.py 2010-02-28 22:05:24 +0000
@@ -0,0 +1,107 @@
1#! /usr/bin/env python
2
3# Copyright (C) 2010 Robert Collins <robertc@robertcollins.net>
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License.
7#
8# You may obtain a copy of the License at
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16#
17# Part of Tribunal <https://launchpad.net/tribunal>
18
19"""Support for running testrepository commands."""
20
21__all__ = ['GTKUI']
22
23import optparse
24
25import gtk
26from testrepository import ui
27
28
29class GTKUI(ui.AbstractUI):
30 """A GTK testrepository.ui.AbstractUI implementation."""
31
32 def __init__(self, subunit_window, here):
33 """Create a GTKUI to run a TestRepository command under subunit_window.
34
35 :param subunit_window: A SubunitWindow from tribunal-subunit.
36 :param here: What should the 'here' be for the UI.
37 """
38 self.window = subunit_window
39 self.here = here
40
41 def _check_cmd(self):
42 # TODO: prompt for options and arguments here.
43 # Options are available on self.cmd.options
44 options = []
45 self.options = optparse.Values()
46 seen_options = set()
47 for option, value in options:
48 setattr(self.options, option, value)
49 seen_options.add(option)
50 if not 'quiet' in seen_options:
51 setattr(self.options, 'quiet', False)
52 for option in self.cmd.options:
53 if not option.dest in seen_options:
54 setattr(self.options, option.dest, option.default)
55 # Arguments on self.cmd.args
56 parsed_args = {}
57 unparsed = []
58 failed = False
59 for arg in self.cmd.args:
60 try:
61 parsed_args[arg.name] = arg.parse(unparsed)
62 except ValueError:
63 failed = True
64 break
65 self.arguments = parsed_args
66 return unparsed == [] and not failed
67
68 def output_error(self, error_tuple):
69 # Shows the error in a dialog. We could instead have a 'console' on
70 # the SubunitWindow and write the error into the console.
71 import traceback
72 exctype, value, tb = error_tuple
73 as_string = ''.join(traceback.format_exception(exctype, value, tb))
74 dialog = gtk.MessageDialog(self.window.subunit_window,
75 gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
76 gtk.MESSAGE_ERROR,
77 gtk.BUTTONS_CLOSE,
78 as_string)
79 dialog.run()
80 dialog.destroy()
81
82 def output_rest(self, rest_string):
83 # TODO: format as HTML, embed a browser?
84 raise NotImplementedError(self.output_rest)
85
86 def output_results(self, suite_or_test):
87 # TODO: feed to the main window
88 raise NotImplementedError(self.output_results)
89
90 def output_stream(self, stream):
91 # TODO: ask for a filename to save to.
92 raise NotImplementedError(self.output_stream)
93
94 def output_table(self, table):
95 raise NotImplementedError(self.output_table)
96
97 def output_values(self, values):
98 # TODO: log this to the GUI somehow.
99 outputs = []
100 for label, value in values:
101 outputs.append('%s: %s' % (label, value))
102 print '%s\n' % ' '.join(outputs)
103
104 def subprocess_Popen(self, *args, **kwargs):
105 # TODO: use a GTK GIO thingy
106 import subprocess
107 return subprocess.Popen(*args, **kwargs)

Subscribers

People subscribed via source and target branches

to all changes: