source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/test/unit/ui/gtk/testrunner.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 13.9 KB
Line 
1#--
2#
3# Author:: Nathaniel Talbott.
4# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
5# License:: Ruby license.
6
7require 'gtk'
8require 'test/unit/ui/testrunnermediator'
9require 'test/unit/ui/testrunnerutilities'
10
11module Test
12 module Unit
13 module UI
14 module GTK
15
16 # Runs a Test::Unit::TestSuite in a Gtk UI. Obviously,
17 # this one requires you to have Gtk
18 # (http://www.gtk.org/) and the Ruby Gtk extension
19 # (http://ruby-gnome.sourceforge.net/) installed.
20 class TestRunner
21 extend TestRunnerUtilities
22
23 # Creates a new TestRunner for running the passed
24 # suite.
25 def initialize(suite, output_level = NORMAL)
26 if (suite.respond_to?(:suite))
27 @suite = suite.suite
28 else
29 @suite = suite
30 end
31 @result = nil
32
33 @runner = Thread.current
34 @restart_signal = Class.new(Exception)
35 @viewer = Thread.start do
36 @runner.join rescue @runner.run
37 Gtk.main
38 end
39 @viewer.join rescue nil # wait deadlock to handshake
40 end
41
42 # Begins the test run.
43 def start
44 setup_mediator
45 setup_ui
46 attach_to_mediator
47 start_ui
48 @result
49 end
50
51 private
52 def setup_mediator
53 @mediator = TestRunnerMediator.new(@suite)
54 suite_name = @suite.to_s
55 if ( @suite.kind_of?(Module) )
56 suite_name = @suite.name
57 end
58 suite_name_entry.set_text(suite_name)
59 end
60
61 def attach_to_mediator
62 run_button.signal_connect("clicked", nil, &method(:run_test))
63 @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
64 @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
65 @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
66 @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
67 @mediator.add_listener(TestCase::STARTED, &method(:test_started))
68 @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
69 @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
70 end
71
72 def run_test(*)
73 @runner.raise(@restart_signal)
74 end
75
76 def start_ui
77 @viewer.run
78 running = false
79 begin
80 loop do
81 if (running ^= true)
82 run_button.child.text = "Stop"
83 @mediator.run_suite
84 else
85 run_button.child.text = "Run"
86 @viewer.join
87 break
88 end
89 end
90 rescue @restart_signal
91 retry
92 rescue
93 end
94 end
95
96 def stop(*)
97 Gtk.main_quit
98 end
99
100 def reset_ui(count)
101 test_progress_bar.set_style(green_style)
102 test_progress_bar.configure(0, 0, count)
103 @red = false
104
105 run_count_label.set_text("0")
106 assertion_count_label.set_text("0")
107 failure_count_label.set_text("0")
108 error_count_label.set_text("0")
109
110 fault_list.remove_items(fault_list.children)
111 end
112
113 def add_fault(fault)
114 if ( ! @red )
115 test_progress_bar.set_style(red_style)
116 @red = true
117 end
118 item = FaultListItem.new(fault)
119 item.show
120 fault_list.append_items([item])
121 end
122
123 def show_fault(fault)
124 raw_show_fault(fault.long_display)
125 end
126
127 def raw_show_fault(string)
128 fault_detail_label.set_text(string)
129 outer_detail_sub_panel.queue_resize
130 end
131
132 def clear_fault
133 raw_show_fault("")
134 end
135
136 def result_changed(result)
137 run_count_label.set_text(result.run_count.to_s)
138 assertion_count_label.set_text(result.assertion_count.to_s)
139 failure_count_label.set_text(result.failure_count.to_s)
140 error_count_label.set_text(result.error_count.to_s)
141 end
142
143 def started(result)
144 @result = result
145 output_status("Started...")
146 end
147
148 def test_started(test_name)
149 output_status("Running #{test_name}...")
150 end
151
152 def test_finished(test_name)
153 test_progress_bar.set_value(test_progress_bar.get_value + 1)
154 end
155
156 def finished(elapsed_time)
157 output_status("Finished in #{elapsed_time} seconds")
158 end
159
160 def output_status(string)
161 status_entry.set_text(string)
162 end
163
164 def setup_ui
165 main_window.signal_connect("destroy", nil, &method(:stop))
166 main_window.show_all
167 fault_list.signal_connect("select-child", nil) {
168 | list, item, data |
169 show_fault(item.fault)
170 }
171 fault_list.signal_connect("unselect-child", nil) {
172 clear_fault
173 }
174 @red = false
175 end
176
177 def main_window
178 lazy_initialize(:main_window) {
179 @main_window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
180 @main_window.set_title("Test::Unit TestRunner")
181 @main_window.set_usize(800, 600)
182 @main_window.set_uposition(20, 20)
183 @main_window.set_policy(true, true, false)
184 @main_window.add(main_panel)
185 }
186 end
187
188 def main_panel
189 lazy_initialize(:main_panel) {
190 @main_panel = Gtk::VBox.new(false, 0)
191 @main_panel.pack_start(suite_panel, false, false, 0)
192 @main_panel.pack_start(progress_panel, false, false, 0)
193 @main_panel.pack_start(info_panel, false, false, 0)
194 @main_panel.pack_start(list_panel, false, false, 0)
195 @main_panel.pack_start(detail_panel, true, true, 0)
196 @main_panel.pack_start(status_panel, false, false, 0)
197 }
198 end
199
200 def suite_panel
201 lazy_initialize(:suite_panel) {
202 @suite_panel = Gtk::HBox.new(false, 10)
203 @suite_panel.border_width(10)
204 @suite_panel.pack_start(Gtk::Label.new("Suite:"), false, false, 0)
205 @suite_panel.pack_start(suite_name_entry, true, true, 0)
206 @suite_panel.pack_start(run_button, false, false, 0)
207 }
208 end
209
210 def suite_name_entry
211 lazy_initialize(:suite_name_entry) {
212 @suite_name_entry = Gtk::Entry.new
213 @suite_name_entry.set_editable(false)
214 }
215 end
216
217 def run_button
218 lazy_initialize(:run_button) {
219 @run_button = Gtk::Button.new("Run")
220 }
221 end
222
223 def progress_panel
224 lazy_initialize(:progress_panel) {
225 @progress_panel = Gtk::HBox.new(false, 10)
226 @progress_panel.border_width(10)
227 @progress_panel.pack_start(test_progress_bar, true, true, 0)
228 }
229 end
230
231 def test_progress_bar
232 lazy_initialize(:test_progress_bar) {
233 @test_progress_bar = EnhancedProgressBar.new
234 @test_progress_bar.set_usize(@test_progress_bar.allocation.width,
235 info_panel.size_request.height)
236 @test_progress_bar.set_style(green_style)
237 }
238 end
239
240 def green_style
241 lazy_initialize(:green_style) {
242 @green_style = Gtk::Style.new
243 @green_style.set_bg(Gtk::STATE_PRELIGHT, 0x0000, 0xFFFF, 0x0000)
244 }
245 end
246
247 def red_style
248 lazy_initialize(:red_style) {
249 @red_style = Gtk::Style.new
250 @red_style.set_bg(Gtk::STATE_PRELIGHT, 0xFFFF, 0x0000, 0x0000)
251 }
252 end
253
254 def info_panel
255 lazy_initialize(:info_panel) {
256 @info_panel = Gtk::HBox.new(false, 0)
257 @info_panel.border_width(10)
258 @info_panel.pack_start(Gtk::Label.new("Runs:"), false, false, 0)
259 @info_panel.pack_start(run_count_label, true, false, 0)
260 @info_panel.pack_start(Gtk::Label.new("Assertions:"), false, false, 0)
261 @info_panel.pack_start(assertion_count_label, true, false, 0)
262 @info_panel.pack_start(Gtk::Label.new("Failures:"), false, false, 0)
263 @info_panel.pack_start(failure_count_label, true, false, 0)
264 @info_panel.pack_start(Gtk::Label.new("Errors:"), false, false, 0)
265 @info_panel.pack_start(error_count_label, true, false, 0)
266 }
267 end
268
269 def run_count_label
270 lazy_initialize(:run_count_label) {
271 @run_count_label = Gtk::Label.new("0")
272 @run_count_label.set_justify(Gtk::JUSTIFY_LEFT)
273 }
274 end
275
276 def assertion_count_label
277 lazy_initialize(:assertion_count_label) {
278 @assertion_count_label = Gtk::Label.new("0")
279 @assertion_count_label.set_justify(Gtk::JUSTIFY_LEFT)
280 }
281 end
282
283 def failure_count_label
284 lazy_initialize(:failure_count_label) {
285 @failure_count_label = Gtk::Label.new("0")
286 @failure_count_label.set_justify(Gtk::JUSTIFY_LEFT)
287 }
288 end
289
290 def error_count_label
291 lazy_initialize(:error_count_label) {
292 @error_count_label = Gtk::Label.new("0")
293 @error_count_label.set_justify(Gtk::JUSTIFY_LEFT)
294 }
295 end
296
297 def list_panel
298 lazy_initialize(:list_panel) {
299 @list_panel = Gtk::HBox.new
300 @list_panel.border_width(10)
301 @list_panel.pack_start(list_scrolled_window, true, true, 0)
302 }
303 end
304
305 def list_scrolled_window
306 lazy_initialize(:list_scrolled_window) {
307 @list_scrolled_window = Gtk::ScrolledWindow.new
308 @list_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
309 @list_scrolled_window.set_usize(@list_scrolled_window.allocation.width, 150)
310 @list_scrolled_window.add_with_viewport(fault_list)
311 }
312 end
313
314 def fault_list
315 lazy_initialize(:fault_list) {
316 @fault_list = Gtk::List.new
317 }
318 end
319
320 def detail_panel
321 lazy_initialize(:detail_panel) {
322 @detail_panel = Gtk::HBox.new
323 @detail_panel.border_width(10)
324 @detail_panel.pack_start(detail_scrolled_window, true, true, 0)
325 }
326 end
327
328 def detail_scrolled_window
329 lazy_initialize(:detail_scrolled_window) {
330 @detail_scrolled_window = Gtk::ScrolledWindow.new
331 @detail_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
332 @detail_scrolled_window.set_usize(400, @detail_scrolled_window.allocation.height)
333 @detail_scrolled_window.add_with_viewport(outer_detail_sub_panel)
334 }
335 end
336
337 def outer_detail_sub_panel
338 lazy_initialize(:outer_detail_sub_panel) {
339 @outer_detail_sub_panel = Gtk::VBox.new
340 @outer_detail_sub_panel.pack_start(inner_detail_sub_panel, false, false, 0)
341 }
342 end
343
344 def inner_detail_sub_panel
345 lazy_initialize(:inner_detail_sub_panel) {
346 @inner_detail_sub_panel = Gtk::HBox.new
347 @inner_detail_sub_panel.pack_start(fault_detail_label, false, false, 0)
348 }
349 end
350
351 def fault_detail_label
352 lazy_initialize(:fault_detail_label) {
353 @fault_detail_label = EnhancedLabel.new("")
354 style = Gtk::Style.new
355 font = Gdk::Font.font_load("-*-Courier New-medium-r-normal--*-120-*-*-*-*-*-*")
356 begin
357 style.set_font(font)
358 rescue ArgumentError; end
359 @fault_detail_label.set_style(style)
360 @fault_detail_label.set_justify(Gtk::JUSTIFY_LEFT)
361 @fault_detail_label.set_line_wrap(false)
362 }
363 end
364
365 def status_panel
366 lazy_initialize(:status_panel) {
367 @status_panel = Gtk::HBox.new
368 @status_panel.border_width(10)
369 @status_panel.pack_start(status_entry, true, true, 0)
370 }
371 end
372
373 def status_entry
374 lazy_initialize(:status_entry) {
375 @status_entry = Gtk::Entry.new
376 @status_entry.set_editable(false)
377 }
378 end
379
380 def lazy_initialize(symbol)
381 if (!instance_eval("defined?(@#{symbol.to_s})"))
382 yield
383 end
384 return instance_eval("@" + symbol.to_s)
385 end
386 end
387
388 class EnhancedProgressBar < Gtk::ProgressBar
389 def set_style(style)
390 super
391 hide
392 show
393 end
394 end
395
396 class EnhancedLabel < Gtk::Label
397 def set_text(text)
398 super(text.gsub(/\n\t/, "\n" + (" " * 4)))
399 end
400 end
401
402 class FaultListItem < Gtk::ListItem
403 attr_reader(:fault)
404 def initialize(fault)
405 super(fault.short_display)
406 @fault = fault
407 end
408 end
409 end
410 end
411 end
412end
413
414if __FILE__ == $0
415 Test::Unit::UI::GTK::TestRunner.start_command_line_test
416end
Note: See TracBrowser for help on using the repository browser.