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 | |
parent | ce2cf5ed73d81180e9f88d590daaa23989ee9472 (diff) |
rspec for rails 2.1
Diffstat (limited to 'vendor/plugins/rspec/lib')
56 files changed, 742 insertions, 406 deletions
diff --git a/vendor/plugins/rspec/lib/autotest/rspec.rb b/vendor/plugins/rspec/lib/autotest/rspec.rb index cf7421ee1..164f298f5 100644 --- a/vendor/plugins/rspec/lib/autotest/rspec.rb +++ b/vendor/plugins/rspec/lib/autotest/rspec.rb @@ -18,35 +18,18 @@ end class RspecCommandError < StandardError; end class Autotest::Rspec < Autotest - - def tests_for_file(filename) - super.select { |f| @files.has_key? f } - end - - alias :specs_for_file :tests_for_file - - def failed_results(results) - results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m) - end - def handle_results(results) - @files_to_test = consolidate_failures failed_results(results) - unless @files_to_test.empty? then - hook :red - else - hook :green - end unless $TESTING - @tainted = true unless @files_to_test.empty? + def initialize + super + self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m + self.completed_re = /\n(?:\e\[\d*m)?\d* examples?/m end - + def consolidate_failures(failed) - filters = Hash.new { |h,k| h[k] = [] } - failed.each do |spec, failed_trace| - @files.keys.select{|f| f =~ /spec\//}.each do |f| - if failed_trace =~ Regexp.new(f) - filters[f] << spec - break - end + filters = new_hash_of_arrays + failed.each do |spec, trace| + if trace =~ /\n(\.\/)?(.*\.rb):[\d]+:\Z?/ + filters[$2] << spec end end return filters @@ -56,23 +39,25 @@ class Autotest::Rspec < Autotest return "#{ruby} -S #{spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}" end - def add_options_if_present + def add_options_if_present # :nodoc: File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : "" end - # Finds the proper spec command to use. Precendence - # is set in the lazily-evaluated method spec_commands. Alias + Override - # that in ~/.autotest to provide a different spec command - # then the default paths provided. - def spec_command - @spec_command ||= spec_commands.each do |command| - if File.exists?(command) - return @alt_separator ? (command.gsub @separator, @alt_separator) : command - end + # Finds the proper spec command to use. Precendence is set in the + # lazily-evaluated method spec_commands. Alias + Override that in + # ~/.autotest to provide a different spec command then the default + # paths provided. + def spec_command(separator=File::ALT_SEPARATOR) + unless defined? @spec_command then + @spec_command = spec_commands.find { |cmd| File.exists? cmd } + + raise RspecCommandError, "No spec command could be found!" unless @spec_command + + @spec_command.gsub! File::SEPARATOR, separator if separator end - raise RspecCommandError, "No spec command could be found!" + @spec_command end - + # Autotest will look for spec commands in the following # locations, in this order: # @@ -84,5 +69,4 @@ class Autotest::Rspec < Autotest File.join(Config::CONFIG['bindir'], 'spec') ] end - end diff --git a/vendor/plugins/rspec/lib/spec.rb b/vendor/plugins/rspec/lib/spec.rb index a0fc64750..c143aa885 100644 --- a/vendor/plugins/rspec/lib/spec.rb +++ b/vendor/plugins/rspec/lib/spec.rb @@ -27,11 +27,4 @@ module Spec !Object.const_defined?(:Test) || Test::Unit.run?; \ end end -end - -at_exit do \ - unless $! || Spec.run?; \ - success = Spec.run; \ - exit success if Spec.exit?; \ - end \ end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/example.rb b/vendor/plugins/rspec/lib/spec/example.rb index 39ff76b99..16ce12261 100644 --- a/vendor/plugins/rspec/lib/spec/example.rb +++ b/vendor/plugins/rspec/lib/spec/example.rb @@ -1,7 +1,7 @@ require 'timeout' -require 'forwardable' require 'spec/example/pending' require 'spec/example/module_reopening_fix' +require 'spec/example/module_inclusion_warnings' require 'spec/example/example_group_methods' require 'spec/example/example_methods' require 'spec/example/example_group' diff --git a/vendor/plugins/rspec/lib/spec/example/configuration.rb b/vendor/plugins/rspec/lib/spec/example/configuration.rb index 674184727..cd3f46909 100644 --- a/vendor/plugins/rspec/lib/spec/example/configuration.rb +++ b/vendor/plugins/rspec/lib/spec/example/configuration.rb @@ -7,14 +7,20 @@ module Spec # config.mock_with :rspec, :mocha, :flexmock, or :rr # end # - # To use any other mock framework, you'll have to provide - # your own adapter. This is simply a module that responds to - # setup_mocks_for_rspec, verify_mocks_for_rspec and teardown_mocks_for_rspec. + # To use any other mock framework, you'll have to provide your own + # adapter. This is simply a module that responds to the following + # methods: + # + # setup_mocks_for_rspec + # verify_mocks_for_rspec + # teardown_mocks_for_rspec. + # # These are your hooks into the lifecycle of a given example. RSpec will - # call setup_mocks_for_rspec before running anything else in each Example. - # After executing the #after methods, RSpec will then call verify_mocks_for_rspec - # and teardown_mocks_for_rspec (this is guaranteed to run even if there are - # failures in verify_mocks_for_rspec). + # call setup_mocks_for_rspec before running anything else in each + # Example. After executing the #after methods, RSpec will then call + # verify_mocks_for_rspec and teardown_mocks_for_rspec (this is + # guaranteed to run even if there are failures in + # verify_mocks_for_rspec). # # Once you've defined this module, you can pass that to mock_with: # @@ -35,12 +41,18 @@ module Spec @mock_framework ||= mock_framework_path("rspec") end - # Declares modules to be included in all example groups (<tt>describe</tt> blocks). - # - # config.include(My::Bottle, My::Cup) - # - # If you want to restrict the inclusion to a subset of all the example groups then - # specify this in a Hash as the last argument: + # :call-seq: + # include(Some::Helpers) + # include(Some::Helpers, More::Helpers) + # include(My::Helpers, :type => :key) + # + # Declares modules to be included in multiple example groups + # (<tt>describe</tt> blocks). With no :type, the modules listed will be + # included in all example groups. Use :type to restrict the inclusion to + # a subset of example groups. The value assigned to :type should be a + # key that maps to a class that is either a subclass of + # Spec::Example::ExampleGroup or extends Spec::Example::ExampleGroupMethods + # and includes Spec::Example::ExampleMethods # # config.include(My::Pony, My::Horse, :type => :farm) # @@ -70,7 +82,7 @@ module Spec # # This makes it possible to say: # - # person.should swim # passes if person.should_swim? returns true + # person.should swim # passes if person.can_swim? returns true # def predicate_matchers @predicate_matchers ||= {} @@ -85,10 +97,11 @@ module Spec ) example_group.prepend_before(scope, &proc) end + # Appends a global <tt>before</tt> block to all example groups. # - # If you want to restrict the block to a subset of all the example groups then - # specify this in a Hash as the last argument: + # If you want to restrict the block to a subset of all the example + # groups then specify this in a Hash as the last argument: # # config.prepend_before(:all, :type => :farm) # @@ -115,6 +128,7 @@ module Spec example_group.prepend_after(scope, &proc) end alias_method :after, :prepend_after + # Appends a global <tt>after</tt> block to all example groups. # See #append_before for filtering semantics. def append_after(*args, &proc) diff --git a/vendor/plugins/rspec/lib/spec/example/example_group.rb b/vendor/plugins/rspec/lib/spec/example/example_group.rb index d6e156f93..35997f0c4 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group.rb @@ -1,6 +1,7 @@ module Spec module Example - # The superclass for all regular RSpec examples. + # Base class for customized example groups. Use this if you + # want to make a custom example group. class ExampleGroup extend Spec::Example::ExampleGroupMethods include Spec::Example::ExampleMethods diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb index 0414a3b96..c5caf4c9c 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb @@ -7,52 +7,54 @@ module Spec default(ExampleGroup) end - # Registers an example group class +klass+ with the symbol - # +type+. For example: + # Registers an example group class +klass+ with the symbol +type+. For + # example: # - # Spec::Example::ExampleGroupFactory.register(:farm, Spec::Farm::Example::FarmExampleGroup) + # Spec::Example::ExampleGroupFactory.register(:farm, FarmExampleGroup) # - # This will cause Main#describe from a file living in - # <tt>spec/farm</tt> to create example group instances of type - # Spec::Farm::Example::FarmExampleGroup. - def register(id, example_group_class) - @example_group_types[id] = example_group_class + # With that you can append a hash with :type => :farm to the describe + # method and it will load an instance of FarmExampleGroup. + # + # describe Pig, :type => :farm do + # ... + # + # If you don't use the hash explicitly, <tt>describe</tt> will + # implicitly use an instance of FarmExampleGroup for any file loaded + # from the <tt>./spec/farm</tt> directory. + def register(key, example_group_class) + @example_group_types[key] = example_group_class end # Sets the default ExampleGroup class def default(example_group_class) old = @example_group_types @example_group_types = Hash.new(example_group_class) - @example_group_types.merge(old) if old + @example_group_types.merge!(old) if old end - def get(id=nil) - if @example_group_types.values.include?(id) - id + def get(key=nil) + if @example_group_types.values.include?(key) + key else - @example_group_types[id] + @example_group_types[key] end end def create_example_group(*args, &block) opts = Hash === args.last ? args.last : {} - if opts[:shared] - SharedExampleGroup.new(*args, &block) - else - superclass = determine_superclass(opts) - superclass.describe(*args, &block) - end + superclass = determine_superclass(opts) + superclass.describe(*args, &block) end protected def determine_superclass(opts) - id = if opts[:type] + key = if opts[:type] opts[:type] elsif opts[:spec_path] =~ /spec(\\|\/)(#{@example_group_types.keys.join('|')})/ $2 == '' ? nil : $2.to_sym end - get(id) + get(key) end end diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb index 8f73a9853..64e90cdb2 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb @@ -11,13 +11,14 @@ module Spec end end - attr_reader :description_text, :description_args, :description_options, :spec_path + attr_reader :description_text, :description_args, :description_options, :spec_path, :registration_binding_block def inherited(klass) super - klass.register + klass.register {} + Spec::Runner.register_at_exit_hook end - + # Makes the describe/it syntax available from a class. For example: # # class StackSpec < Spec::ExampleGroup @@ -33,10 +34,17 @@ module Spec # end # def describe(*args, &example_group_block) + args << {} unless Hash === args.last if example_group_block - self.subclass("Subclass") do - describe(*args) - module_eval(&example_group_block) + params = args.last + params[:spec_path] = eval("caller(0)[1]", example_group_block) unless params[:spec_path] + if params[:shared] + SharedExampleGroup.new(*args, &example_group_block) + else + self.subclass("Subclass") do + describe(*args) + module_eval(&example_group_block) + end end else set_description(*args) @@ -44,6 +52,7 @@ module Spec self end end + alias :context :describe # Use this to pull in examples from shared example groups. # See Spec::Runner for information about shared example groups. @@ -106,11 +115,12 @@ module Spec def xit(description=nil, opts={}, &block) Kernel.warn("Example disabled: #{description}") end + alias_method :xspecify, :xit def run examples = examples_to_run - return true if examples.empty? reporter.add_example_group(self) + return true if examples.empty? return dry_run(examples) if dry_run? plugin_mock_framework @@ -149,10 +159,12 @@ module Spec @description_text = ExampleGroupMethods.description_text(*args) @spec_path = File.expand_path(options[:spec_path]) if options[:spec_path] if described_type.class == Module - include described_type + @described_module = described_type end self end + + attr_reader :described_module def examples #:nodoc: examples = example_objects.dup @@ -236,7 +248,8 @@ module Spec @after_each_parts = nil end - def register + def register(®istration_binding_block) + @registration_binding_block = registration_binding_block rspec_options.add_example_group self end @@ -244,6 +257,10 @@ module Spec rspec_options.remove_example_group self end + def registration_backtrace + eval("caller", registration_binding_block.binding) + end + def run_before_each(example) execute_in_class_hierarchy do |example_group| example.eval_each_fail_fast(example_group.before_each_parts) @@ -378,6 +395,7 @@ module Spec case scope when :each; before_each_parts when :all; before_all_parts + when :suite; rspec_options.before_suite_parts end end @@ -385,6 +403,7 @@ module Spec case scope when :each; after_each_parts when :all; after_all_parts + when :suite; rspec_options.after_suite_parts end end diff --git a/vendor/plugins/rspec/lib/spec/example/example_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_methods.rb index 6dd4c9c72..d4d716c2d 100644 --- a/vendor/plugins/rspec/lib/spec/example/example_methods.rb +++ b/vendor/plugins/rspec/lib/spec/example/example_methods.rb @@ -3,6 +3,8 @@ module Spec module ExampleMethods extend ExampleGroupMethods extend ModuleReopeningFix + include ModuleInclusionWarnings + PENDING_EXAMPLE_BLOCK = lambda { raise Spec::Example::ExamplePendingError.new("Not Yet Implemented") @@ -63,6 +65,10 @@ module Spec def description @_defined_description || @_matcher_description || "NO NAME" end + + def __full_description + "#{self.class.description} #{self.description}" + end def set_instance_variables_from_hash(ivars) ivars.each do |variable_name, value| @@ -81,6 +87,10 @@ module Spec Spec::Matchers.clear_generated_description end end + + def implementation_backtrace + eval("caller", @_implementation) + end protected include Matchers diff --git a/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb b/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb new file mode 100644 index 000000000..c65faf2dd --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/module_inclusion_warnings.rb @@ -0,0 +1,37 @@ +module Spec + module Example + # In the future, modules will no longer be automatically included + # in the Example Group (based on the description name); when that + # time comes, this code should be removed. + module ModuleInclusionWarnings + # Thanks, Francis Hwang. + class MethodDispatcher + def initialize(mod, target=nil) + @mod = mod + @target = target + end + + def respond_to?(sym) + @mod && @mod.instance_methods.include?(sym.to_s) + end + + def call(sym, *args, &blk) + Kernel.warn("Modules will no longer be automatically included in RSpec version 1.1.4. Called from #{caller[2]}") + @target.extend @mod + @target.send(sym, *args, &blk) + end + end + + def respond_to?(sym) + MethodDispatcher.new(self.class.described_module).respond_to?(sym) ? true : super + end + + private + + def method_missing(sym, *args, &blk) + md = MethodDispatcher.new(self.class.described_module, self) + self.respond_to?(sym) ? md.call(sym, *args, &blk) : super + end + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb b/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb index a5eb1bb89..74b59bbe3 100644 --- a/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb +++ b/vendor/plugins/rspec/lib/spec/expectations/differs/default.rb @@ -17,7 +17,7 @@ module Spec end # This is snagged from diff/lcs/ldiff.rb (which is a commandline tool) - def diff_as_string(data_old, data_new) + def diff_as_string(data_new, data_old) data_old = data_old.split(/\n/).map! { |e| e.chomp } data_new = data_new.split(/\n/).map! { |e| e.chomp } output = "" diff --git a/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb b/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb index a3925bbee..2091c2947 100644 --- a/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb +++ b/vendor/plugins/rspec/lib/spec/expectations/extensions/object.rb @@ -27,12 +27,8 @@ module Spec # # NOTE that this does NOT support receiver.should != expected. # Instead, use receiver.should_not == expected - def should(matcher = :default_parameter, &block) - if :default_parameter == matcher - Spec::Matchers::PositiveOperatorMatcher.new(self) - else - ExpectationMatcherHandler.handle_matcher(self, matcher, &block) - end + def should(matcher=:use_operator_matcher, &block) + ExpectationMatcherHandler.handle_matcher(self, matcher, &block) end # :call-seq: @@ -54,12 +50,8 @@ module Spec # => Passes unless (receiver =~ regexp) # # See Spec::Matchers for more information about matchers - def should_not(matcher = :default_parameter, &block) - if :default_parameter == matcher - Spec::Matchers::NegativeOperatorMatcher.new(self) - else - NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block) - end + def should_not(matcher=:use_operator_matcher, &block) + NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block) end end diff --git a/vendor/plugins/rspec/lib/spec/expectations/handler.rb b/vendor/plugins/rspec/lib/spec/expectations/handler.rb index e6dce0846..2e5f2a621 100644 --- a/vendor/plugins/rspec/lib/spec/expectations/handler.rb +++ b/vendor/plugins/rspec/lib/spec/expectations/handler.rb @@ -12,6 +12,10 @@ module Spec class << self include MatcherHandlerHelper def handle_matcher(actual, matcher, &block) + if :use_operator_matcher == matcher + return Spec::Matchers::PositiveOperatorMatcher.new(actual) + end + unless matcher.respond_to?(:matches?) raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}." end @@ -27,6 +31,10 @@ module Spec class << self include MatcherHandlerHelper def handle_matcher(actual, matcher, &block) + if :use_operator_matcher == matcher + return Spec::Matchers::NegativeOperatorMatcher.new(actual) + end + unless matcher.respond_to?(:matches?) raise InvalidMatcherError, "Expected a matcher, got #{matcher.inspect}." end diff --git a/vendor/plugins/rspec/lib/spec/extensions.rb b/vendor/plugins/rspec/lib/spec/extensions.rb index 9a313d0e7..715bb49f2 100755 --- a/vendor/plugins/rspec/lib/spec/extensions.rb +++ b/vendor/plugins/rspec/lib/spec/extensions.rb @@ -1,3 +1,4 @@ require 'spec/extensions/object' require 'spec/extensions/class' require 'spec/extensions/main' +require 'spec/extensions/metaclass' diff --git a/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb b/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb new file mode 100644 index 000000000..acf9febea --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/extensions/metaclass.rb @@ -0,0 +1,7 @@ +module Spec + module MetaClass + def metaclass + class << self; self; end + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/extensions/object.rb b/vendor/plugins/rspec/lib/spec/extensions/object.rb index e9f6364e2..0b8c26fa2 100755 --- a/vendor/plugins/rspec/lib/spec/extensions/object.rb +++ b/vendor/plugins/rspec/lib/spec/extensions/object.rb @@ -3,8 +3,4 @@ class Object options = Hash === args.last ? args.pop : {} return args, options end - - def metaclass - class << self; self; end - end end diff --git a/vendor/plugins/rspec/lib/spec/interop/test.rb b/vendor/plugins/rspec/lib/spec/interop/test.rb index 5c9543398..afa16137b 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test.rb @@ -7,4 +7,6 @@ require 'spec/interop/test/unit/autorunner' require 'spec/interop/test/unit/testresult' require 'spec/interop/test/unit/ui/console/testrunner' -Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase)
\ No newline at end of file +Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase) + +Test::Unit.run = true diff --git a/vendor/plugins/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb b/vendor/plugins/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb index 663dd4722..8e9995e02 100644 --- a/vendor/plugins/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb +++ b/vendor/plugins/rspec/lib/spec/interop/test/unit/ui/console/testrunner.rb @@ -36,6 +36,7 @@ module Test alias_method :finished_without_rspec, :finished def finished_with_rspec(elapsed_time) + @ran_test ||= false if @ran_test finished_without_rspec(elapsed_time) end diff --git a/vendor/plugins/rspec/lib/spec/matchers/change.rb b/vendor/plugins/rspec/lib/spec/matchers/change.rb index 784e516ed..8f4ecc187 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/change.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/change.rb @@ -114,7 +114,7 @@ EOF # # string = "string" # lambda { - # string.reverse + # string.reverse! # }.should change { string }.from("string").to("gnirts") # # lambda { diff --git a/vendor/plugins/rspec/lib/spec/matchers/has.rb b/vendor/plugins/rspec/lib/spec/matchers/has.rb index cc5a250b8..60199f54d 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/has.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/has.rb @@ -8,24 +8,14 @@ module Spec end def matches?(target) - @target = target - begin - return target.send(predicate, *@args) - rescue => @error - # This clause should be empty, but rcov will not report it as covered - # unless something (anything) is executed within the clause - rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" - end - return false + target.send(predicate, *@args) end def failure_message - raise @error if @error "expected ##{predicate}(#{@args[0].inspect}) to return true, got false" end def negative_failure_message - raise @error if @error "expected ##{predicate}(#{@args[0].inspect}) to return false, got true" end diff --git a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb index b45dcf65c..c003849b6 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb @@ -1,50 +1,66 @@ module Spec module Matchers - class RaiseError #:nodoc: - def initialize(error_or_message=Exception, message=nil) - if String === error_or_message - @expected_error = Exception - @expected_message = error_or_message + def initialize(error_or_message=Exception, message=nil, &block) + @block = block + case error_or_message + when String, Regexp + @expected_error, @expected_message = Exception, error_or_message else - @expected_error = error_or_message - @expected_message = message + @expected_error, @expected_message = error_or_message, message end end - + def matches?(proc) @raised_expected_error = false - @raised_other = false + @with_expected_message = false + @eval_block = false + @eval_block_passed = false begin proc.call rescue @expected_error => @actual_error - if @expected_message.nil? - @raised_expected_error = true - else - case @expected_message - when Regexp - if @expected_message =~ @actual_error.message - @raised_expected_error = true - else - @raised_other = true - end - else - if @expected_message == @actual_error.message - @raised_expected_error = true - else - @raised_other = true - end - end - end - rescue => @actual_error - @raised_other = true - ensure - return @raised_expected_error + @raised_expected_error = true + @with_expected_message = verify_message + rescue Exception => @actual_error + # This clause should be empty, but rcov will not report it as covered + # unless something (anything) is executed within the clause + rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" + end + + unless negative_expectation? + eval_block if @raised_expected_error && @with_expected_message && @block + end + ensure + return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false + end + + def eval_block + @eval_block = true + begin + @block[@actual_error] + @eval_block_passed = true + rescue Exception => err + @actual_error = err + end + end + + def verify_message + case @expected_message + when nil + return true + when Regexp + return @expected_message =~ @actual_error.message + else + return @expected_message == @actual_error.message end end def failure_message - return "expected #{expected_error}#{actual_error}" if @raised_other || !@raised_expected_error + if @eval_block + return @actual_error.message + else + return "expected #{expected_error}#{actual_error}" + end end def negative_failure_message @@ -70,6 +86,11 @@ module Spec def actual_error @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}" end + + def negative_expectation? + # YES - I'm a bad person... help me find a better way - ryand + caller.first(3).find { |s| s =~ /should_not/ } + end end # :call-seq: @@ -77,6 +98,10 @@ module Spec # should raise_error(NamedError) # should raise_error(NamedError, String) # should raise_error(NamedError, Regexp) + # should raise_error() { |error| ... } + # should raise_error(NamedError) { |error| ... } + # should raise_error(NamedError, String) { |error| ... } + # should raise_error(NamedError, Regexp) { |error| ... } # should_not raise_error() # should_not raise_error(NamedError) # should_not raise_error(NamedError, String) @@ -86,11 +111,13 @@ module Spec # With a named error, matches only if that specific error is raised. # With a named error and messsage specified as a String, matches only if both match. # With a named error and messsage specified as a Regexp, matches only if both match. + # Pass an optional block to perform extra verifications on the exception matched # # == Examples # # lambda { do_something_risky }.should raise_error # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError) + # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError) { |error| error.data.should == 42 } # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, "that was too risky") # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, /oo ri/) # @@ -98,8 +125,8 @@ module Spec # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError) # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, "that was too risky") # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, /oo ri/) - def raise_error(error=Exception, message=nil) - Matchers::RaiseError.new(error, message) + def raise_error(error=Exception, message=nil, &block) + Matchers::RaiseError.new(error, message, &block) end end end diff --git a/vendor/plugins/rspec/lib/spec/mocks.rb b/vendor/plugins/rspec/lib/spec/mocks.rb index 9f9cd215b..678dd6aae 100644 --- a/vendor/plugins/rspec/lib/spec/mocks.rb +++ b/vendor/plugins/rspec/lib/spec/mocks.rb @@ -1,3 +1,4 @@ +require 'spec/mocks/framework' require 'spec/mocks/methods' require 'spec/mocks/argument_constraint_matchers' require 'spec/mocks/spec_methods' @@ -11,7 +12,6 @@ require 'spec/mocks/error_generator' require 'spec/mocks/extensions/object' require 'spec/mocks/space' - module Spec # == Mocks and Stubs # diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb index 0e4777082..96ccf0f4a 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/argument_constraint_matchers.rb @@ -1,7 +1,7 @@ module Spec module Mocks module ArgumentConstraintMatchers - + # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint def duck_type(*args) DuckTypeArgConstraint.new(*args) @@ -19,6 +19,10 @@ module Spec BooleanArgConstraint.new(nil) end + def hash_including(expected={}) + HashIncludingConstraint.new(expected) + end + def no_args NoArgsConstraint.new end diff --git a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb index 34a1d4d03..b3fdcc80d 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/argument_expectation.rb @@ -108,6 +108,32 @@ module Spec "duck_type" end end + + class HashIncludingConstraint + def initialize(expected) + @expected = expected + end + + def ==(actual) + @expected.each do | key, value | + # check key for case that value evaluates to nil + return false unless actual.has_key?(key) && actual[key] == value + end + true + rescue NoMethodError => ex + return false + end + + def matches?(value) + self == value + end + + def description + "hash_including(#{@expected.inspect.sub(/^\{/,"").sub(/\}$/,"")})" + end + + end + class ArgumentExpectation attr_reader :args diff --git a/vendor/plugins/rspec/lib/spec/mocks/extensions.rb b/vendor/plugins/rspec/lib/spec/mocks/extensions.rb new file mode 100644 index 000000000..6fd51a272 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/mocks/extensions.rb @@ -0,0 +1 @@ +require 'spec/mocks/extensions/object' diff --git a/vendor/plugins/rspec/lib/spec/mocks/framework.rb b/vendor/plugins/rspec/lib/spec/mocks/framework.rb new file mode 100644 index 000000000..92089673a --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/mocks/framework.rb @@ -0,0 +1,15 @@ +# Require everything except the global extensions of class and object. This +# supports wrapping rspec's mocking functionality without invading every +# object in the system. + +require 'spec/mocks/methods' +require 'spec/mocks/argument_constraint_matchers' +require 'spec/mocks/spec_methods' +require 'spec/mocks/proxy' +require 'spec/mocks/mock' +require 'spec/mocks/argument_expectation' +require 'spec/mocks/message_expectation' +require 'spec/mocks/order_group' +require 'spec/mocks/errors' +require 'spec/mocks/error_generator' +require 'spec/mocks/space' diff --git a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb index 6bd2f1c32..0b10290b3 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/message_expectation.rb @@ -72,12 +72,18 @@ module Spec end def invoke(args, block) + if @expected_received_count == 0 + @actual_received_count += 1 + @error_generator.raise_expectation_error @sym, @expected_received_count, @actual_received_count, *args + end + @order_group.handle_order_constraint self begin Kernel::raise @exception_to_raise unless @exception_to_raise.nil? Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil? + if !@method_block.nil? default_return_val = invoke_method_block(args) elsif @args_to_yield.size > 0 @@ -112,12 +118,14 @@ module Spec if block.nil? @error_generator.raise_missing_block_error @args_to_yield end + value = nil @args_to_yield.each do |args_to_yield_this_time| if block.arity > -1 && args_to_yield_this_time.length != block.arity @error_generator.raise_wrong_arity_error args_to_yield_this_time, block.arity end - block.call(*args_to_yield_this_time) + value = block.call(*args_to_yield_this_time) end + value end def invoke_consecutive_return_block(args, block) @@ -147,9 +155,8 @@ module Spec @sym == sym and not @args_expectation.check_args(args) end - def verify_messages_received - return if ignoring_args? || matches_exact_count? || - matches_at_least_count? || matches_at_most_count? + def verify_messages_received + return if expected_messages_received? generate_error rescue Spec::Mocks::MockExpectationError => error @@ -157,6 +164,11 @@ module Spec Kernel::raise error end + def expected_messages_received? + ignoring_args? || matches_exact_count? || + matches_at_least_count? || matches_at_most_count? + end + def ignoring_args? @expected_received_count == :any end @@ -173,8 +185,20 @@ module Spec @expected_received_count == @actual_received_count end + def similar_messages + @similar_messages ||= [] + end + + def advise(args, block) + similar_messages << args + end + def generate_error - @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args) + if similar_messages.empty? + @error_generator.raise_expectation_error(@sym, @expected_received_count, @actual_received_count, *@args_expectation.args) + else + @error_generator.raise_unexpected_message_args_error(self, *@similar_messages.first) + end end def with(*args, &block) diff --git a/vendor/plugins/rspec/lib/spec/mocks/mock.rb b/vendor/plugins/rspec/lib/spec/mocks/mock.rb index f029b1b8f..d0b5f204d 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/mock.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/mock.rb @@ -3,19 +3,21 @@ module Spec class Mock include Methods - # Creates a new mock with a +name+ (that will be used in error messages only) - # == Options: - # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it. + # Creates a new mock with a +name+ (that will be used in error messages + # only) == Options: + # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving + # null object allowing any message to be sent to it. def initialize(name, stubs_and_options={}) @name = name @options = parse_options(stubs_and_options) assign_stubs(stubs_and_options) end - # This allows for comparing the mock to other objects that proxy - # such as ActiveRecords belongs_to proxy objects - # By making the other object run the comparison, we're sure the call gets delegated to the proxy target - # This is an unfortunate side effect from ActiveRecord, but this should be safe unless the RHS redefines == in a nonsensical manner + # This allows for comparing the mock to other objects that proxy such as + # ActiveRecords belongs_to proxy objects By making the other object run + # the comparison, we're sure the call gets delegated to the proxy target + # This is an unfortunate side effect from ActiveRecord, but this should + # be safe unless the RHS redefines == in a nonsensical manner def ==(other) other == __mock_proxy end diff --git a/vendor/plugins/rspec/lib/spec/mocks/proxy.rb b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb index 03db3b113..45b96a30b 100644 --- a/vendor/plugins/rspec/lib/spec/mocks/proxy.rb +++ b/vendor/plugins/rspec/lib/spec/mocks/proxy.rb @@ -63,10 +63,14 @@ module Spec def message_received(sym, *args, &block) if expectation = find_matching_expectation(sym, *args) expectation.invoke(args, block) - elsif stub = find_matching_method_stub(sym, *args) + elsif (stub = find_matching_method_stub(sym, *args)) + if expectation = find_almost_matching_expectation(sym, *args) + expectation.advise(args, block) unless expectation.expected_messages_received? + end stub.invoke([], block) elsif expectation = find_almost_matching_expectation(sym, *args) - raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object? + expectation.advise(args, block) if null_object? unless expectation.expected_messages_received? + raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?) else @target.send :method_missing, sym, *args, &block end @@ -88,18 +92,20 @@ module Spec end def define_expected_method(sym) - if target_responds_to?(sym) && !metaclass.method_defined?(munge(sym)) + visibility_string = "#{visibility(sym)} :#{sym}" + if target_responds_to?(sym) && !target_metaclass.method_defined?(munge(sym)) munged_sym = munge(sym) - metaclass.instance_eval do + target_metaclass.instance_eval do alias_method munged_sym, sym if method_defined?(sym.to_s) end @proxied_methods << sym end - metaclass_eval(<<-EOF, __FILE__, __LINE__) + target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__) def #{sym}(*args, &block) __mock_proxy.message_received :#{sym}, *args, &block end + #{visibility_string} EOF end @@ -109,6 +115,18 @@ module Spec return @target.respond_to?(sym) end + def visibility(sym) + if Mock === @target + 'public' + elsif target_metaclass.private_method_defined?(sym) + 'private' + elsif target_metaclass.protected_method_defined?(sym) + 'protected' + else + 'public' + end + end + def munge(sym) "proxied_by_rspec__#{sym.to_s}".to_sym end @@ -125,12 +143,8 @@ module Spec @proxied_methods.clear end - def metaclass_eval(str, filename, lineno) - metaclass.class_eval(str, filename, lineno) - end - - def metaclass - (class << @target; self; end) + def target_metaclass + class << @target; self; end end def verify_expectations @@ -142,7 +156,7 @@ module Spec def reset_proxied_methods @proxied_methods.each do |sym| munged_sym = munge(sym) - metaclass.instance_eval do + target_metaclass.instance_eval do if method_defined?(munged_sym.to_s) alias_method sym, munged_sym undef_method munged_sym diff --git a/vendor/plugins/rspec/lib/spec/rake/spectask.rb b/vendor/plugins/rspec/lib/spec/rake/spectask.rb index c59e226f5..ecf39506d 100644 --- a/vendor/plugins/rspec/lib/spec/rake/spectask.rb +++ b/vendor/plugins/rspec/lib/spec/rake/spectask.rb @@ -11,7 +11,7 @@ module Spec # A Rake task that runs a set of specs. # # Example: - # + # # Spec::Rake::SpecTask.new do |t| # t.warning = true # t.rcov = true @@ -87,7 +87,7 @@ module Spec # Whether or not to use RCov (default is false) # See http://eigenclass.org/hiki.rb?rcov attr_accessor :rcov - + # Array of commandline options to pass to RCov. Defaults to ['--exclude', 'lib\/spec,bin\/spec']. # Ignored if rcov=false # Setting the RCOV_OPTS environment variable overrides this. @@ -117,7 +117,7 @@ module Spec # used, then the list of spec files is the union of the two. # Setting the SPEC environment variable overrides this. attr_accessor :spec_files - + # Use verbose output. If this is set to true, the task will print # the executed spec command to stdout. Defaults to false. attr_accessor :verbose @@ -155,7 +155,7 @@ module Spec # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts] # or # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts] - cmd = "ruby " + cmd = "#{File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])} " rb_opts = ruby_opts.clone rb_opts << "-I\"#{lib_path}\"" @@ -210,7 +210,7 @@ module Spec STDERR.puts "RSPECOPTS is DEPRECATED and will be removed in a future version. Use SPEC_OPTS instead." if ENV['RSPECOPTS'] ENV['SPEC_OPTS'] || ENV['RSPECOPTS'] || spec_opts.join(" ") || "" end - + def evaluate(o) # :nodoc: case o when Proc then o.call diff --git a/vendor/plugins/rspec/lib/spec/runner.rb b/vendor/plugins/rspec/lib/spec/runner.rb index 1a9373fee..97ef95bd2 100644 --- a/vendor/plugins/rspec/lib/spec/runner.rb +++ b/vendor/plugins/rspec/lib/spec/runner.rb @@ -183,6 +183,20 @@ module Spec def configure yield configuration end + + def register_at_exit_hook # :nodoc: + $spec_runner_at_exit_hook_registered ||= nil + unless $spec_runner_at_exit_hook_registered + at_exit do + unless $! || Spec.run?; \ + success = Spec.run; \ + exit success if Spec.exit?; \ + end + end + $spec_runner_at_exit_hook_registered = true + end + end + end end end 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 diff --git a/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb b/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb index 7955b4c33..8ee338605 100644 --- a/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb +++ b/vendor/plugins/rspec/lib/spec/story/extensions/regexp.rb @@ -1,9 +1,9 @@ class Regexp def step_name - self.source + self.source.gsub '\\$', '$$' end def arg_regexp ::Spec::Story::Step::PARAM_OR_GROUP_PATTERN end -end
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/story/extensions/string.rb b/vendor/plugins/rspec/lib/spec/story/extensions/string.rb index 896578def..0e4ec1d68 100644 --- a/vendor/plugins/rspec/lib/spec/story/extensions/string.rb +++ b/vendor/plugins/rspec/lib/spec/story/extensions/string.rb @@ -4,6 +4,6 @@ class String end def arg_regexp - ::Spec::Story::Step::PARAM_PATTERN + ::Spec::Story::Step::PARAM_OR_GROUP_PATTERN end -end
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/story/runner.rb b/vendor/plugins/rspec/lib/spec/story/runner.rb index 2dd36fbc6..3d7ed59b5 100644 --- a/vendor/plugins/rspec/lib/spec/story/runner.rb +++ b/vendor/plugins/rspec/lib/spec/story/runner.rb @@ -10,16 +10,17 @@ module Spec module Runner class << self def run_options # :nodoc: - @run_options ||= ::Spec::Runner::OptionParser.parse(ARGV, $stderr, $stdout) + rspec_options + # @run_options ||= ::Spec::Runner::OptionParser.parse(ARGV, $stderr, $stdout) end def story_runner # :nodoc: unless @story_runner - @story_runner = StoryRunner.new(scenario_runner, world_creator) + @story_runner = create_story_runner run_options.story_formatters.each do |formatter| register_listener(formatter) end - Runner.register_exit_hook + self.register_exit_hook end @story_runner end @@ -32,6 +33,10 @@ module Spec @world_creator ||= World end + def create_story_runner + StoryRunner.new(scenario_runner, world_creator) + end + # Use this to register a customer output formatter. def register_listener(listener) story_runner.add_listener(listener) # run_started, story_started, story_ended, #run_ended @@ -40,12 +45,9 @@ module Spec end def register_exit_hook # :nodoc: - # TODO - when story runner uses test/unit runners like example runner does we can kill - # this and also the assorted Kernel.stub!(:at_exit) in examples at_exit do - Runner.story_runner.run_stories unless $! + exit Runner.story_runner.run_stories unless $! end - # TODO exit with non-zero status if run fails end def dry_run diff --git a/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb index 8d34ea2d2..a1bfbda4f 100644 --- a/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb +++ b/vendor/plugins/rspec/lib/spec/story/runner/plain_text_story_runner.rb @@ -26,9 +26,9 @@ module Spec @story_file = path end - def run + def run(story_runner=Spec::Story::Runner.story_runner) raise "You must set a path to the file with the story. See the RDoc." if @story_file.nil? - mediator = Spec::Story::Runner::StoryMediator.new(steps, Spec::Story::Runner.story_runner, @options) + mediator = Spec::Story::Runner::StoryMediator.new(steps, story_runner, @options) parser = Spec::Story::Runner::StoryParser.new(mediator) story_text = File.read(@story_file) diff --git a/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb index aee52e412..2d7c58d03 100644 --- a/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb +++ b/vendor/plugins/rspec/lib/spec/story/runner/scenario_runner.rb @@ -11,6 +11,12 @@ module Spec run_story_ignoring_scenarios(scenario.story, world) world.start_collecting_errors + + unless scenario.body + @listeners.each { |l| l.scenario_pending(scenario.story.title, scenario.name, '') } + return true + end + world.instance_eval(&scenario.body) if world.errors.empty? @listeners.each { |l| l.scenario_succeeded(scenario.story.title, scenario.name) } @@ -19,8 +25,10 @@ module Spec @listeners.each { |l| l.scenario_pending(scenario.story.title, scenario.name, e.message) } else @listeners.each { |l| l.scenario_failed(scenario.story.title, scenario.name, e) } + return false end end + true end def add_listener(listener) diff --git a/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb b/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb index 1f4744b9f..826f322ee 100644 --- a/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb +++ b/vendor/plugins/rspec/lib/spec/story/runner/story_mediator.rb @@ -64,7 +64,7 @@ title = @title narrative = @narrative scenarios = @scenarios.collect { |scenario| scenario.to_proc } - options = @options.merge(:steps => @step_group) + options = @options.merge(:steps_for => @step_group) lambda do Story title, narrative, options do scenarios.each { |scenario| instance_eval(&scenario) } diff --git a/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb b/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb index f9eeb9ac1..a63479783 100644 --- a/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb +++ b/vendor/plugins/rspec/lib/spec/story/runner/story_runner.rb @@ -36,6 +36,7 @@ module Spec def run_stories return if @stories.empty? @listeners.each { |l| l.run_started(scenarios.size) } + success = true @stories.each do |story| story.assign_steps_to(World) @current_story = story @@ -45,7 +46,7 @@ module Spec type = story[:type] || Object args = story[:args] || [] world = @world_creator.create(type, *args) - @scenario_runner.run(scenario, world) + success = success & @scenario_runner.run(scenario, world) end @listeners.each { |l| l.story_ended(story.title, story.narrative) } World.step_mother.clear @@ -53,6 +54,7 @@ module Spec unique_steps = (World.step_names.collect {|n| Regexp === n ? n.source : n.to_s}).uniq.sort @listeners.each { |l| l.collected_steps(unique_steps) } @listeners.each { |l| l.run_ended } + return success end def add_listener(listener) diff --git a/vendor/plugins/rspec/lib/spec/story/step.rb b/vendor/plugins/rspec/lib/spec/story/step.rb index 1d596e92c..5cd8765d6 100644 --- a/vendor/plugins/rspec/lib/spec/story/step.rb +++ b/vendor/plugins/rspec/lib/spec/story/step.rb @@ -1,8 +1,8 @@ module Spec module Story class Step - PARAM_PATTERN = /(\$\w*)/ - PARAM_OR_GROUP_PATTERN = /(\$\w*)|\(.*?\)/ + PARAM_PATTERN = /([^\\]|^)(\$(?!\$)\w*)/ + PARAM_OR_GROUP_PATTERN = /(\$(?!\$)\w*)|\(.*?\)/ attr_reader :name def initialize(name, &block) @@ -39,18 +39,20 @@ module Spec private - def assign_expression(name) - expression = name.dup - if String === expression + def assign_expression(string_or_regexp) + if String === string_or_regexp + expression = string_or_regexp.dup expression.gsub! '(', '\(' expression.gsub! ')', '\)' - while expression =~ PARAM_PATTERN - expression.gsub!($1, "(.*?)") - end + elsif Regexp === string_or_regexp + expression = string_or_regexp.source + end + while expression =~ PARAM_PATTERN + expression.gsub!($2, "(.*?)") end @expression = Regexp.new("^#{expression}$") end end end -end
\ No newline at end of file +end diff --git a/vendor/plugins/rspec/lib/spec/story/story.rb b/vendor/plugins/rspec/lib/spec/story/story.rb index 112e9414b..9cd1a0fec 100644 --- a/vendor/plugins/rspec/lib/spec/story/story.rb +++ b/vendor/plugins/rspec/lib/spec/story/story.rb @@ -19,17 +19,14 @@ module Spec end def assign_steps_to(assignee) - if @params[:steps] - assignee.use(@params[:steps]) - else - case keys = @params[:steps_for] - when Symbol - keys = [keys] - when nil - keys = [] - end - keys.each do |key| - assignee.use(steps_for(key)) + if steps=@params[:steps_for] + steps = [steps] unless steps.is_a?(Array) + steps.each do |step| + if step.is_a?(StepGroup) + assignee.use(step) + else + assignee.use(steps_for(step)) + end end end end diff --git a/vendor/plugins/rspec/lib/spec/story/world.rb b/vendor/plugins/rspec/lib/spec/story/world.rb index 6296537b8..a27d3dda9 100644 --- a/vendor/plugins/rspec/lib/spec/story/world.rb +++ b/vendor/plugins/rspec/lib/spec/story/world.rb @@ -1,4 +1,3 @@ -require 'rubygems' require 'spec/expectations' require 'spec/matchers' require 'spec/example/pending' @@ -70,6 +69,7 @@ module Spec # story_server/prototype/rspec_stories.html (generated by rake stories) args = step.parse_args(name) if args.empty? begin + listeners.each { |l| l.step_upcoming(type, step_name, *args) } step.perform(world, *args) unless ::Spec::Story::Runner.dry_run listeners.each { |l| l.step_succeeded(type, step_name, *args) } rescue Exception => e diff --git a/vendor/plugins/rspec/lib/spec/version.rb b/vendor/plugins/rspec/lib/spec/version.rb index f83a4c697..959bf5189 100644 --- a/vendor/plugins/rspec/lib/spec/version.rb +++ b/vendor/plugins/rspec/lib/spec/version.rb @@ -1,22 +1,22 @@ -module Spec - module VERSION - unless defined? MAJOR - MAJOR = 1 - MINOR = 1 - TINY = 2 - RELEASE_CANDIDATE = nil - - BUILD_TIME_UTC = 20080114022430 - - STRING = [MAJOR, MINOR, TINY].join('.') - TAG = "REL_#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('_')}".upcase.gsub(/\.|-/, '_') - FULL_VERSION = "#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('.')} (build #{BUILD_TIME_UTC})" - - NAME = "RSpec" - URL = "http://rspec.rubyforge.org/" - - DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}" - end - end -end - +module Spec
+ module VERSION
+ unless defined? MAJOR
+ MAJOR = 1
+ MINOR = 1
+ TINY = 4
+ RELEASE_CANDIDATE = nil
+
+ BUILD_TIME_UTC = 20080526202855
+
+ STRING = [MAJOR, MINOR, TINY].join('.')
+ TAG = "REL_#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('_')}".upcase.gsub(/\.|-/, '_')
+ FULL_VERSION = "#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('.')} (build #{BUILD_TIME_UTC})"
+
+ NAME = "RSpec"
+ URL = "http://rspec.rubyforge.org/"
+
+ DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}"
+ end
+ end
+end
+
|