mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
196 lines
7.2 KiB
Ruby
196 lines
7.2 KiB
Ruby
|
# Copyright (c) 2008 Nicholas A. Evans
|
||
|
# http://ekenosen.net/nick/devblog/2008/12/better-progress-bar-for-rspec/
|
||
|
#
|
||
|
# With some tweaks (slow spec profiler, growl support)
|
||
|
# By Nick Zadrozny
|
||
|
# http://gist.github.com/71340
|
||
|
#
|
||
|
# Further tweaks (formatador, elapsed time instead of eta)
|
||
|
# By geemus (Wesley Beary)
|
||
|
# http://gist.github.com/266221
|
||
|
#
|
||
|
# Permission is hereby granted, free of charge, to any person obtaining
|
||
|
# a copy of this software and associated documentation files (the
|
||
|
# "Software"), to deal in the Software without restriction, including
|
||
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
# permit persons to whom the Software is furnished to do so, subject to
|
||
|
# the following conditions:
|
||
|
#
|
||
|
# The above copyright notice and this permission notice shall be
|
||
|
# included in all copies or substantial portions of the Software.
|
||
|
#
|
||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
|
||
|
require 'spec/runner/formatter/base_text_formatter'
|
||
|
require "rubygems"
|
||
|
require 'formatador'
|
||
|
|
||
|
module Spec
|
||
|
module Runner
|
||
|
module Formatter
|
||
|
class CompactProgressBarFormatter < BaseTextFormatter
|
||
|
# Threshold for slow specs, in seconds.
|
||
|
# Anything that takes longer than this will be printed out
|
||
|
# It would be great to get this down to 0.5 or less...
|
||
|
SLOW_SPEC_THRESHOLD = 2.0
|
||
|
|
||
|
# Keep track the slowest specs and print a report at the end
|
||
|
SLOW_SPEC_REPORT = 3
|
||
|
|
||
|
attr_reader :total, :current
|
||
|
|
||
|
def start(example_count)
|
||
|
@current = 0
|
||
|
@started_at = Time.now
|
||
|
@total = example_count
|
||
|
@error_state = :all_passing
|
||
|
@slow_specs = []
|
||
|
@formatador = Formatador.new
|
||
|
@formatador.display_line
|
||
|
end
|
||
|
|
||
|
def example_started(example)
|
||
|
super
|
||
|
@start_time = Time.now
|
||
|
end
|
||
|
|
||
|
def example_passed(example)
|
||
|
elapsed = Time.now - @start_time
|
||
|
profile_example(example_group.description, example.description, elapsed)
|
||
|
increment
|
||
|
end
|
||
|
|
||
|
# third param is optional, because earlier versions of rspec sent only two args
|
||
|
def example_pending(example, message, pending_caller=nil)
|
||
|
immediately_dump_pending(example.description, message, pending_caller)
|
||
|
mark_error_state_pending
|
||
|
increment
|
||
|
end
|
||
|
|
||
|
def example_failed(example, counter, failure)
|
||
|
immediately_dump_failure(counter, failure)
|
||
|
notify_failure(counter, failure)
|
||
|
mark_error_state_failed
|
||
|
increment
|
||
|
end
|
||
|
|
||
|
def start_dump
|
||
|
@formatador.display_line("\n")
|
||
|
report_slow_specs
|
||
|
end
|
||
|
|
||
|
def dump_failure(*args)
|
||
|
# no-op; we summarized failures as we were running
|
||
|
end
|
||
|
|
||
|
def method_missing(sym, *args)
|
||
|
# ignore
|
||
|
end
|
||
|
|
||
|
def notify(title, message, priority)
|
||
|
title = title.gsub(/\s+/, ' ').gsub(/"/,'\"').gsub(/'/, "\'")
|
||
|
message = message.gsub(/\s+/, ' ').gsub(/"/,'\"').gsub(/'/, "\'").gsub(/`/,'\`')
|
||
|
notify_command = case RUBY_PLATFORM
|
||
|
when /darwin/
|
||
|
"test -x `which growlnotify` && growlnotify -n autotest -p #{priority} -m \"#{message}\" \"#{title}\""
|
||
|
when /linux/
|
||
|
"test -x `which notify-send` && notify-send \"#{title}\" \"#{message}\""
|
||
|
end
|
||
|
# puts notify_command # use this for debugging purposes
|
||
|
system notify_command if notify_command
|
||
|
end
|
||
|
|
||
|
def notify_failure(counter, failure)
|
||
|
notify failure.header, failure.exception.message, 2
|
||
|
end
|
||
|
|
||
|
# stolen and slightly modified from BaseTextFormatter#dump_failure
|
||
|
def immediately_dump_failure(counter, failure)
|
||
|
@formatador.redisplay("#{' ' * progress_bar.length}\n")
|
||
|
@formatador.redisplay("[red]#{counter.to_s})[/]")
|
||
|
@formatador.display_line("[red]#{failure.header}[/]")
|
||
|
@formatador.indent do
|
||
|
@formatador.display_line("[red]#{failure.exception.message}[/]")
|
||
|
@formatador.display_line
|
||
|
failure.exception.backtrace.each do |line|
|
||
|
@formatador.display_line("[red]#{line}[/]")
|
||
|
end
|
||
|
@formatador.display_line
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# stolen and modified from BaseTextFormatter#dump_pending
|
||
|
def immediately_dump_pending(desc, msg, called_from)
|
||
|
@formatador.indent do
|
||
|
@formatador.redisplay("#{' ' * progress_bar.length}\r")
|
||
|
@formatador.display_line("[yellow]PENDING SPEC:[/] #{desc} (#{msg})\n")
|
||
|
end
|
||
|
# output.puts " Called from #{called_from}" if called_from
|
||
|
end
|
||
|
|
||
|
def increment
|
||
|
@current += 1
|
||
|
@formatador.redisplay(progress_bar)
|
||
|
end
|
||
|
|
||
|
def mark_error_state_failed
|
||
|
@error_state = :some_failed
|
||
|
end
|
||
|
|
||
|
def mark_error_state_pending
|
||
|
@error_state = :some_pending unless @error_state == :some_failed
|
||
|
end
|
||
|
|
||
|
def progress_bar
|
||
|
color = case @error_state
|
||
|
when :some_failed
|
||
|
'red'
|
||
|
when :some_pending
|
||
|
'yellow'
|
||
|
else
|
||
|
'green'
|
||
|
end
|
||
|
ratio = "#{(' ' * (@total.to_s.size - @current.to_s.size))}#{@current}/#{@total}"
|
||
|
fraction = "[#{color}]#{(' ' * (@total.to_s.size - @current.to_s.size))}#{@current}/#{@total}[/]"
|
||
|
percent = @current.to_f / @total.to_f
|
||
|
progress = "[_white_]|[/][#{color}][_#{color}_]#{'*' * (percent * 50).ceil}[/]#{' ' * (50 - (percent * 50).ceil)}[_white_]|[/]"
|
||
|
microseconds = Time.now - @started_at
|
||
|
minutes = (microseconds / 60).round.to_s
|
||
|
seconds = (microseconds % 60).round.to_s
|
||
|
elapsed = "#{minutes}:#{'0' if seconds.size < 2}#{seconds}"
|
||
|
[fraction, progress, elapsed, ''].join(' ')
|
||
|
end
|
||
|
|
||
|
def profile_example(group, example, elapsed)
|
||
|
@slow_specs = (@slow_specs + [[elapsed, group, example]]).sort.reverse[0, SLOW_SPEC_REPORT]
|
||
|
print_warning_if_really_slow(group, example, elapsed)
|
||
|
end
|
||
|
|
||
|
def print_warning_if_really_slow(group, example, elapsed)
|
||
|
if elapsed > SLOW_SPEC_THRESHOLD
|
||
|
@formatador.indent do
|
||
|
@formatador.redisplay("#{' ' * progress_bar.length}\r")
|
||
|
@formatador.display_line("[yellow]SLOW SPEC (#{sprintf("%.4f", elapsed)})[/]: #{group} #{example}\n")
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def report_slow_specs
|
||
|
@formatador.display_line("[yellow]Top #{@slow_specs.size} slowest specs:[/]")
|
||
|
@slow_specs.each do |elapsed, group, example|
|
||
|
@formatador.display_line("[yellow] #{yellow(sprintf('%.4f', elapsed))} #{group} #{example}[/]")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|