class RSpec::Core::Metadata
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
Constants
- RESERVED_KEYS
Public Class Methods
# File lib/rspec/core/metadata.rb, line 163 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
# File lib/rspec/core/metadata.rb, line 29 def self.relative_path(line) line = line.sub(File.expand_path("."), ".") line = line.sub(/\A([^:]+:\d+)$/, '\1') return nil if line == '-e:1' line rescue SecurityError nil end
Public Instance Methods
@private
# File lib/rspec/core/metadata.rb, line 196 def all_apply?(filters) filters.all? {|k,v| filter_applies?(k,v)} end
@private
# File lib/rspec/core/metadata.rb, line 191 def any_apply?(filters) filters.any? {|k,v| filter_applies?(k,v)} end
@private
# File lib/rspec/core/metadata.rb, line 201 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 return false unless metadata.has_key?(key) case value when Regexp metadata[key] =~ value when Proc case value.arity when 0 then value.call when 2 then value.call(metadata[key], metadata) else value.call(metadata[key]) end else metadata[key].to_s == value.to_s end end
@private
# File lib/rspec/core/metadata.rb, line 229 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 224 def filters_apply?(key, value) value.all? {|k, v| filter_applies?(k, v, self[key])} end
@private
# File lib/rspec/core/metadata.rb, line 186 def for_example(description, user_metadata) dup.extend(ExampleMetadataHash).configure_for_example(description, user_metadata) end
@private
# File lib/rspec/core/metadata.rb, line 241 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 234 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 175 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
Protected Instance Methods
# File lib/rspec/core/metadata.rb, line 248 def configure_for_example(description, user_metadata) store(:description_args, [description]) if description store(:caller, user_metadata.delete(:caller) || caller) update(user_metadata) end
Private Instance Methods
# File lib/rspec/core/metadata.rb, line 266 def ensure_valid_keys(user_metadata) RESERVED_KEYS.each do |key| if user_metadata.has_key?(key) raise <<-EOM #{"*"*50} :#{key} is not allowed RSpec reserves some hash keys for its own internal use, including :#{key}, which is used on: #{caller(0)[4]}. Here are all of RSpec's reserved hash keys: #{RESERVED_KEYS.join("\n ")} #{"*"*50} EOM end end end
# File lib/rspec/core/metadata.rb, line 287 def example_group_declaration_line(locations) locations[File.expand_path(self[:example_group][:file_path])] if self[:example_group] end
TODO - make this a method on metadata - the problem is metadata is not always a kind of GroupMetadataHash.
# File lib/rspec/core/metadata.rb, line 293 def relevant_line_numbers(metadata=self) [metadata[:line_number]] + (metadata[:example_group] ? relevant_line_numbers(metadata[:example_group]) : []) end