Each ExampleGroup class and Example instance owns an instance of Metadata, which is Hash extended to support lazy evaluation of values associated with keys that may or may not be used by any example or group.
In addition to metadata that is used internally, this also stores user-supplied metadata, e.g.
describe Something, :type => :ui do it "does something", :slow => true do # ... end end
`:type => :ui` is stored in the Metadata owned by the example group, and `:slow => true` is stored in the Metadata owned by the example. These can then be used to select which examples are run using the `--tag` option on the command line, or several methods on `Configuration` used to filter a run (e.g. `filter_run_including`, `filter_run_excluding`, etc).
@see RSpec::Core::Example#metadata @see RSpec::Core::ExampleGroup.metadata @see FilterManager @see RSpec::Core::Configuration#filter_run_including @see RSpec::Core::Configuration#filter_run_excluding
# File lib/rspec/core/metadata.rb, line 133 def initialize(parent_group_metadata=nil) if parent_group_metadata update(parent_group_metadata) store(:example_group, {:example_group => parent_group_metadata[:example_group].extend(GroupMetadataHash)}.extend(GroupMetadataHash)) else store(:example_group, {}.extend(GroupMetadataHash)) end yield self if block_given? end
@private
# File lib/rspec/core/metadata.rb, line 166 def all_apply?(filters) filters.all? {|k,v| filter_applies?(k,v)} end
@private
# File lib/rspec/core/metadata.rb, line 161 def any_apply?(filters) filters.any? {|k,v| filter_applies?(k,v)} end
@private
# File lib/rspec/core/metadata.rb, line 171 def filter_applies?(key, value, metadata=self) return metadata.filter_applies_to_any_value?(key, value) if Array === metadata[key] && !(Proc === value) return metadata.line_number_filter_applies?(value) if key == :line_numbers return metadata.location_filter_applies?(value) if key == :locations return metadata.filters_apply?(key, value) if Hash === value case value when Regexp metadata[key] =~ value when Proc if value.arity == 2 # Pass the metadata hash to allow the proc to check if it even has the key. # This is necessary for the implicit :if exclusion filter: # { } # => run the example # { :if => nil } # => exclude the example # The value of metadata[:if] is the same in these two cases but # they need to be treated differently. value.call(metadata[key], metadata) rescue false else value.call(metadata[key]) rescue false end else metadata[key].to_s == value.to_s end end
@private
# File lib/rspec/core/metadata.rb, line 203 def filter_applies_to_any_value?(key, value) self[key].any? {|v| filter_applies?(key, v, {key => value})} end
@private
# File lib/rspec/core/metadata.rb, line 198 def filters_apply?(key, value) value.all? {|k, v| filter_applies?(k, v, self[key])} end
@private
# File lib/rspec/core/metadata.rb, line 156 def for_example(description, user_metadata) dup.extend(ExampleMetadataHash).configure_for_example(description, user_metadata) end
@private
# File lib/rspec/core/metadata.rb, line 215 def line_number_filter_applies?(line_numbers) preceding_declaration_lines = line_numbers.map {|n| RSpec.world.preceding_declaration_line(n)} !(relevant_line_numbers & preceding_declaration_lines).empty? end
@private
# File lib/rspec/core/metadata.rb, line 208 def location_filter_applies?(locations) # it ignores location filters for other files line_number = example_group_declaration_line(locations) line_number ? line_number_filter_applies?(line_number) : true end
@private
# File lib/rspec/core/metadata.rb, line 145 def process(*args) user_metadata = args.last.is_a?(Hash) ? args.pop : {} ensure_valid_keys(user_metadata) self[:example_group].store(:description_args, args) self[:example_group].store(:caller, user_metadata.delete(:caller) || caller) update(user_metadata) end
# File lib/rspec/core/metadata.rb, line 222 def configure_for_example(description, user_metadata) store(:description_args, [description]) store(:caller, user_metadata.delete(:caller) || caller) update(user_metadata) end