diff options
author | francis <francis> | 2008-09-04 06:10:25 +0000 |
---|---|---|
committer | francis <francis> | 2008-09-04 06:10:25 +0000 |
commit | 5bde1025dc4d43ea53f63107b88711ebf8942408 (patch) | |
tree | 962c8b1fb32186fbd1ab15050ede8e560d9a63f6 /vendor/plugins/rspec/lib/spec/runner | |
parent | ce2cf5ed73d81180e9f88d590daaa23989ee9472 (diff) |
rspec for rails 2.1
Diffstat (limited to 'vendor/plugins/rspec/lib/spec/runner')
15 files changed, 300 insertions, 159 deletions
diff --git a/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb b/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb index 5fd2fb99f..587e57d90 100644 --- a/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb +++ b/vendor/plugins/rspec/lib/spec/runner/backtrace_tweaker.rb @@ -27,7 +27,7 @@ module Spec /\/lib\/ruby\//, /bin\/spec:/, /bin\/rcov:/, - /lib\/rspec_on_rails/, + /lib\/rspec-rails/, /vendor\/rails/, # TextMate's Ruby and RSpec plugins /Ruby\.tmbundle\/Support\/tmruby.rb:/, diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb index c8647cf50..a1269b513 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/base_formatter.rb @@ -19,8 +19,7 @@ module Spec end # This method is invoked at the beginning of the execution of each example_group. - # +name+ is the name of the example_group and +first+ is true if it is the - # first example_group - otherwise it's false. + # +example_group+ is the example_group. # # The next method to be invoked after this is #example_failed or #example_finished def add_example_group(example_group) @@ -46,7 +45,7 @@ module Spec # been provided a block), or when an ExamplePendingError is raised. # +message+ is the message from the ExamplePendingError, if it exists, or the # default value of "Not Yet Implemented" - def example_pending(example_group_description, example, message) + def example_pending(example, message) end # This method is invoked after all of the examples have executed. The next method diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb index 859b2641d..bad023db7 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/base_text_formatter.rb @@ -26,8 +26,8 @@ module Spec @pending_examples = [] end - def example_pending(example_group_description, example, message) - @pending_examples << ["#{example_group_description} #{example.description}", message] + def example_pending(example, message) + @pending_examples << [example.__full_description, message] end def dump_failure(counter, failure) diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb index 5a4607983..8d39bc572 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/failing_example_groups_formatter.rb @@ -4,19 +4,15 @@ module Spec module Runner module Formatter class FailingExampleGroupsFormatter < BaseTextFormatter - def add_example_group(example_group) - super - @example_group_description_parts = example_group.description_parts - end - def example_failed(example, counter, failure) - if @example_group_description_parts - description_parts = @example_group_description_parts.collect do |description| + if @example_group + description_parts = @example_group.description_parts.collect do |description| description =~ /(.*) \(druby.*\)$/ ? $1 : description end @output.puts ::Spec::Example::ExampleGroupMethods.description_text(*description_parts) + @output.flush - @example_group_description_parts = nil + @example_group = nil end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb index ad153c8dc..e5368f2cb 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/html_formatter.rb @@ -9,18 +9,22 @@ module Spec def initialize(options, output) super - @current_example_group_number = 0 - @current_example_number = 0 + @example_group_number = 0 + @example_number = 0 + end + + def method_missing(sym, *args) + # no-op end # The number of the currently running example_group - def current_example_group_number - @current_example_group_number + def example_group_number + @example_group_number end # The number of the currently running example (a global counter) - def current_example_number - @current_example_number + def example_number + @example_number end def start(example_count) @@ -35,14 +39,14 @@ module Spec super @example_group_red = false @example_group_red = false - @current_example_group_number += 1 - unless current_example_group_number == 1 + @example_group_number += 1 + unless example_group_number == 1 @output.puts " </dl>" @output.puts "</div>" end @output.puts "<div class=\"example_group\">" @output.puts " <dl>" - @output.puts " <dt id=\"example_group_#{current_example_group_number}\">#{h(example_group.description)}</dt>" + @output.puts " <dt id=\"example_group_#{example_group_number}\">#{h(example_group.description)}</dt>" @output.flush end @@ -53,7 +57,7 @@ module Spec end def example_started(example) - @current_example_number += 1 + @example_number += 1 end def example_passed(example) @@ -67,7 +71,7 @@ module Spec failure_style = failure.pending_fixed? ? 'pending_fixed' : 'failed' @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red @header_red = true - @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{current_example_group_number}');</script>" unless @example_group_red + @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{example_group_number}');</script>" unless @example_group_red @example_group_red = true move_progress @output.puts " <dd class=\"spec #{failure_style}\">" @@ -81,9 +85,9 @@ module Spec @output.flush end - def example_pending(example_group_description, example, message) + def example_pending(example, message) @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red - @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{current_example_group_number}');</script>" unless @example_group_red + @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{example_group_number}');</script>" unless @example_group_red move_progress @output.puts " <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>" @output.flush @@ -106,7 +110,7 @@ module Spec def percent_done result = 100.0 if @example_count != 0 - result = ((current_example_number).to_f / @example_count.to_f * 1000).to_i / 10.0 + result = ((example_number).to_f / @example_count.to_f * 1000).to_i / 10.0 end result end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb new file mode 100644 index 000000000..f9aa5f67c --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/nested_text_formatter.rb @@ -0,0 +1,65 @@ +require 'spec/runner/formatter/base_text_formatter' + +module Spec + module Runner + module Formatter + class NestedTextFormatter < BaseTextFormatter + attr_reader :previous_nested_example_groups + def initialize(options, where) + super + @previous_nested_example_groups = [] + end + + def add_example_group(example_group) + super + + current_nested_example_groups = described_example_group_chain + current_nested_example_groups.each_with_index do |nested_example_group, i| + unless nested_example_group == previous_nested_example_groups[i] + output.puts "#{' ' * i}#{nested_example_group.description_args}" + end + end + + @previous_nested_example_groups = described_example_group_chain + end + + def example_failed(example, counter, failure) + message = if failure.expectation_not_met? + "#{current_indentation}#{example.description} (FAILED - #{counter})" + else + "#{current_indentation}#{example.description} (ERROR - #{counter})" + end + + output.puts(failure.expectation_not_met? ? red(message) : magenta(message)) + output.flush + end + + def example_passed(example) + message = "#{current_indentation}#{example.description}" + output.puts green(message) + output.flush + end + + def example_pending(example, message) + super + output.puts yellow("#{current_indentation}#{example.description} (PENDING: #{message})") + output.flush + end + + def current_indentation + ' ' * previous_nested_example_groups.length + end + + def described_example_group_chain + example_group_chain = [] + example_group.send(:execute_in_class_hierarchy) do |parent_example_group| + if parent_example_group.description_args && !parent_example_group.description_args.empty? + example_group_chain << parent_example_group + end + end + example_group_chain + end + end + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb index 3784f3ac7..8671d721e 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/profile_formatter.rb @@ -41,6 +41,10 @@ module Spec end @output.flush end + + def method_missing(sym, *args) + # ignore + end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb index 8d0e50432..032a2872d 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb @@ -14,7 +14,7 @@ module Spec @output.flush end - def example_pending(example_group_description, example, message) + def example_pending(example, message) super @output.print yellow('P') @output.flush @@ -24,6 +24,10 @@ module Spec @output.puts @output.flush end + + def method_missing(sym, *args) + # ignore + end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb index f426dc948..facf1a65a 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/specdoc_formatter.rb @@ -28,7 +28,7 @@ module Spec output.flush end - def example_pending(example_group_description, example, message) + def example_pending(example, message) super output.puts yellow("- #{example.description} (PENDING: #{message})") output.flush diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb index b70ac153a..5a8134683 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/story/html_formatter.rb @@ -98,6 +98,9 @@ EOF scenario_ended end + def step_upcoming(type, description, *args) + end + def step_succeeded(type, description, *args) print_step('passed', type, description, *args) # TODO: uses succeeded CSS class end diff --git a/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb b/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb index 424e27cc6..31cd614cb 100644 --- a/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/formatter/story/plain_text_formatter.rb @@ -38,6 +38,7 @@ module Spec @scenario_already_failed = false @output.print "\n\n Scenario: #{scenario_name}" @scenario_ok = true + @scenario_pending = false end def scenario_succeeded(story_title, scenario_name) @@ -52,6 +53,7 @@ module Spec def scenario_pending(story_title, scenario_name, msg) @pending_scenario_count += 1 unless @scenario_already_failed + @scenario_pending = true @scenario_already_failed = true end @@ -76,21 +78,29 @@ module Spec end end end - + + def step_upcoming(type, description, *args) + end + def step_succeeded(type, description, *args) - found_step(type, description, false, *args) + found_step(type, description, false, false, *args) end def step_pending(type, description, *args) - found_step(type, description, false, *args) + found_step(type, description, false, true, *args) @pending_steps << [@current_story_title, @current_scenario_name, description] - @output.print " (PENDING)" + @output.print yellow(" (PENDING)") + @scenario_pending = true @scenario_ok = false end def step_failed(type, description, *args) - found_step(type, description, true, *args) - @output.print red(@scenario_ok ? " (FAILED)" : " (SKIPPED)") + found_step(type, description, true, @scenario_pending, *args) + if @scenario_pending + @output.print yellow(" (SKIPPED)") + else + @output.print red(@scenario_ok ? " (FAILED)" : " (SKIPPED)") + end @scenario_ok = false end @@ -103,7 +113,7 @@ module Spec private - def found_step(type, description, failed, *args) + def found_step(type, description, failed, pending, *args) desc_string = description.step_name arg_regexp = description.arg_regexp text = if(type == @previous_type) @@ -113,7 +123,11 @@ module Spec end i = -1 text << desc_string.gsub(arg_regexp) { |param| args[i+=1] } - @output.print(failed ? red(text) : green(text)) + if pending + @output.print yellow(text) + else + @output.print(failed ? red(text) : green(text)) + end if type == :'given scenario' @previous_type = :given diff --git a/vendor/plugins/rspec/lib/spec/runner/option_parser.rb b/vendor/plugins/rspec/lib/spec/runner/option_parser.rb index 09cedccac..91525e089 100644 --- a/vendor/plugins/rspec/lib/spec/runner/option_parser.rb +++ b/vendor/plugins/rspec/lib/spec/runner/option_parser.rb @@ -15,7 +15,11 @@ module Spec attr_reader :options OPTIONS = { - :diff => ["-D", "--diff [FORMAT]", "Show diff of objects that are expected to be equal when they are not", + :pattern => ["-p", "--pattern [PATTERN]","Limit files loaded to those matching this pattern. Defaults to '**/*_spec.rb'", + "Separate multiple patterns with commas.", + "Applies only to directories named on the command line (files", + "named explicitly on the command line will be loaded regardless)."], + :diff => ["-D", "--diff [FORMAT]","Show diff of objects that are expected to be equal when they are not", "Builtin formats: unified|u|context|c", "You can also specify a custom differ class", "(in which case you should also specify --require)"], @@ -32,7 +36,7 @@ module Spec :specification => ["-s", "--specification [NAME]", "DEPRECATED - use -e instead", "(This will be removed when autotest works with -e)"], :line => ["-l", "--line LINE_NUMBER", Integer, "Execute behaviout or specification at given line.", "(does not work for dynamically generated specs)"], - :format => ["-f", "--format FORMAT[:WHERE]", "Specifies what format to use for output. Specify WHERE to tell", + :format => ["-f", "--format FORMAT[:WHERE]","Specifies what format to use for output. Specify WHERE to tell", "the formatter where to write the output. All built-in formats", "expect WHERE to be a file name, and will write to STDOUT if it's", "not specified. The --format option may be specified several times", @@ -42,6 +46,7 @@ module Spec "progress|p : Text progress", "profile|o : Text progress with profiling of 10 slowest examples", "specdoc|s : Example doc as text", + "indented|i : Example doc as indented text", "html|h : A nice HTML report", "failing_examples|e : Write all failing examples - input for --example", "failing_example_groups|g : Write all failing example groups - input for --example", @@ -53,13 +58,13 @@ module Spec "FORMAT can also be the name of a custom formatter class", "(in which case you should also specify --require to load it)"], :require => ["-r", "--require FILE", "Require FILE before running specs", - "Useful for loading custom formatters or other extensions.", - "If this option is used it must come before the others"], + "Useful for loading custom formatters or other extensions.", + "If this option is used it must come before the others"], :backtrace => ["-b", "--backtrace", "Output full backtrace"], :loadby => ["-L", "--loadby STRATEGY", "Specify the strategy by which spec files should be loaded.", - "STRATEGY can currently only be 'mtime' (File modification time)", - "By default, spec files are loaded in alphabetical order if --loadby", - "is not specified."], + "STRATEGY can currently only be 'mtime' (File modification time)", + "By default, spec files are loaded in alphabetical order if --loadby", + "is not specified."], :reverse => ["-R", "--reverse", "Run examples in reverse order"], :timeout => ["-t", "--timeout FLOAT", "Interrupt and fail each example that doesn't complete in the", "specified time"], @@ -84,11 +89,11 @@ module Spec @out_stream = out @options = Options.new(@error_stream, @out_stream) - @spec_parser = SpecParser.new @file_factory = File self.banner = "Usage: spec (FILE|DIRECTORY|GLOB)+ [options]" self.separator "" + on(*OPTIONS[:pattern]) {|pattern| @options.filename_pattern = pattern} on(*OPTIONS[:diff]) {|diff| @options.parse_diff(diff)} on(*OPTIONS[:colour]) {@options.colour = true} on(*OPTIONS[:example]) {|example| @options.parse_example(example)} @@ -103,11 +108,8 @@ module Spec on(*OPTIONS[:heckle]) {|heckle| @options.load_heckle_runner(heckle)} on(*OPTIONS[:dry_run]) {@options.dry_run = true} on(*OPTIONS[:options_file]) {|options_file| parse_options_file(options_file)} - on(*OPTIONS[:generate_options]) do |options_file| - end - on(*OPTIONS[:runner]) do |runner| - @options.user_input_for_runner = runner - end + on(*OPTIONS[:generate_options]) {|options_file|} + on(*OPTIONS[:runner]) {|runner| @options.user_input_for_runner = runner} on(*OPTIONS[:drb]) {} on(*OPTIONS[:version]) {parse_version} on_tail(*OPTIONS[:help]) {parse_help} @@ -124,10 +126,6 @@ module Spec blk.call(file) if blk end - if @options.line_number - set_spec_from_line_number - end - @options end @@ -141,6 +139,10 @@ module Spec def parse_options_file(options_file) option_file_args = IO.readlines(options_file).map {|l| l.chomp.split " "}.flatten @argv.push(*option_file_args) + # TODO - this is a brute force solution to http://rspec.lighthouseapp.com/projects/5645/tickets/293. + # Let's look for a cleaner way. Might not be one. But let's look. If not, perhaps + # this can be moved to a different method to indicate the special handling for drb? + parse_drb(@argv) end def parse_generate_options @@ -170,12 +172,12 @@ module Spec @options.examples_should_not_be_run end - def parse_drb + def parse_drb(argv = nil) + argv ||= @options.argv # TODO - see note about about http://rspec.lighthouseapp.com/projects/5645/tickets/293 is_drb = false - argv = @options.argv is_drb ||= argv.delete(OPTIONS[:drb][0]) is_drb ||= argv.delete(OPTIONS[:drb][1]) - return nil unless is_drb + return false unless is_drb @options.examples_should_not_be_run DrbCommandLine.run( self.class.parse(argv, @error_stream, @out_stream) @@ -193,37 +195,9 @@ module Spec exit if stdout? end - def set_spec_from_line_number - if @options.examples.empty? - if @options.files.length == 1 - if @file_factory.file?(@options.files[0]) - source = @file_factory.open(@options.files[0]) - example = @spec_parser.spec_name_for(source, @options.line_number) - @options.parse_example(example) - elsif @file_factory.directory?(@options.files[0]) - @error_stream.puts "You must specify one file, not a directory when using the --line option" - exit(1) if stderr? - else - @error_stream.puts "#{@options.files[0]} does not exist" - exit(2) if stderr? - end - else - @error_stream.puts "Only one file can be specified when using the --line option: #{@options.files.inspect}" - exit(3) if stderr? - end - else - @error_stream.puts "You cannot use both --line and --example" - exit(4) if stderr? - end - end - def stdout? @out_stream == $stdout end - - def stderr? - @error_stream == $stderr - end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/options.rb b/vendor/plugins/rspec/lib/spec/runner/options.rb index a5a07548d..6716464af 100644 --- a/vendor/plugins/rspec/lib/spec/runner/options.rb +++ b/vendor/plugins/rspec/lib/spec/runner/options.rb @@ -8,6 +8,8 @@ module Spec EXAMPLE_FORMATTERS = { # Load these lazily for better speed 'specdoc' => ['spec/runner/formatter/specdoc_formatter', 'Formatter::SpecdocFormatter'], 's' => ['spec/runner/formatter/specdoc_formatter', 'Formatter::SpecdocFormatter'], + 'nested' => ['spec/runner/formatter/nested_text_formatter', 'Formatter::NestedTextFormatter'], + 'n' => ['spec/runner/formatter/nested_text_formatter', 'Formatter::NestedTextFormatter'], 'html' => ['spec/runner/formatter/html_formatter', 'Formatter::HtmlFormatter'], 'h' => ['spec/runner/formatter/html_formatter', 'Formatter::HtmlFormatter'], 'progress' => ['spec/runner/formatter/progress_bar_formatter', 'Formatter::ProgressBarFormatter'], @@ -29,6 +31,7 @@ module Spec } attr_accessor( + :filename_pattern, :backtrace_tweaker, :context_lines, :diff_format, @@ -45,6 +48,8 @@ module Spec :user_input_for_runner, :error_stream, :output_stream, + :before_suite_parts, + :after_suite_parts, # TODO: BT - Figure out a better name :argv ) @@ -53,6 +58,7 @@ module Spec def initialize(error_stream, output_stream) @error_stream = error_stream @output_stream = output_stream + @filename_pattern = "**/*_spec.rb" @backtrace_tweaker = QuietBacktraceTweaker.new @examples = [] @colour = false @@ -63,9 +69,12 @@ module Spec @diff_format = :unified @files = [] @example_groups = [] + @result = nil @examples_run = false @examples_should_be_run = nil @user_input_for_runner = nil + @before_suite_parts = [] + @after_suite_parts = [] end def add_example_group(example_group) @@ -78,16 +87,31 @@ module Spec def run_examples return true unless examples_should_be_run? - runner = custom_runner || ExampleGroupRunner.new(self) + success = true + begin + before_suite_parts.each do |part| + part.call + end + runner = custom_runner || ExampleGroupRunner.new(self) - runner.load_files(files_to_load) - if example_groups.empty? - true - else - success = runner.run - @examples_run = true - heckle if heckle_runner - success + unless @files_loaded + runner.load_files(files_to_load) + @files_loaded = true + end + + if example_groups.empty? + true + else + set_spec_from_line_number if line_number + success = runner.run + @examples_run = true + heckle if heckle_runner + success + end + ensure + after_suite_parts.each do |part| + part.call(success) + end end end @@ -101,10 +125,14 @@ module Spec def colour=(colour) @colour = colour - begin; \ - require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/; \ - rescue LoadError ; \ - raise "You must gem install win32console to use colour on Windows" ; \ + if @colour && RUBY_PLATFORM =~ /win32/ ;\ + begin ;\ + require 'rubygems' ;\ + require 'Win32/Console/ANSI' ;\ + rescue LoadError ;\ + warn "You must 'gem install win32console' to use colour on Windows" ;\ + @colour = false ;\ + end end end @@ -170,11 +198,29 @@ module Spec end def number_of_examples - @example_groups.inject(0) do |sum, example_group| - sum + example_group.number_of_examples + total = 0 + @example_groups.each do |example_group| + total += example_group.number_of_examples end + total end + def files_to_load + result = [] + sorted_files.each do |file| + if File.directory?(file) + filename_pattern.split(",").each do |pattern| + result += Dir[File.expand_path("#{file}/#{pattern.strip}")] + end + elsif File.file?(file) + result << file + else + raise "File or directory not found: #{file}" + end + end + result + end + protected def examples_should_be_run? return @examples_should_be_run unless @examples_should_be_run.nil? @@ -205,20 +251,6 @@ module Spec end end - def files_to_load - result = [] - sorted_files.each do |file| - if test ?d, file - result += Dir[File.expand_path("#{file}/**/*.rb")] - elsif test ?f, file - result << file - else - raise "File or directory not found: #{file}" - end - end - result - end - def custom_runner return nil unless custom_runner? klass_name, arg = ClassAndArgumentsParser.parse(user_input_for_runner) @@ -231,9 +263,9 @@ module Spec end def heckle - returns = self.heckle_runner.heckle_with + heckle_runner = self.heckle_runner self.heckle_runner = nil - returns + heckle_runner.heckle_with end def sorted_files @@ -248,6 +280,30 @@ module Spec require 'spec/expectations/differs/default' self.differ_class = Spec::Expectations::Differs::Default end + + def set_spec_from_line_number + if examples.empty? + if files.length == 1 + if File.directory?(files[0]) + error_stream.puts "You must specify one file, not a directory when using the --line option" + exit(1) if stderr? + else + example = SpecParser.new.spec_name_for(files[0], line_number) + @examples = [example] + end + else + error_stream.puts "Only one file can be specified when using the --line option: #{files.inspect}" + exit(3) if stderr? + end + else + error_stream.puts "You cannot use both --line and --example" + exit(4) if stderr? + end + end + + def stderr? + @error_stream == $stderr + end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/reporter.rb b/vendor/plugins/rspec/lib/spec/runner/reporter.rb index cfc511baf..66db38406 100644 --- a/vendor/plugins/rspec/lib/spec/runner/reporter.rb +++ b/vendor/plugins/rspec/lib/spec/runner/reporter.rb @@ -26,7 +26,7 @@ module Spec if error.nil? example_passed(example) elsif Spec::Example::ExamplePendingError === error - example_pending(example_groups.last, example, error.message) + example_pending(example, error.message) else example_failed(example, error) end @@ -34,8 +34,7 @@ module Spec def failure(example, error) backtrace_tweaker.tweak_backtrace(error) - example_name = "#{example_groups.last.description} #{example.description}" - failure = Failure.new(example_name, error) + failure = Failure.new(example, error) @failures << failure formatters.each do |f| f.example_failed(example, @failures.length, failure) @@ -91,6 +90,7 @@ module Spec index + 1 end end + def dump_pending formatters.each{|f| f.dump_pending} end @@ -104,28 +104,28 @@ module Spec formatters.each{|f| f.example_passed(example)} end - def example_pending(example_group, example, message="Not Yet Implemented") + def example_pending(example, message="Not Yet Implemented") @pending_count += 1 formatters.each do |f| - f.example_pending(example_group.description, example, message) + f.example_pending(example, message) end end class Failure - attr_reader :exception + attr_reader :example, :exception - def initialize(example_name, exception) - @example_name = example_name + def initialize(example, exception) + @example = example @exception = exception end def header if expectation_not_met? - "'#{@example_name}' FAILED" + "'#{example_name}' FAILED" elsif pending_fixed? - "'#{@example_name}' FIXED" + "'#{example_name}' FIXED" else - "#{@exception.class.name} in '#{@example_name}'" + "#{@exception.class.name} in '#{example_name}'" end end @@ -137,6 +137,10 @@ module Spec @exception.is_a?(Spec::Expectations::ExpectationNotMetError) end + protected + def example_name + @example.__full_description + end end end end diff --git a/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb b/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb index 5ce51e3b2..8beb384e9 100644 --- a/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb +++ b/vendor/plugins/rspec/lib/spec/runner/spec_parser.rb @@ -2,14 +2,28 @@ module Spec module Runner # Parses a spec file and finds the nearest example for a given line number. class SpecParser - def spec_name_for(io, line_number) - source = io.read - example_group, example_group_line = example_group_at_line(source, line_number) - example, example_line = example_at_line(source, line_number) - if example_group && example && (example_group_line < example_line) - "#{example_group} #{example}" - elsif example_group - example_group + attr_reader :best_match + + def initialize + @best_match = {} + end + + def spec_name_for(file, line_number) + best_match.clear + file = File.expand_path(file) + rspec_options.example_groups.each do |example_group| + consider_example_groups_for_best_match example_group, file, line_number + + example_group.examples.each do |example| + consider_example_for_best_match example, example_group, file, line_number + end + end + if best_match[:example_group] + if best_match[:example] + "#{best_match[:example_group].description} #{best_match[:example].description}" + else + best_match[:example_group].description + end else nil end @@ -17,36 +31,40 @@ module Spec protected - def example_group_at_line(source, line_number) - find_above(source, line_number, /^\s*(context|describe)\s+(.*)\s+do/) - end - - def example_at_line(source, line_number) - find_above(source, line_number, /^\s*(specify|it)\s+(.*)\s+do/) + def consider_example_groups_for_best_match(example_group, file, line_number) + parsed_backtrace = parse_backtrace(example_group.registration_backtrace) + parsed_backtrace.each do |example_file, example_line| + if is_best_match?(file, line_number, example_file, example_line) + best_match.clear + best_match[:example_group] = example_group + best_match[:line] = example_line + end + end end - # Returns the context/describe or specify/it name and the line number - def find_above(source, line_number, pattern) - lines_above_reversed(source, line_number).each_with_index do |line, n| - return [parse_description($2), line_number-n] if line =~ pattern + def consider_example_for_best_match(example, example_group, file, line_number) + parsed_backtrace = parse_backtrace(example.implementation_backtrace) + parsed_backtrace.each do |example_file, example_line| + if is_best_match?(file, line_number, example_file, example_line) + best_match.clear + best_match[:example_group] = example_group + best_match[:example] = example + best_match[:line] = example_line + end end - nil end - def lines_above_reversed(source, line_number) - lines = source.split("\n") - lines[0...line_number].reverse + def is_best_match?(file, line_number, example_file, example_line) + file == File.expand_path(example_file) && + example_line <= line_number && + example_line > best_match[:line].to_i end - - def parse_description(str) - return str[1..-2] if str =~ /^['"].*['"]$/ - if matches = /^['"](.*)['"](,.*)?$/.match(str) - return ::Spec::Example::ExampleGroupMethods.description_text(matches[1]) - end - if matches = /^(.*)\s*,\s*['"](.*)['"](,.*)?$/.match(str) - return ::Spec::Example::ExampleGroupMethods.description_text(matches[1], matches[2]) + + def parse_backtrace(backtrace) + backtrace.collect do |trace_line| + split_line = trace_line.split(':') + [split_line[0], Integer(split_line[1])] end - return str end end end |