class RSpec::Core::ExampleGroup

{MemoizedHelpers} and {Pending}.
There are additional instance methods available to your examples defined in
defined in {Hooks}, {MemoizedHelpers::ClassMethods} and {SharedExampleGroup}.
Besides the class methods defined here, there are other interesting macros
to which they belong.
evalutaed in the context of an instance of the specific ExampleGroup subclass
in the context of a new subclass of ExampleGroup. Individual examples are
Example group bodies (e.g. ‘describe` or `context` blocks) are evaluated
is declared.
which serves as a wrapper for an instance of the ExampleGroup in which it
The object returned by `it “does something”` is an instance of Example,
The object returned by `describe Thing` is a subclass of ExampleGroup.
end
end
it “does something” do
describe Thing do
rspec-core. Consider this example:
ExampleGroup and {Example} are the main structural elements of

def self.all_apply?(filters)

Other tags:
    Private: -
def self.all_apply?(filters)
  MetadataFilter.all_apply?(filters, metadata)
end

def self.any_apply?(filters)

Other tags:
    Private: -
def self.any_apply?(filters)
  MetadataFilter.any_apply?(filters, metadata)
end

def self.before_context_ivars

Other tags:
    Private: -
def self.before_context_ivars
  @before_context_ivars ||= {}
end

def self.children

Other tags:
    Private: -
def self.children
  @children ||= []
end

def self.declaration_line_numbers

Other tags:
    Private: -
def self.declaration_line_numbers
  @declaration_line_numbers ||= [metadata[:line_number]] +
    examples.collect {|e| e.metadata[:line_number]} +
    children.inject([]) {|l,c| l + c.declaration_line_numbers}
end

def self.define_example_group_method(name, metadata={})

Other tags:
    See: DSL#describe -

Other tags:
    Yield: - The example group definition

Parameters:
  • metadata (Hash) -- Additional metadata to attach to the example group
  • name (String) -- The example group doc string

Other tags:
    Private: -
def self.define_example_group_method(name, metadata={})
  define_singleton_method(name) do |*args, &example_group_block|
    thread_data = RSpec.thread_local_metadata
    top_level   = self == ExampleGroup
    if top_level
      if thread_data[:in_example_group]
        raise "Creating an isolated context from within a context is " +
              "not allowed. Change `RSpec.#{name}` to `#{name}` or " +
              "move this to a top-level scope."
      end
      thread_data[:in_example_group] = true
    end
    begin
      description = args.shift
      combined_metadata = metadata.dup
      combined_metadata.merge!(args.pop) if args.last.is_a? Hash
      args << combined_metadata
      subclass(self, description, args, &example_group_block).tap do |child|
        children << child
      end
    ensure
      thread_data.delete(:in_example_group) if top_level
    end
  end
  RSpec::Core::DSL.expose_example_group_alias(name)
end

def self.define_example_method(name, extra_options={})

Other tags:
    Yield: - the example object

Parameters:
  • implementation (Block) --
  • extra_options (Hash) --
  • name (String) --

Other tags:
    Private: -
def self.define_example_method(name, extra_options={})
  define_singleton_method(name) do |*all_args, &block|
    desc, *args = *all_args
    options = Metadata.build_hash_from(args)
    options.update(:skip => RSpec::Core::Pending::NOT_YET_IMPLEMENTED) unless block
    options.update(extra_options)
    # Metadata inheritance normally happens in `Example#initialize`,
    # but for `:pending` specifically we need it earlier.
    pending_metadata = options[:pending] || metadata[:pending]
    if pending_metadata
      options, block = ExampleGroup.pending_metadata_and_block_for(
        options.merge(:pending => pending_metadata),
        block
      )
    end
    examples << RSpec::Core::Example.new(self, desc, options, block)
    examples.last
  end
end

def self.define_nested_shared_group_method(new_name, report_label="it should behave like")

Other tags:
    See: SharedExampleGroup -

Other tags:
    Private: -
def self.define_nested_shared_group_method(new_name, report_label="it should behave like")
  define_singleton_method(new_name) do |name, *args, &customization_block|
    # Pass :caller so the :location metadata is set properly...
    # otherwise, it'll be set to the next line because that's
    # the block's source_location.
    group = example_group("#{report_label} #{name}", :caller => caller) do
      find_and_eval_shared("examples", name, *args, &customization_block)
    end
    group.metadata[:shared_group_name] = name
    group
  end
end

def self.define_singleton_method(*a, &b)

Other tags:
    Private: -
def self.define_singleton_method(*a, &b)
  (class << self; self; end).__send__(:define_method, *a, &b)
end

def self.delegate_to_metadata(*names)

Other tags:
    Private: -
def self.delegate_to_metadata(*names)
  names.each do |name|
    define_singleton_method(name) { metadata.fetch(name) }
  end
end

def self.descendant_filtered_examples

Other tags:
    Private: -
def self.descendant_filtered_examples
  @descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
end

def self.descendants

Other tags:
    Private: -
def self.descendants
  @_descendants ||= [self] + children.inject([]) {|list, c| list + c.descendants}
end

def self.description

Returns:
  • (String) - the current example group description
def self.description
  description = metadata[:description]
  RSpec.configuration.format_docstrings_block.call(description)
end

def self.ensure_example_groups_are_configured

Other tags:
    Private: -
def self.ensure_example_groups_are_configured
  unless defined?(@@example_groups_configured)
    RSpec.configuration.configure_mock_framework
    RSpec.configuration.configure_expectation_framework
    @@example_groups_configured = true
  end
end

def self.examples

Other tags:
    Private: -
def self.examples
  @examples ||= []
end

def self.fail_fast?

Other tags:
    Private: -
def self.fail_fast?
  RSpec.configuration.fail_fast?
end

def self.filtered_examples

Other tags:
    Private: -
def self.filtered_examples
  RSpec.world.filtered_examples[self]
end

def self.find_and_eval_shared(label, name, *args, &customization_block)

Other tags:
    Private: -
def self.find_and_eval_shared(label, name, *args, &customization_block)
  unless shared_block = RSpec.world.shared_example_group_registry.find(parent_groups, name)
    raise ArgumentError, "Could not find shared #{label} #{name.inspect}"
  end
  module_exec(*args, &shared_block)
  module_exec(&customization_block) if customization_block
end

def self.for_filtered_examples(reporter, &block)

Other tags:
    Private: -
def self.for_filtered_examples(reporter, &block)
  filtered_examples.each(&block)
  children.each do |child|
    reporter.example_group_started(child)
    child.for_filtered_examples(reporter, &block)
    reporter.example_group_finished(child)
  end
  false
end

def self.include_context(name, *args, &block)

Other tags:
    See: SharedExampleGroup -
def self.include_context(name, *args, &block)
  find_and_eval_shared("context", name, *args, &block)
end

def self.include_examples(name, *args, &block)

Other tags:
    See: SharedExampleGroup -
def self.include_examples(name, *args, &block)
  find_and_eval_shared("examples", name, *args, &block)
end

def self.metadata

Other tags:
    See: Metadata -
def self.metadata
  @metadata if defined?(@metadata)
end

def self.ordering_strategy

Other tags:
    Private: -
def self.ordering_strategy
  order = metadata.fetch(:order, :global)
  registry = RSpec.configuration.ordering_registry
  registry.fetch(order) do
    warn <<-WARNING.gsub(/^ +\|/, '')
      |WARNING: Ignoring unknown ordering specified using `:order => #{order.inspect}` metadata.
      |         Falling back to configured global ordering.
      |         Unrecognized ordering specified at: #{location}
    WARNING
    registry.fetch(:global)
  end
end

def self.parent_groups

# @private
def self.parent_groups
  @parent_groups ||= ancestors.select {|a| a < RSpec::Core::ExampleGroup}
end

def self.pending_metadata_and_block_for(options, block)

Other tags:
    Private: -
def self.pending_metadata_and_block_for(options, block)
  if String === options[:pending]
    reason = options[:pending]
  else
    options[:pending] = true
    reason = RSpec::Core::Pending::NO_REASON_GIVEN
  end
  # Assign :caller so that the callback's source_location isn't used
  # as the example location.
  options[:caller] ||= Metadata.backtrace_from(block)
  # This will fail if no block is provided, which is effectively the
  # same as failing the example so it will be marked correctly as
  # pending.
  callback = Proc.new { pending(reason); instance_exec(&block) }
  return options, callback
end

def self.run(reporter)

Runs all the examples in this group
def self.run(reporter)
  if RSpec.world.wants_to_quit
    RSpec.world.clear_remaining_example_groups if top_level?
    return
  end
  reporter.example_group_started(self)
  begin
    run_before_context_hooks(new)
    result_for_this_group = run_examples(reporter)
    results_for_descendants = ordering_strategy.order(children).map { |child| child.run(reporter) }.all?
    result_for_this_group && results_for_descendants
  rescue Pending::SkipDeclaredInExample => ex
    for_filtered_examples(reporter) {|example| example.skip_with_exception(reporter, ex) }
  rescue Exception => ex
    RSpec.world.wants_to_quit = true if fail_fast?
    for_filtered_examples(reporter) {|example| example.fail_with_exception(reporter, ex) }
  ensure
    run_after_context_hooks(new)
    before_context_ivars.clear
    reporter.example_group_finished(self)
  end
end

def self.run_after_context_hooks(example_group_instance)

Other tags:
    Private: -
def self.run_after_context_hooks(example_group_instance)
  return if descendant_filtered_examples.empty?
  set_ivars(example_group_instance, before_context_ivars)
  ContextHookMemoizedHash::After.isolate_for_context_hook(example_group_instance) do
    hooks.run(:after, :context, example_group_instance)
  end
end

def self.run_before_context_hooks(example_group_instance)

Other tags:
    Private: -
def self.run_before_context_hooks(example_group_instance)
  return if descendant_filtered_examples.empty?
  begin
    set_ivars(example_group_instance, superclass.before_context_ivars)
    ContextHookMemoizedHash::Before.isolate_for_context_hook(example_group_instance) do
      hooks.run(:before, :context, example_group_instance)
    end
  ensure
    store_before_context_ivars(example_group_instance)
  end
end

def self.run_examples(reporter)

Other tags:
    Private: -
def self.run_examples(reporter)
  ordering_strategy.order(filtered_examples).map do |example|
    next if RSpec.world.wants_to_quit
    instance = new
    set_ivars(instance, before_context_ivars)
    succeeded = example.run(instance, reporter)
    RSpec.world.wants_to_quit = true if fail_fast? && !succeeded
    succeeded
  end.all?
end

def self.set_it_up(*args, &example_group_block)

Other tags:
    Private: -
def self.set_it_up(*args, &example_group_block)
  # Ruby 1.9 has a bug that can lead to infinite recursion and a
  # SystemStackError if you include a module in a superclass after
  # including it in a subclass: https://gist.github.com/845896
  # To prevent this, we must include any modules in RSpec::Core::ExampleGroup
  # before users create example groups and have a chance to include
  # the same module in a subclass of RSpec::Core::ExampleGroup.
  # So we need to configure example groups here.
  ensure_example_groups_are_configured
  description = args.shift
  user_metadata = Metadata.build_hash_from(args)
  args.unshift(description)
  @metadata = Metadata::ExampleGroupHash.create(
    superclass_metadata, user_metadata, *args, &example_group_block
  )
  hooks.register_globals(self, RSpec.configuration.hooks)
  RSpec.world.configure_group(self)
end

def self.set_ivars(instance, ivars)

Other tags:
    Private: -
def self.set_ivars(instance, ivars)
  ivars.each {|name, value| instance.instance_variable_set(name, value)}
end

def self.store_before_context_ivars(example_group_instance)

Other tags:
    Private: -
def self.store_before_context_ivars(example_group_instance)
  return if example_group_instance.instance_variables.empty?
  example_group_instance.instance_variables.each { |ivar|
    before_context_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
  }
end

def self.subclass(parent, description, args, &example_group_block)

Other tags:
    Private: -
def self.subclass(parent, description, args, &example_group_block)
  subclass = Class.new(parent)
  subclass.set_it_up(description, *args, &example_group_block)
  ExampleGroups.assign_const(subclass)
  subclass.module_exec(&example_group_block) if example_group_block
  # The LetDefinitions module must be included _after_ other modules
  # to ensure that it takes precedence when there are name collisions.
  # Thus, we delay including it until after the example group block
  # has been eval'd.
  MemoizedHelpers.define_helpers_on(subclass)
  subclass
end

def self.superclass_metadata

Returns:
  • (Metadata) - belonging to the parent of a nested {ExampleGroup}

Other tags:
    Private: -
def self.superclass_metadata
  @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
end

def self.top_level?

Other tags:
    Private: -
def self.top_level?
  @top_level ||= superclass == ExampleGroup
end

def self.top_level_description

Other tags:
    Private: -
def self.top_level_description
  parent_groups.last.description
end

def described_class



end
end
described_class == Thing
it "does something" do
describe Thing do
@example
Returns nil if the subject is not a class or module.
Returns the class or module passed to the `describe` method (or alias).
def described_class
  self.class.described_class
end