# Original Author of the test/unit console runner:: Nathaniel Talbott. # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved. # License:: Ruby license. # Author of a couple of lines of change: Peter Burns. I just added in the # code to throw up a growl notification with the results of running the tests #Requires: http://rubycocoa.sourceforge.net/ require 'test/unit/ui/testrunnermediator' require 'test/unit/ui/testrunnerutilities' begin require 'growl' rescue LoadError => e # #Inline include of the Growl ruby bindings: # http://growl.info/downloads_developers.php # ### Copyright # # Copyright 2004 Thomas Kollbach # # Released under the BSD license. # ### Description # # A ruby class that enables posting notifications to the Growl daemon. # See for more information. # # Requires RubyCocoa (http://www.fobj.com/rubycocoa/) and Ruby 1.8 # (http://ruby-lang.org). # ### Versions # # v0.1- 25.11.2004 - Initial version, this is less more then a ruby translation of # the python bindings # # TODO: transform this into a ruby-module, so it is usable as a mixin # for ruby-scripts # ### Usage # # Here is a short example how to use this in a script # # n = GrowlNotifier.new('bla',['Foo'],nil,OSX::NSWorkspace.sharedWorkspace().iconForFileType_('unknown')) # n.register() # # n.notify('Foo', 'Test Notification', 'Blah blah blah') # ### require 'osx/cocoa' $priority = {"Very Low" => -2, "Moderate" => -1, "Normal" => 0, "High" => 1, "Emergency"=> 2 } class GrowlNotifier # A class that abstracts the process of registering and posting # notifications to the Growl daemon. # # `appName': The name of the application # `notifications': an array of notifications - default is an empty array # # `defaultNotifications': optional - defaults to the value of # `notifications' # `appIcon' is also optional but defaults to a senseless icon so # so you are higly encouraged to pass it along. # def initialize(appName='GrowlNotifier', notifications=[], defaultNotifications=nil, appIcon=nil) @appName = appName @notifications = notifications @defaultNotifications = defaultNotifications @appIcon = appIcon end #initialize def register if @appIcon == nil then @appIcon = OSX::NSWorkspace.sharedWorkspace().iconForFileType_("txt") end if @defaultNotifications == nil then @defaultNotifications = @notifications end regData = { 'ApplicationName'=>@appName, 'AllNotifications'=> OSX::NSArray.arrayWithArray(@notifications), 'DefaultNotifications'=> OSX::NSArray.arrayWithArray(@defaultNotifications), 'ApplicationIcon'=> @appIcon.TIFFRepresentation } dict = OSX::NSDictionary.dictionaryWithDictionary(regData) notifyCenter = OSX::NSDistributedNotificationCenter.defaultCenter notifyCenter.postNotificationName_object_userInfo_deliverImmediately_("GrowlApplicationRegistrationNotification", nil, dict, true) end #register def notify(noteType, title, description, icon=nil, appIcon=nil, sticky=false, priority=nil) # Post a notification to the Growl daemon. # # `noteType' is the name of the notification that is being posted. # `title' is the user-visible title for this notification. # `description' is the user-visible description of this notification. # `icon' is an optional icon for this notification. It defaults to # `@applicationIcon'. # `appIcon' is an optional icon for the sending application. # `sticky' is a boolean controlling whether the notification is sticky. @notifications << noteType if icon == nil then icon = @appIcon end notification = {'NotificationName'=> noteType, 'ApplicationName'=> @appName, 'NotificationTitle'=> title, 'NotificationDescription'=> description, 'NotificationIcon'=> icon.TIFFRepresentation()} unless appIcon == nil notification['NotificationAppIcon'] = appicon.TIFFRepresentation end if sticky notification['NotificationSticky'] = OSX::NSNumber.numberWithBool_(true) end unless priority == nil notification['NotificationPriority'] = OSX::NSNumber.numberWithInt_(priority) end d = OSX::NSDictionary.dictionaryWithDictionary_(notification) notCenter = OSX::NSDistributedNotificationCenter.defaultCenter() notCenter.postNotificationName_object_userInfo_deliverImmediately_('GrowlNotification', nil, d, true) end #notify end #class growlnotifier end#end inline include of the growl ruby bindings module Test module Unit module UI module Growl # Runs a Test::Unit::TestSuite on the console. class TestRunner extend TestRunnerUtilities # Creates a new TestRunner for running the passed # suite. If quiet_mode is true, the output while # running is limited to progress dots, errors and # failures, and the final result. io specifies # where runner output should go to; defaults to # STDOUT. def initialize(suite, output_level=NORMAL,io=STDOUT) if (suite.respond_to?(:suite)) @suite = suite.suite else @suite = suite end @output_level = output_level @already_outputted = false @faults = [] @result_string = "" @io = io @passed_title = "Tests Passed" @failed_title = "Tests Failed" @notifier = GrowlNotifier.new('RUnit Testing',[@passed_title,@failed_title],nil, OSX::NSWorkspace.sharedWorkspace().iconForFileType_('rb')) @notifier.register() end # Begins the test run. def start setup_mediator attach_to_mediator return start_mediator end private def setup_mediator @mediator = create_mediator(@suite) suite_name = @suite.to_s if ( @suite.kind_of?(Module) ) suite_name = @suite.name end output("Loaded suite #{suite_name}") end def create_mediator(suite) return TestRunnerMediator.new(suite) end def attach_to_mediator @mediator.add_listener(TestResult::FAULT, &method(:add_fault)) @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started)) @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished)) @mediator.add_listener(TestCase::STARTED, &method(:test_started)) @mediator.add_listener(TestCase::FINISHED, &method(:test_finished)) end def start_mediator return @mediator.run_suite end def add_fault(fault) @faults << fault output_single(fault.single_character_display, PROGRESS_ONLY) @already_outputted = true end def started(result) @result = result output("Started") end def finished(elapsed_time) nl output("Finished in #{elapsed_time} seconds.") @faults.each_with_index do |fault, index| nl output("%3d) %s" % [index + 1, fault.long_display]) end nl output(@result) if @faults.length > 0 @notifier.notify(@failed_title, @suite.to_s, @result.to_s) else @notifier.notify(@passed_title, @suite.to_s, @result.to_s) end end def test_started(name) output_single(name + ": ", VERBOSE) end def test_finished(name) output_single(".", PROGRESS_ONLY) unless (@already_outputted) nl(VERBOSE) @already_outputted = false end def nl(level=NORMAL) output("", level) end def output(something, level=NORMAL) output_single("#{something}\n", level) end def output_single(something, level=NORMAL) if (output?(level)) @result_string += something.to_s @io.write(something) @io.flush end end def output?(level) level <= @output_level end end end end end end if __FILE__ == $0 Test::Unit::UI::Console::TestRunner.start_command_line_test end