rspec-core 2.10.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changelog.md +35 -2
- data/README.md +14 -13
- data/features/command_line/example_name_option.feature +15 -0
- data/features/helper_methods/modules.feature +3 -3
- data/lib/rspec/core.rb +6 -2
- data/lib/rspec/core/configuration.rb +61 -26
- data/lib/rspec/core/configuration_options.rb +5 -1
- data/lib/rspec/core/deprecation.rb +0 -15
- data/lib/rspec/core/drb_command_line.rb +3 -0
- data/lib/rspec/core/drb_options.rb +3 -1
- data/lib/rspec/core/dsl.rb +4 -2
- data/lib/rspec/core/example.rb +85 -23
- data/lib/rspec/core/example_group.rb +103 -78
- data/lib/rspec/core/hooks.rb +68 -33
- data/lib/rspec/core/let.rb +0 -1
- data/lib/rspec/core/mocking/with_mocha.rb +10 -4
- data/lib/rspec/core/option_parser.rb +3 -2
- data/lib/rspec/core/project_initializer.rb +7 -1
- data/lib/rspec/core/runner.rb +2 -2
- data/lib/rspec/core/shared_context.rb +2 -2
- data/lib/rspec/core/shared_example_group.rb +38 -14
- data/lib/rspec/core/subject.rb +67 -52
- data/lib/rspec/core/version.rb +1 -1
- data/spec/rspec/core/command_line_spec.rb +68 -126
- data/spec/rspec/core/configuration_options_spec.rb +20 -4
- data/spec/rspec/core/configuration_spec.rb +61 -21
- data/spec/rspec/core/drb_command_line_spec.rb +1 -0
- data/spec/rspec/core/drb_options_spec.rb +1 -0
- data/spec/rspec/core/dsl_spec.rb +17 -0
- data/spec/rspec/core/example_group_spec.rb +19 -11
- data/spec/rspec/core/example_spec.rb +34 -0
- data/spec/rspec/core/option_parser_spec.rb +2 -1
- data/spec/rspec/core/shared_example_group_spec.rb +9 -9
- data/spec/rspec/core/subject_spec.rb +14 -0
- data/spec/rspec/core_spec.rb +18 -8
- data/spec/spec_helper.rb +1 -2
- metadata +7 -5
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            module RSpec
         | 
| 2 2 | 
             
              module Core
         | 
| 3 | 
            -
                # ExampleGroup and Example are the main structural elements of | 
| 4 | 
            -
                # Consider this example:
         | 
| 3 | 
            +
                # ExampleGroup and {Example} are the main structural elements of
         | 
| 4 | 
            +
                # rspec-core.  Consider this example:
         | 
| 5 5 | 
             
                #
         | 
| 6 6 | 
             
                #     describe Thing do
         | 
| 7 7 | 
             
                #       it "does something" do
         | 
| @@ -47,81 +47,118 @@ module RSpec | |
| 47 47 | 
             
                    alias_method :display_name, :description
         | 
| 48 48 | 
             
                    # @private
         | 
| 49 49 | 
             
                    alias_method :describes, :described_class
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  # @private
         | 
| 53 | 
            -
                  def self.define_example_method(name, extra_options={})
         | 
| 54 | 
            -
                    module_eval(<<-END_RUBY, __FILE__, __LINE__)
         | 
| 55 | 
            -
                      def self.#{name}(desc=nil, *args, &block)
         | 
| 56 | 
            -
                        options = build_metadata_hash_from(args)
         | 
| 57 | 
            -
                        options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
         | 
| 58 | 
            -
                        options.update(#{extra_options.inspect})
         | 
| 59 | 
            -
                        examples << RSpec::Core::Example.new(self, desc, options, block)
         | 
| 60 | 
            -
                        examples.last
         | 
| 61 | 
            -
                      end
         | 
| 62 | 
            -
                    END_RUBY
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  define_example_method :example
         | 
| 66 | 
            -
                  define_example_method :it
         | 
| 67 | 
            -
                  define_example_method :specify
         | 
| 68 50 |  | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 51 | 
            +
                    # @private
         | 
| 52 | 
            +
                    # @macro [attach] define_example_method
         | 
| 53 | 
            +
                    #   @param [String] name
         | 
| 54 | 
            +
                    #   @param [Hash] extra_options
         | 
| 55 | 
            +
                    #   @param [Block] implementation
         | 
| 56 | 
            +
                    def self.define_example_method(name, extra_options={})
         | 
| 57 | 
            +
                      module_eval(<<-END_RUBY, __FILE__, __LINE__)
         | 
| 58 | 
            +
                        def #{name}(desc=nil, *args, &block)
         | 
| 59 | 
            +
                          options = build_metadata_hash_from(args)
         | 
| 60 | 
            +
                          options.update(:pending => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
         | 
| 61 | 
            +
                          options.update(#{extra_options.inspect})
         | 
| 62 | 
            +
                          examples << RSpec::Core::Example.new(self, desc, options, block)
         | 
| 63 | 
            +
                          examples.last
         | 
| 64 | 
            +
                        end
         | 
| 65 | 
            +
                      END_RUBY
         | 
| 66 | 
            +
                    end
         | 
| 76 67 |  | 
| 77 | 
            -
             | 
| 78 | 
            -
                     | 
| 79 | 
            -
             | 
| 68 | 
            +
                    # Defines an example within a group.
         | 
| 69 | 
            +
                    define_example_method :example
         | 
| 70 | 
            +
                    # Defines an example within a group.
         | 
| 71 | 
            +
                    #
         | 
| 72 | 
            +
                    # @see example
         | 
| 73 | 
            +
                    define_example_method :it
         | 
| 74 | 
            +
                    # Defines an example within a group.
         | 
| 75 | 
            +
                    # This is here primarily for backward compatibility with early versions
         | 
| 76 | 
            +
                    # of RSpec which used `context` and `specify` instead of `describe` and
         | 
| 77 | 
            +
                    # `it`.
         | 
| 78 | 
            +
                    define_example_method :specify
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    # Shortcut to define an example with `:focus` => true
         | 
| 81 | 
            +
                    define_example_method :focus,   :focused => true, :focus => true
         | 
| 82 | 
            +
                    # Shortcut to define an example with `:focus` => true
         | 
| 83 | 
            +
                    define_example_method :focused, :focused => true, :focus => true
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                    # Shortcut to define an example with :pending => true
         | 
| 86 | 
            +
                    define_example_method :pending,  :pending => true
         | 
| 87 | 
            +
                    # Shortcut to define an example with :pending => 'Temporarily disabled with xexample'
         | 
| 88 | 
            +
                    define_example_method :xexample, :pending => 'Temporarily disabled with xexample'
         | 
| 89 | 
            +
                    # Shortcut to define an example with :pending => 'Temporarily disabled with xit'
         | 
| 90 | 
            +
                    define_example_method :xit,      :pending => 'Temporarily disabled with xit'
         | 
| 91 | 
            +
                    # Shortcut to define an example with :pending => 'Temporarily disabled with xspecify'
         | 
| 92 | 
            +
                    define_example_method :xspecify, :pending => 'Temporarily disabled with xspecify'
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                    # Works like `alias_method :name, :example` with the added benefit of
         | 
| 95 | 
            +
                    # assigning default metadata to the generated example.
         | 
| 96 | 
            +
                    #
         | 
| 97 | 
            +
                    # @note Use with caution. This extends the language used in your
         | 
| 98 | 
            +
                    #   specs, but does not add any additional documentation.  We use this
         | 
| 99 | 
            +
                    #   in rspec to define methods like `focus` and `xit`, but we also add
         | 
| 100 | 
            +
                    #   docs for those methods.
         | 
| 101 | 
            +
                    def alias_example_to name, extra={}
         | 
| 102 | 
            +
                      (class << self; self; end).define_example_method name, extra
         | 
| 103 | 
            +
                    end
         | 
| 80 104 |  | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
                     | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 105 | 
            +
                    # @private
         | 
| 106 | 
            +
                    # @macro [attach] define_nested_shared_group_method
         | 
| 107 | 
            +
                    #
         | 
| 108 | 
            +
                    #   @see SharedExampleGroup
         | 
| 109 | 
            +
                    def self.define_nested_shared_group_method(new_name, report_label=nil)
         | 
| 110 | 
            +
                      module_eval(<<-END_RUBY, __FILE__, __LINE__)
         | 
| 111 | 
            +
                        def #{new_name}(name, *args, &customization_block)
         | 
| 112 | 
            +
                          group = describe("#{report_label || "it should behave like"} \#{name}") do
         | 
| 113 | 
            +
                            find_and_eval_shared("examples", name, *args, &customization_block)
         | 
| 114 | 
            +
                          end
         | 
| 115 | 
            +
                          group.metadata[:shared_group_name] = name
         | 
| 116 | 
            +
                          group
         | 
| 87 117 | 
             
                        end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
                      end
         | 
| 91 | 
            -
                    END_RUBY
         | 
| 92 | 
            -
                  end
         | 
| 93 | 
            -
             | 
| 94 | 
            -
                  define_nested_shared_group_method :it_should_behave_like
         | 
| 118 | 
            +
                      END_RUBY
         | 
| 119 | 
            +
                    end
         | 
| 95 120 |  | 
| 96 | 
            -
             | 
| 97 | 
            -
                     | 
| 121 | 
            +
                    # Generates a nested example group and includes the shared content
         | 
| 122 | 
            +
                    # mapped to `name` in the nested group.
         | 
| 123 | 
            +
                    define_nested_shared_group_method :it_behaves_like, "behaves like"
         | 
| 124 | 
            +
                    # Generates a nested example group and includes the shared content
         | 
| 125 | 
            +
                    # mapped to `name` in the nested group.
         | 
| 126 | 
            +
                    define_nested_shared_group_method :it_should_behave_like
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    # Works like `alias_method :name, :it_behaves_like` with the added
         | 
| 129 | 
            +
                    # benefit of assigning default metadata to the generated example.
         | 
| 130 | 
            +
                    #
         | 
| 131 | 
            +
                    # @note Use with caution. This extends the language used in your
         | 
| 132 | 
            +
                    #   specs, but does not add any additional documentation.  We use this
         | 
| 133 | 
            +
                    #   in rspec to define `it_should_behave_like` (for backward
         | 
| 134 | 
            +
                    #   compatibility), but we also add docs for that method.
         | 
| 135 | 
            +
                    def alias_it_behaves_like_to name, *args, &block
         | 
| 136 | 
            +
                      (class << self; self; end).define_nested_shared_group_method name, *args, &block
         | 
| 137 | 
            +
                    end
         | 
| 98 138 | 
             
                  end
         | 
| 99 139 |  | 
| 100 | 
            -
                   | 
| 101 | 
            -
             | 
| 102 | 
            -
                  #  | 
| 140 | 
            +
                  # Includes shared content mapped to `name` directly in the group in which
         | 
| 141 | 
            +
                  # it is declared, as opposed to `it_behaves_like`, which creates a nested
         | 
| 142 | 
            +
                  # group. If given a block, that block is also eval'd in the current context.
         | 
| 103 143 | 
             
                  #
         | 
| 104 144 | 
             
                  # @see SharedExampleGroup
         | 
| 105 | 
            -
                  def self.include_context(name, *args)
         | 
| 106 | 
            -
                     | 
| 145 | 
            +
                  def self.include_context(name, *args, &block)
         | 
| 146 | 
            +
                    find_and_eval_shared("context", name, *args, &block)
         | 
| 107 147 | 
             
                  end
         | 
| 108 148 |  | 
| 109 | 
            -
                  # Includes shared content  | 
| 149 | 
            +
                  # Includes shared content mapped to `name` directly in the group in which
         | 
| 150 | 
            +
                  # it is declared, as opposed to `it_behaves_like`, which creates a nested
         | 
| 151 | 
            +
                  # group. If given a block, that block is also eval'd in the current context.
         | 
| 110 152 | 
             
                  #
         | 
| 111 153 | 
             
                  # @see SharedExampleGroup
         | 
| 112 | 
            -
                  def self.include_examples(name, *args)
         | 
| 113 | 
            -
                     | 
| 114 | 
            -
                  end
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                  # @private
         | 
| 117 | 
            -
                  def self.block_not_supported(label)
         | 
| 118 | 
            -
                    warn("Customization blocks not supported for include_#{label}.  Use it_behaves_like instead.")
         | 
| 154 | 
            +
                  def self.include_examples(name, *args, &block)
         | 
| 155 | 
            +
                    find_and_eval_shared("examples", name, *args, &block)
         | 
| 119 156 | 
             
                  end
         | 
| 120 157 |  | 
| 121 158 | 
             
                  # @private
         | 
| 122 159 | 
             
                  def self.find_and_eval_shared(label, name, *args, &customization_block)
         | 
| 123 160 | 
             
                    raise ArgumentError, "Could not find shared #{label} #{name.inspect}" unless
         | 
| 124 | 
            -
             | 
| 161 | 
            +
                    shared_block = world.shared_example_groups[name]
         | 
| 125 162 |  | 
| 126 163 | 
             
                    module_eval_with_args(*args, &shared_block)
         | 
| 127 164 | 
             
                    module_eval(&customization_block) if customization_block
         | 
| @@ -149,7 +186,7 @@ module RSpec | |
| 149 186 | 
             
                  end
         | 
| 150 187 |  | 
| 151 188 | 
             
                  # @private
         | 
| 152 | 
            -
                  # @return [Metadata] belonging to the parent of a nested  | 
| 189 | 
            +
                  # @return [Metadata] belonging to the parent of a nested {ExampleGroup}
         | 
| 153 190 | 
             
                  def self.superclass_metadata
         | 
| 154 191 | 
             
                    @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
         | 
| 155 192 | 
             
                  end
         | 
| @@ -247,19 +284,7 @@ module RSpec | |
| 247 284 | 
             
                    args.unshift(symbol_description) if symbol_description
         | 
| 248 285 | 
             
                    @metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
         | 
| 249 286 | 
             
                    world.configure_group(self)
         | 
| 250 | 
            -
                     | 
| 251 | 
            -
                      RSpec.configuration.hooks[_when][:each].each do |hook|
         | 
| 252 | 
            -
                        unless ancestors.any? {|a| a.hooks[_when][:each].include? hook }
         | 
| 253 | 
            -
                          hooks[_when][:each] << hook # each's get filtered later per example
         | 
| 254 | 
            -
                        end
         | 
| 255 | 
            -
                      end
         | 
| 256 | 
            -
                      next if _when == :around # no around(:all) hooks
         | 
| 257 | 
            -
                      RSpec.configuration.hooks[_when][:all].each do |hook|
         | 
| 258 | 
            -
                        unless ancestors.any? {|a| a.hooks[_when][:all].include? hook }
         | 
| 259 | 
            -
                          hooks[_when][:all] << hook if hook.options_apply?(self)
         | 
| 260 | 
            -
                        end
         | 
| 261 | 
            -
                      end
         | 
| 262 | 
            -
                    end
         | 
| 287 | 
            +
                    hooks.register_globals(self, RSpec.configuration.hooks)
         | 
| 263 288 | 
             
                  end
         | 
| 264 289 |  | 
| 265 290 | 
             
                  # @private
         | 
| @@ -318,7 +343,7 @@ An error occurred in an after(:all) hook. | |
| 318 343 | 
             
              #{e.class}: #{e.message}
         | 
| 319 344 | 
             
              occurred at #{e.backtrace.first}
         | 
| 320 345 |  | 
| 321 | 
            -
             | 
| 346 | 
            +
                  EOS
         | 
| 322 347 | 
             
                    end
         | 
| 323 348 | 
             
                  end
         | 
| 324 349 |  | 
| @@ -401,11 +426,11 @@ An error occurred in an after(:all) hook. | |
| 401 426 | 
             
                  end
         | 
| 402 427 |  | 
| 403 428 | 
             
                  # @attr_reader
         | 
| 404 | 
            -
                  # Returns the  | 
| 429 | 
            +
                  # Returns the {Example} object that wraps this instance of
         | 
| 405 430 | 
             
                  # `ExampleGroup`
         | 
| 406 431 | 
             
                  attr_accessor :example
         | 
| 407 432 |  | 
| 408 | 
            -
                  # @deprecated use  | 
| 433 | 
            +
                  # @deprecated use {ExampleGroup#example}
         | 
| 409 434 | 
             
                  def running_example
         | 
| 410 435 | 
             
                    RSpec.deprecate("running_example", "example")
         | 
| 411 436 | 
             
                    example
         | 
| @@ -428,12 +453,12 @@ An error occurred in an after(:all) hook. | |
| 428 453 | 
             
                  # @private
         | 
| 429 454 | 
             
                  # instance_evals the block, capturing and reporting an exception if
         | 
| 430 455 | 
             
                  # raised
         | 
| 431 | 
            -
                  def instance_eval_with_rescue(&hook)
         | 
| 456 | 
            +
                  def instance_eval_with_rescue(context = nil, &hook)
         | 
| 432 457 | 
             
                    begin
         | 
| 433 458 | 
             
                      instance_eval(&hook)
         | 
| 434 459 | 
             
                    rescue Exception => e
         | 
| 435 460 | 
             
                      raise unless example
         | 
| 436 | 
            -
                      example.set_exception(e)
         | 
| 461 | 
            +
                      example.set_exception(e, context)
         | 
| 437 462 | 
             
                    end
         | 
| 438 463 | 
             
                  end
         | 
| 439 464 | 
             
                end
         | 
    
        data/lib/rspec/core/hooks.rb
    CHANGED
    
    | @@ -32,7 +32,7 @@ module RSpec | |
| 32 32 | 
             
                    include HookExtension
         | 
| 33 33 |  | 
| 34 34 | 
             
                    def run(example)
         | 
| 35 | 
            -
                      example.instance_eval_with_rescue(&self)
         | 
| 35 | 
            +
                      example.instance_eval_with_rescue("in an after hook", &self)
         | 
| 36 36 | 
             
                    end
         | 
| 37 37 |  | 
| 38 38 | 
             
                    def display_name
         | 
| @@ -48,7 +48,16 @@ module RSpec | |
| 48 48 | 
             
                    end
         | 
| 49 49 | 
             
                  end
         | 
| 50 50 |  | 
| 51 | 
            +
                  module HookCollectionAliases
         | 
| 52 | 
            +
                    def self.included(host)
         | 
| 53 | 
            +
                      host.send :alias_method, :prepend, :unshift
         | 
| 54 | 
            +
                      host.send :alias_method, :append,  :push
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 51 58 | 
             
                  class HookCollection < Array
         | 
| 59 | 
            +
                    include HookCollectionAliases
         | 
| 60 | 
            +
             | 
| 52 61 | 
             
                    def for(example_or_group)
         | 
| 53 62 | 
             
                      self.class.new(select {|hook| hook.options_apply?(example_or_group)}).
         | 
| 54 63 | 
             
                        with(example_or_group)
         | 
| @@ -64,18 +73,9 @@ module RSpec | |
| 64 73 | 
             
                    end
         | 
| 65 74 | 
             
                  end
         | 
| 66 75 |  | 
| 67 | 
            -
                  class GroupHookCollection < Array
         | 
| 68 | 
            -
                    def for(group)
         | 
| 69 | 
            -
                      @group = group
         | 
| 70 | 
            -
                      self
         | 
| 71 | 
            -
                    end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                    def run
         | 
| 74 | 
            -
                      shift.run(@group) until empty?
         | 
| 75 | 
            -
                    end
         | 
| 76 | 
            -
                  end
         | 
| 77 | 
            -
             | 
| 78 76 | 
             
                  class AroundHookCollection < Array
         | 
| 77 | 
            +
                    include HookCollectionAliases
         | 
| 78 | 
            +
             | 
| 79 79 | 
             
                    def for(example, initial_procsy=nil)
         | 
| 80 80 | 
             
                      self.class.new(select {|hook| hook.options_apply?(example)}).
         | 
| 81 81 | 
             
                        with(example, initial_procsy)
         | 
| @@ -96,13 +96,43 @@ module RSpec | |
| 96 96 | 
             
                    end
         | 
| 97 97 | 
             
                  end
         | 
| 98 98 |  | 
| 99 | 
            +
                  class GroupHookCollection < Array
         | 
| 100 | 
            +
                    def for(group)
         | 
| 101 | 
            +
                      @group = group
         | 
| 102 | 
            +
                      self
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    def run
         | 
| 106 | 
            +
                      shift.run(@group) until empty?
         | 
| 107 | 
            +
                    end
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  module RegistersGlobals
         | 
| 111 | 
            +
                    def register_globals host, globals
         | 
| 112 | 
            +
                      [:before, :after, :around].each do |position|
         | 
| 113 | 
            +
                        process host, globals, position, :each
         | 
| 114 | 
            +
                        next if position == :around # no around(:all) hooks
         | 
| 115 | 
            +
                        process host, globals, position, :all
         | 
| 116 | 
            +
                      end
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                    private
         | 
| 120 | 
            +
                    def process host, globals, position, scope
         | 
| 121 | 
            +
                      globals[position][scope].each do |hook|
         | 
| 122 | 
            +
                        unless host.ancestors.any? { |a| a.hooks[position][scope].include? hook }
         | 
| 123 | 
            +
                          self[position][scope] << hook if scope == :each || hook.options_apply?(host)
         | 
| 124 | 
            +
                        end
         | 
| 125 | 
            +
                      end
         | 
| 126 | 
            +
                    end
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
             | 
| 99 129 | 
             
                  # @private
         | 
| 100 130 | 
             
                  def hooks
         | 
| 101 131 | 
             
                    @hooks ||= {
         | 
| 102 132 | 
             
                      :around => { :each => AroundHookCollection.new },
         | 
| 103 | 
            -
                      :before => { :each =>  | 
| 104 | 
            -
                      :after =>  { :each =>  | 
| 105 | 
            -
                    }
         | 
| 133 | 
            +
                      :before => { :each => HookCollection.new, :all => HookCollection.new, :suite => HookCollection.new },
         | 
| 134 | 
            +
                      :after =>  { :each => HookCollection.new, :all => HookCollection.new, :suite => HookCollection.new }
         | 
| 135 | 
            +
                    }.extend(RegistersGlobals)
         | 
| 106 136 | 
             
                  end
         | 
| 107 137 |  | 
| 108 138 | 
             
                  # @api public
         | 
| @@ -126,12 +156,11 @@ module RSpec | |
| 126 156 | 
             
                  #
         | 
| 127 157 | 
             
                  # Declare a block of code to be run before each example (using `:each`)
         | 
| 128 158 | 
             
                  # or once before any example (using `:all`). These are usually declared
         | 
| 129 | 
            -
                  # directly in the  | 
| 130 | 
            -
                  #  | 
| 159 | 
            +
                  # directly in the {ExampleGroup} to which they apply, but they can also
         | 
| 160 | 
            +
                  # be shared across multiple groups.
         | 
| 131 161 | 
             
                  #
         | 
| 132 162 | 
             
                  # You can also use `before(:suite)` to run a block of code before any
         | 
| 133 | 
            -
                  # example groups are run. This should be declared in
         | 
| 134 | 
            -
                  # [RSpec.configure](../../RSpec#configure-class_method)
         | 
| 163 | 
            +
                  # example groups are run. This should be declared in {RSpec.configure}
         | 
| 135 164 | 
             
                  #
         | 
| 136 165 | 
             
                  # Instance variables declared in `before(:each)` or `before(:all)` are
         | 
| 137 166 | 
             
                  # accessible within each example.
         | 
| @@ -232,7 +261,7 @@ module RSpec | |
| 232 261 | 
             
                  # rspec-rails, but it will not be wrapped in a transaction for you, so
         | 
| 233 262 | 
             
                  # you are on your own to clean up in an `after(:all)` block.
         | 
| 234 263 | 
             
                  #
         | 
| 235 | 
            -
                  # @example before(:each) declared in an  | 
| 264 | 
            +
                  # @example before(:each) declared in an {ExampleGroup}
         | 
| 236 265 | 
             
                  #
         | 
| 237 266 | 
             
                  #     describe Thing do
         | 
| 238 267 | 
             
                  #       before(:each) do
         | 
| @@ -244,7 +273,7 @@ module RSpec | |
| 244 273 | 
             
                  #       end
         | 
| 245 274 | 
             
                  #     end
         | 
| 246 275 | 
             
                  #
         | 
| 247 | 
            -
                  # @example before(:all) declared in an  | 
| 276 | 
            +
                  # @example before(:all) declared in an {ExampleGroup}
         | 
| 248 277 | 
             
                  #
         | 
| 249 278 | 
             
                  #     describe Parser do
         | 
| 250 279 | 
             
                  #       before(:all) do
         | 
| @@ -264,8 +293,7 @@ module RSpec | |
| 264 293 | 
             
                  #       end
         | 
| 265 294 | 
             
                  #     end
         | 
| 266 295 | 
             
                  def before(*args, &block)
         | 
| 267 | 
            -
                     | 
| 268 | 
            -
                    hooks[:before][scope] << block.extend(BeforeHookExtension).with(options)
         | 
| 296 | 
            +
                    register_hook :append, :before, *args, &block
         | 
| 269 297 | 
             
                  end
         | 
| 270 298 |  | 
| 271 299 | 
             
                  alias_method :append_before, :before
         | 
| @@ -275,8 +303,7 @@ module RSpec | |
| 275 303 | 
             
                  #
         | 
| 276 304 | 
             
                  # See #before for scoping semantics.
         | 
| 277 305 | 
             
                  def prepend_before(*args, &block)
         | 
| 278 | 
            -
                     | 
| 279 | 
            -
                    hooks[:before][scope].unshift block.extend(BeforeHookExtension).with(options)
         | 
| 306 | 
            +
                    register_hook :prepend, :before, *args, &block
         | 
| 280 307 | 
             
                  end
         | 
| 281 308 |  | 
| 282 309 | 
             
                  # @api public
         | 
| @@ -328,8 +355,7 @@ module RSpec | |
| 328 355 | 
             
                  # Similarly, if more than one `after` is declared within any one scope,
         | 
| 329 356 | 
             
                  # they are run in reverse order of that in which they are declared.
         | 
| 330 357 | 
             
                  def after(*args, &block)
         | 
| 331 | 
            -
                     | 
| 332 | 
            -
                    hooks[:after][scope].unshift block.extend(AfterHookExtension).with(options)
         | 
| 358 | 
            +
                    register_hook :prepend, :after, *args, &block
         | 
| 333 359 | 
             
                  end
         | 
| 334 360 |  | 
| 335 361 | 
             
                  alias_method :prepend_after, :after
         | 
| @@ -339,8 +365,7 @@ module RSpec | |
| 339 365 | 
             
                  #
         | 
| 340 366 | 
             
                  # See #after for scoping semantics.
         | 
| 341 367 | 
             
                  def append_after(*args, &block)
         | 
| 342 | 
            -
                     | 
| 343 | 
            -
                    hooks[:after][scope] << block.extend(AfterHookExtension).with(options)
         | 
| 368 | 
            +
                    register_hook :append, :after, *args, &block
         | 
| 344 369 | 
             
                  end
         | 
| 345 370 |  | 
| 346 371 | 
             
                  # @api public
         | 
| @@ -388,8 +413,7 @@ module RSpec | |
| 388 413 | 
             
                  #     around(:each) {|ex| FakeFS(&ex)}
         | 
| 389 414 | 
             
                  #
         | 
| 390 415 | 
             
                  def around(*args, &block)
         | 
| 391 | 
            -
                     | 
| 392 | 
            -
                    hooks[:around][scope].unshift block.extend(AroundHookExtension).with(options)
         | 
| 416 | 
            +
                    register_hook :prepend, :around, *args, &block
         | 
| 393 417 | 
             
                  end
         | 
| 394 418 |  | 
| 395 419 | 
             
                  # @private
         | 
| @@ -407,6 +431,14 @@ module RSpec | |
| 407 431 |  | 
| 408 432 | 
             
                private
         | 
| 409 433 |  | 
| 434 | 
            +
                  SCOPES = [:each, :all, :suite]
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                  EXTENSIONS = {
         | 
| 437 | 
            +
                    :before => BeforeHookExtension,
         | 
| 438 | 
            +
                    :after  => AfterHookExtension,
         | 
| 439 | 
            +
                    :around => AroundHookExtension
         | 
| 440 | 
            +
                  }
         | 
| 441 | 
            +
             | 
| 410 442 | 
             
                  def before_all_hooks_for(group)
         | 
| 411 443 | 
             
                    GroupHookCollection.new(hooks[:before][:all]).for(group)
         | 
| 412 444 | 
             
                  end
         | 
| @@ -423,6 +455,11 @@ module RSpec | |
| 423 455 | 
             
                    HookCollection.new(ancestors.map {|a| a.hooks[:after][:each]}.flatten).for(example)
         | 
| 424 456 | 
             
                  end
         | 
| 425 457 |  | 
| 458 | 
            +
                  def register_hook prepend_or_append, hook, *args, &block
         | 
| 459 | 
            +
                    scope, options = scope_and_options_from(*args)
         | 
| 460 | 
            +
                    hooks[hook][scope].send(prepend_or_append, block.extend(EXTENSIONS[hook]).with(options))
         | 
| 461 | 
            +
                  end
         | 
| 462 | 
            +
             | 
| 426 463 | 
             
                  def find_hook(hook, scope, example_or_group, initial_procsy)
         | 
| 427 464 | 
             
                    case [hook, scope]
         | 
| 428 465 | 
             
                    when [:before, :all]
         | 
| @@ -440,8 +477,6 @@ module RSpec | |
| 440 477 | 
             
                    end
         | 
| 441 478 | 
             
                  end
         | 
| 442 479 |  | 
| 443 | 
            -
                  SCOPES = [:each, :all, :suite]
         | 
| 444 | 
            -
             | 
| 445 480 | 
             
                  def scope_and_options_from(*args)
         | 
| 446 481 | 
             
                    return extract_scope_from(args), build_metadata_hash_from(args)
         | 
| 447 482 | 
             
                  end
         |