class RSpec::Core::Example

Wrapper for an instance of a subclass of {ExampleGroup}. An instance of `RSpec::Core::Example` is returned by example definition methods such as {ExampleGroup.it it} and is yielded to the {ExampleGroup.it it}, {Hooks#before before}, {Hooks#after after}, {Hooks#around around}, {MemoizedHelpers::ClassMethods#let let} and {MemoizedHelpers::ClassMethods#subject subject} blocks.

This allows us to provide rich metadata about each individual example without adding tons of methods directly to the ExampleGroup that users may inadvertantly redefine.

Useful for configuring logging and/or taking some action based on the state of an example's metadata.

@example

RSpec.configure do |config|
  config.before do |example|
    log example.description
  end

  config.after do |example|
    log example.description
  end

  config.around do |example|
    log example.description
    example.run
  end
end

shared_examples "auditable" do
  it "does something" do
    log "#{example.full_description}: #{auditable.inspect}"
    auditable.should do_something
  end
end

@see ExampleGroup @note Example blocks are evaluated in the context of an instance

of an `ExampleGroup`, not in the context of an instance of `Example`.

Attributes

clock[RW]

@attr @private

example_group_instance[R]

@attr_reader @private

Returns the #example_group_instance that provides the context for running this example.

exception[R]

@attr_reader

Returns the first exception raised in the context of running this example (nil if no exception is raised)

metadata[R]

@attr_reader

Returns the metadata object associated with this example.

Public Class Methods

delegate_to_metadata(key) click to toggle source

@private

Used to define methods that delegate to this example's metadata

# File lib/rspec/core/example.rb, line 48
def self.delegate_to_metadata(key)
  define_method(key) { @metadata[key] }
end
new(example_group_class, description, user_metadata, example_block=nil) click to toggle source

Creates a new instance of Example. @param example_group_class [Class] the subclass of ExampleGroup in which this Example is declared @param description [String] the String passed to the `it` method (or alias) @param user_metadata [Hash] additional args passed to `it` to be used as metadata @param example_block [Proc] the block of code that represents the example @api private

# File lib/rspec/core/example.rb, line 110
def initialize(example_group_class, description, user_metadata, example_block=nil)
  @example_group_class = example_group_class
  @example_block       = example_block

  @metadata = Metadata::ExampleHash.create(
    @example_group_class.metadata, user_metadata, description, example_block
  )

  @example_group_instance = @exception = nil
  @clock = RSpec::Core::Time
end

Public Instance Methods

all_apply?(filters) click to toggle source

@private

# File lib/rspec/core/example.rb, line 229
def all_apply?(filters)
  MetadataFilter.all_apply?(filters, metadata) || @example_group_class.all_apply?(filters)
end
any_apply?(filters) click to toggle source

@private

# File lib/rspec/core/example.rb, line 224
def any_apply?(filters)
  MetadataFilter.any_apply?(filters, metadata)
end
around_example_hooks() click to toggle source

@private

# File lib/rspec/core/example.rb, line 234
def around_example_hooks
  @around_example_hooks ||= example_group.hooks.around_example_hooks_for(self)
end
description() click to toggle source

Returns the string submitted to `example` or its aliases (e.g. `specify`, `it`, etc). If no string is submitted (e.g. `it { is_expected.to do_something }`) it returns the message generated by the matcher if there is one, otherwise returns a message including the location of the example.

# File lib/rspec/core/example.rb, line 75
def description
  description = metadata[:description].to_s.empty? ?
    "example at #{location}" :
    metadata[:description]
  RSpec.configuration.format_docstrings_block.call(description)
end
example_group() click to toggle source

Returns the example group class that provides the context for running this example.

# File lib/rspec/core/example.rb, line 124
def example_group
  @example_group_class
end
fail_with_exception(reporter, exception) click to toggle source

@private

Used internally to set an exception and fail without actually executing the example when an exception is raised in before(:context).

# File lib/rspec/core/example.rb, line 267
def fail_with_exception(reporter, exception)
  start(reporter)
  set_exception(exception)
  finish(reporter)
end
instance_exec(*args, &block) click to toggle source

@private

# File lib/rspec/core/example.rb, line 291
def instance_exec(*args, &block)
  @example_group_instance.instance_exec(*args, &block)
end
instance_exec_with_rescue(context, &block) click to toggle source

@private

# File lib/rspec/core/example.rb, line 284
def instance_exec_with_rescue(context, &block)
  @example_group_instance.instance_exec(self, &block)
rescue Exception => e
  set_exception(e, context)
end
run(example_group_instance, reporter) click to toggle source

@api private instance_execs the block passed to the constructor in the context of the instance of {ExampleGroup}. @param #example_group_instance the instance of an ExampleGroup subclass

# File lib/rspec/core/example.rb, line 135
def run(example_group_instance, reporter)
  @example_group_instance = example_group_instance
  RSpec.current_example = self

  start(reporter)

  begin
    if skipped?
      Pending.mark_pending! self, skip
    elsif !RSpec.configuration.dry_run?
      with_around_example_hooks do
        begin
          run_before_example
          @example_group_instance.instance_exec(self, &@example_block)

          if pending?
            Pending.mark_fixed! self

            raise Pending::PendingExampleFixedError,
              'Expected example to fail since it is pending, but it passed.',
              [location]
          end
        rescue Pending::SkipDeclaredInExample
          # no-op, required metadata has already been set by the `skip`
          # method.
        rescue Exception => e
          set_exception(e)
        ensure
          run_after_example
        end
      end
    end
  rescue Exception => e
    set_exception(e)
  ensure
    @example_group_instance.instance_variables.each do |ivar|
      @example_group_instance.instance_variable_set(ivar, nil)
    end
    @example_group_instance = nil
  end

  finish(reporter)
ensure
  RSpec.current_example = nil
end
set_exception(exception, context=nil) click to toggle source

@private

Used internally to set an exception in an after hook, which captures the exception but doesn't raise it.

# File lib/rspec/core/example.rb, line 242
    def set_exception(exception, context=nil)
      if pending? && !(Pending::PendingExampleFixedError === exception)
        execution_result.pending_exception = exception
      else
        if @exception
          # An error has already been set; we don't want to override it,
          # but we also don't want silence the error, so let's print it.
          msg = <<-EOS

An error occurred #{context}
  #{exception.class}: #{exception.message}
  occurred at #{exception.backtrace.first}

          EOS
          RSpec.configuration.reporter.message(msg)
        end

        @exception ||= exception
      end
    end
skip_with_exception(reporter, exception) click to toggle source

@private

Used internally to skip without actually executing the example when skip is used in before(:context)

# File lib/rspec/core/example.rb, line 277
def skip_with_exception(reporter, exception)
  start(reporter)
  Pending.mark_skipped! self, exception.argument
  finish(reporter)
end

Private Instance Methods

assign_generated_description() click to toggle source
# File lib/rspec/core/example.rb, line 366
def assign_generated_description
  if metadata[:description].empty? && (description = RSpec::Matchers.generated_description)
    metadata[:description] = description
    metadata[:full_description] << description
  end
rescue Exception => e
  set_exception(e, "while assigning the example description")
ensure
  RSpec::Matchers.clear_generated_description
end
finish(reporter) click to toggle source
# File lib/rspec/core/example.rb, line 312
def finish(reporter)
  pending_message = execution_result.pending_message

  if @exception
    record_finished :failed
    execution_result.exception = @exception
    reporter.example_failed self
    false
  elsif pending_message
    record_finished :pending
    execution_result.pending_message = pending_message
    reporter.example_pending self
    true
  else
    record_finished :passed
    reporter.example_passed self
    true
  end
end
mocks_need_verification?() click to toggle source
# File lib/rspec/core/example.rb, line 362
def mocks_need_verification?
  exception.nil? || execution_result.pending_fixed?
end
record_finished(status) click to toggle source
# File lib/rspec/core/example.rb, line 332
def record_finished(status)
  execution_result.record_finished(status, clock.now)
end
run_after_example() click to toggle source
# File lib/rspec/core/example.rb, line 341
def run_after_example
  @example_group_class.hooks.run(:after, :example, self)
  verify_mocks
  assign_generated_description if RSpec.configuration.expecting_with_rspec?
rescue Exception => e
  set_exception(e, "in an `after(:example)` hook")
ensure
  @example_group_instance.teardown_mocks_for_rspec
end
run_before_example() click to toggle source
# File lib/rspec/core/example.rb, line 336
def run_before_example
  @example_group_instance.setup_mocks_for_rspec
  @example_group_class.hooks.run(:before, :example, self)
end
skip_message() click to toggle source
# File lib/rspec/core/example.rb, line 377
def skip_message
  if String === skip
    skip
  else
    Pending::NO_REASON_GIVEN
  end
end
start(reporter) click to toggle source
# File lib/rspec/core/example.rb, line 307
def start(reporter)
  reporter.example_started(self)
  execution_result.started_at = clock.now
end
verify_mocks() click to toggle source
# File lib/rspec/core/example.rb, line 351
def verify_mocks
  @example_group_instance.verify_mocks_for_rspec if mocks_need_verification?
rescue Exception => e
  if pending?
    execution_result.pending_fixed = false
    @exception = nil
  else
    set_exception(e)
  end
end
with_around_example_hooks() { || ... } click to toggle source
# File lib/rspec/core/example.rb, line 297
def with_around_example_hooks(&block)
  if around_example_hooks.empty?
    yield
  else
    @example_group_class.hooks.run(:around, :example, self, Procsy.new(self, &block))
  end
rescue Exception => e
  set_exception(e, "in an `around(:example)` hook")
end