/vendor/bundler/ruby/1.9.1/gems/rspec-core-2.13.1/lib/rspec/core/filter_manager.rb
https://bitbucket.org/toihrk/fusuma · Ruby · 203 lines · 103 code · 28 blank · 72 comment · 9 complexity · 131f3524e9648c830f5fe7c8301c0304 MD5 · raw file
- module RSpec
- module Core
- # Manages the filtering of examples and groups by matching tags declared on
- # the command line or options files, or filters declared via
- # `RSpec.configure`, with hash key/values submitted within example group
- # and/or example declarations. For example, given this declaration:
- #
- # describe Thing, :awesome => true do
- # it "does something" do
- # # ...
- # end
- # end
- #
- # That group (or any other with `:awesome => true`) would be filtered in
- # with any of the following commands:
- #
- # rspec --tag awesome:true
- # rspec --tag awesome
- # rspec -t awesome:true
- # rspec -t awesome
- #
- # Prefixing the tag names with `~` negates the tags, thus excluding this group with
- # any of:
- #
- # rspec --tag ~awesome:true
- # rspec --tag ~awesome
- # rspec -t ~awesome:true
- # rspec -t ~awesome
- #
- # ## Options files and command line overrides
- #
- # Tag declarations can be stored in `.rspec`, `~/.rspec`, or a custom
- # options file. This is useful for storing defaults. For example, let's
- # say you've got some slow specs that you want to suppress most of the
- # time. You can tag them like this:
- #
- # describe Something, :slow => true do
- #
- # And then store this in `.rspec`:
- #
- # --tag ~slow:true
- #
- # Now when you run `rspec`, that group will be excluded.
- #
- # ## Overriding
- #
- # Of course, you probably want to run them sometimes, so you can override
- # this tag on the command line like this:
- #
- # rspec --tag slow:true
- #
- # ## RSpec.configure
- #
- # You can also store default tags with `RSpec.configure`. We use `tag` on
- # the command line (and in options files like `.rspec`), but for historical
- # reasons we use the term `filter` in `RSpec.configure:
- #
- # RSpec.configure do |c|
- # c.filter_run_including :foo => :bar
- # c.filter_run_excluding :foo => :bar
- # end
- #
- # These declarations can also be overridden from the command line.
- #
- # @see RSpec.configure
- # @see Configuration#filter_run_including
- # @see Configuration#filter_run_excluding
- class FilterManager
- DEFAULT_EXCLUSIONS = {
- :if => lambda { |value| !value },
- :unless => lambda { |value| value }
- }
- STANDALONE_FILTERS = [:locations, :line_numbers, :full_description]
- module Describable
- PROC_HEX_NUMBER = /0x[0-9a-f]+@/
- PROJECT_DIR = File.expand_path('.')
- def description
- reject { |k, v| RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS[k] == v }.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
- end
- def empty_without_conditional_filters?
- reject { |k, v| RSpec::Core::FilterManager::DEFAULT_EXCLUSIONS[k] == v }.empty?
- end
- end
- module BackwardCompatibility
- def merge(orig, opposite, *updates)
- _warn_deprecated_keys(updates.last)
- super
- end
- def reverse_merge(orig, opposite, *updates)
- _warn_deprecated_keys(updates.last)
- super
- end
- # Supports a use case that probably doesn't exist: overriding the
- # if/unless procs.
- def _warn_deprecated_keys(updates)
- _warn_deprecated_key(:unless, updates) if updates.has_key?(:unless)
- _warn_deprecated_key(:if, updates) if updates.has_key?(:if)
- end
- # Emits a deprecation warning for keys that will not be supported in
- # the future.
- def _warn_deprecated_key(key, updates)
- RSpec.warn_deprecation("\nDEPRECATION NOTICE: FilterManager#exclude(#{key.inspect} => #{updates[key].inspect}) is deprecated with no replacement, and will be removed from rspec-3.0.")
- @exclusions[key] = updates.delete(key)
- end
- end
- attr_reader :exclusions, :inclusions
- def initialize
- @exclusions = DEFAULT_EXCLUSIONS.dup.extend(Describable)
- @inclusions = {}.extend(Describable)
- extend(BackwardCompatibility)
- end
- def add_location(file_path, line_numbers)
- # locations is a hash of expanded paths to arrays of line
- # numbers to match against. e.g.
- # { "path/to/file.rb" => [37, 42] }
- locations = @inclusions.delete(:locations) || Hash.new {|h,k| h[k] = []}
- locations[File.expand_path(file_path)].push(*line_numbers)
- @inclusions.replace(:locations => locations)
- @exclusions.clear
- end
- def empty?
- inclusions.empty? && exclusions.empty_without_conditional_filters?
- end
- def prune(examples)
- examples.select {|e| !exclude?(e) && include?(e)}
- end
- def exclude(*args)
- merge(@exclusions, @inclusions, *args)
- end
- def exclude!(*args)
- replace(@exclusions, @inclusions, *args)
- end
- def exclude_with_low_priority(*args)
- reverse_merge(@exclusions, @inclusions, *args)
- end
- def exclude?(example)
- @exclusions.empty? ? false : example.any_apply?(@exclusions)
- end
- def include(*args)
- unless_standalone(*args) { merge(@inclusions, @exclusions, *args) }
- end
- def include!(*args)
- unless_standalone(*args) { replace(@inclusions, @exclusions, *args) }
- end
- def include_with_low_priority(*args)
- unless_standalone(*args) { reverse_merge(@inclusions, @exclusions, *args) }
- end
- def include?(example)
- @inclusions.empty? ? true : example.any_apply?(@inclusions)
- end
- private
- def unless_standalone(*args)
- is_standalone_filter?(args.last) ? @inclusions.replace(args.last) : yield unless already_set_standalone_filter?
- end
- def merge(orig, opposite, *updates)
- orig.merge!(updates.last).each_key {|k| opposite.delete(k)}
- end
- def replace(orig, opposite, *updates)
- updates.last.each_key {|k| opposite.delete(k)}
- orig.replace(updates.last)
- end
- def reverse_merge(orig, opposite, *updates)
- updated = updates.last.merge(orig)
- opposite.each_pair {|k,v| updated.delete(k) if updated[k] == v}
- orig.replace(updated)
- end
- def already_set_standalone_filter?
- is_standalone_filter?(inclusions)
- end
- def is_standalone_filter?(filter)
- STANDALONE_FILTERS.any? {|key| filter.has_key?(key)}
- end
- end
- end
- end