Permalink
Browse files

Merge pull request #843 from samphippen/backtrace-cleaner

Backtrace cleaner
  • Loading branch information...
myronmarston committed Mar 26, 2013
2 parents 973a03b + 56d7c0a commit 8ac0f7eb90fe5a22cf79aae590fbfd31534ba3bc
@@ -0,0 +1,42 @@
+module RSpec
+ module Core
+ class BacktraceCleaner
+
+ DEFAULT_EXCLUSION_PATTERNS = [
+ /\/lib\d*\/ruby\//,
+ /org\/jruby\//,
+ /bin\//,
+ %r|/gems/|,
+ /spec\/spec_helper\.rb/,
+ /lib\/rspec\/(core|expectations|matchers|mocks)/
+ ]
+
+ attr_accessor :inclusion_patterns
+ attr_accessor :exclusion_patterns
+
+ def initialize(inclusion_patterns=nil, exclusion_patterns=DEFAULT_EXCLUSION_PATTERNS.dup)
+ @exclusion_patterns = exclusion_patterns
+
+ if inclusion_patterns.nil?
+ @inclusion_patterns = (matches_an_exclusion_pattern? Dir.getwd) ? [Regexp.new(Dir.getwd)] : []
+ else
+ @inclusion_patterns = inclusion_patterns
+ end
+ end
+
+ def exclude?(line)
+ @inclusion_patterns.none? {|p| line =~ p} and matches_an_exclusion_pattern?(line)
+ end
+
+ def full_backtrace=(true_or_false)
+ @exclusion_patterns = true_or_false ? [] : DEFAULT_EXCLUSION_PATTERNS.dup
+ end
+
+ private
+
+ def matches_an_exclusion_pattern?(line)
+ @exclusion_patterns.any? {|p| line =~ p}
+ end
+ end
+ end
+end
@@ -1,4 +1,5 @@
require 'fileutils'
+require 'rspec/core/backtrace_cleaner'
require 'rspec/core/ruby_project'
module RSpec
@@ -81,15 +82,6 @@ def self.add_setting(name, opts={})
# @macro [attach] add_setting
# @attribute $1
- # Patterns to match against lines in backtraces presented in failure
- # messages in order to filter them out (default:
- # DEFAULT_BACKTRACE_PATTERNS). You can either replace this list using
- # the setter or modify it using the getter.
- #
- # To override this behavior and display a full backtrace, use
- # `--backtrace` on the command line, in a `.rspec` file, or in the
- # `rspec_options` attribute of RSpec's rake task.
- add_setting :backtrace_clean_patterns
# Path to use if no path is provided to the `rspec` command (default:
# `"spec"`). Allows you to just type `rspec` instead of `rspec spec` to
@@ -183,14 +175,7 @@ def self.add_setting(name, opts={})
# @private
attr_accessor :filter_manager
- DEFAULT_BACKTRACE_PATTERNS = [
- /\/lib\d*\/ruby\//,
- /org\/jruby\//,
- /bin\//,
- %r|/gems/|,
- /spec\/spec_helper\.rb/,
- /lib\/rspec\/(core|expectations|matchers|mocks)/
- ]
+ attr_reader :backtrace_cleaner
def initialize
@expectation_frameworks = []
@@ -201,7 +186,9 @@ def initialize
@color = false
@pattern = '**/*_spec.rb'
@failure_exit_code = 1
- @backtrace_clean_patterns = DEFAULT_BACKTRACE_PATTERNS.dup
+
+ @backtrace_cleaner = BacktraceCleaner.new
+
@default_path = 'spec'
@filter_manager = FilterManager.new
@preferred_options = {}
@@ -276,15 +263,6 @@ def add_setting(name, opts={})
send("#{name}=", default) if default
end
- # Used by formatters to ask whether a backtrace line should be displayed
- # or not, based on the line matching any `backtrace_clean_patterns`.
- def cleaned_from_backtrace?(line)
- # TODO (David 2011-12-25) why are we asking the configuration to do
- # stuff? Either use the patterns directly or enapsulate the filtering
- # in a BacktraceCleaner object.
- backtrace_clean_patterns.any? { |regex| line =~ regex }
- end
-
# Returns the configured mock framework adapter module
def mock_framework
mock_with :rspec unless @mock_framework
@@ -296,6 +274,62 @@ def mock_framework=(framework)
mock_with framework
end
+ # The patterns to discard from backtraces. Deprecated, use
+ # Configuration#backtrace_exclusion_patterns instead
+ #
+ # Defaults to RSpec::Core::BacktraceCleaner::DEFAULT_EXCLUSION_PATTERNS
+ #
+ # One can replace the list by using the setter or modify it through the
+ # getter
+ #
+ # To override this behaviour and display a full backtrace, use
+ # `--backtrace`on the command line, in a `.rspec` file, or in the
+ # `rspec_options` attribute of RSpec's rake task.
+ def backtrace_clean_patterns
+ RSpec.deprecate("RSpec::Core::Configuration#backtrace_clean_patterns",
+ "RSpec::Core::Configuration#backtrace_exclusion_patterns")
+ @backtrace_cleaner.exclusion_patterns
+ end
+
+ def backtrace_clean_patterns=(patterns)
+ RSpec.deprecate("RSpec::Core::Configuration#backtrace_clean_patterns",
+ "RSpec::Core::Configuration#backtrace_exclusion_patterns")
+ @backtrace_cleaner.exclusion_patterns = patterns
+ end
+
+ # The patterns to always include to backtraces.
+ #
+ # Defaults to [Regexp.new Dir.getwd] if the current working directory
+ # matches any of the exclusion patterns. Otherwise it defaults to empty.
+ #
+ # One can replace the list by using the setter or modify it through the
+ # getter
+ def backtrace_inclusion_patterns
+ @backtrace_cleaner.inclusion_patterns
+ end
+
+ def backtrace_inclusion_patterns=(patterns)
+ @backtrace_cleaner.inclusion_patterns = patterns
+ end
+
+ # The patterns to discard from backtraces.
+ #
+ # Defaults to RSpec::Core::BacktraceCleaner::DEFAULT_EXCLUSION_PATTERNS
+ #
+ # One can replace the list by using the setter or modify it through the
+ # getter
+ #
+ # To override this behaviour and display a full backtrace, use
+ # `--backtrace`on the command line, in a `.rspec` file, or in the
+ # `rspec_options` attribute of RSpec's rake task.
+ def backtrace_exclusion_patterns
+ @backtrace_cleaner.exclusion_patterns
+ end
+
+ def backtrace_exclusion_patterns=(patterns)
+ @backtrace_cleaner.exclusion_patterns = patterns
+ end
+
# Sets the mock framework adapter module.
#
# `framework` can be a Symbol or a Module.
@@ -425,7 +459,7 @@ def expect_with(*frameworks)
end
def full_backtrace=(true_or_false)
- @backtrace_clean_patterns = true_or_false ? [] : DEFAULT_BACKTRACE_PATTERNS
+ @backtrace_cleaner.full_backtrace = true_or_false
end
def color(output=output_stream)
@@ -18,7 +18,7 @@ def format_backtrace(backtrace, options = {})
protected
def backtrace_line(line)
- return nil if RSpec.configuration.cleaned_from_backtrace?(line)
+ return nil if RSpec.configuration.backtrace_cleaner.exclude?(line)
RSpec::Core::Metadata::relative_path(line)
rescue SecurityError
nil
@@ -0,0 +1,56 @@
+require "spec_helper"
+
+module RSpec::Core
+ describe BacktraceCleaner do
+ context "with no patterns" do
+ it "keeps all lines" do
+ lines = ["/tmp/a_file", "some_random_text", "hello\330\271!"]
+ cleaner = BacktraceCleaner.new([], [])
+ expect(lines.all? {|line| cleaner.exclude? line}).to be_false
+ end
+ end
+
+ context "with an exclusion pattern but no inclusion patterns" do
+ it "excludes lines that match the exclusion pattern" do
+ cleaner = BacktraceCleaner.new([], [/remove/])
+ expect(cleaner.exclude? "remove me").to be_true
+ end
+
+ it "keeps lines that do not match the exclusion pattern" do
+ cleaner = BacktraceCleaner.new([], [/remove/])
+ expect(cleaner.exclude? "apple").to be_false
+ end
+ end
+
+ context "with an exclusion pattern and an inclusion pattern" do
+ it "excludes lines that match the exclusion pattern but not the inclusion pattern" do
+ cleaner = BacktraceCleaner.new([/keep/], [/discard/])
+ expect(cleaner.exclude? "discard").to be_true
+ end
+
+ it "keeps lines that match the inclusion pattern and the exclusion pattern" do
+ cleaner = BacktraceCleaner.new([/hi/], [/.*/])
+ expect(cleaner.exclude? "hi").to be_false
+ end
+
+ it "keeps lines that match neither pattern" do
+ cleaner = BacktraceCleaner.new([/hi/], [/delete/])
+ expect(cleaner.exclude? "fish").to be_false
+ end
+ end
+
+ context "with an exclusion pattern that matches the current working directory" do
+ it "defaults to having one inclusion pattern, the current working directory" do
+ cleaner = BacktraceCleaner.new(nil, [/.*/])
+ expect(Dir.getwd =~ cleaner.inclusion_patterns.first).to be_true
+ end
+ end
+
+ context "with an exclusion pattern that does not match the current working directory" do
+ it "defaults to having no exclusion patterns" do
+ cleaner = BacktraceCleaner.new(nil, [/i_wont_match_a_directory/])
+ expect(cleaner.inclusion_patterns.length).to be_zero
+ end
+ end
+ end
+end
@@ -940,16 +940,16 @@ def metadata_hash(*args)
describe "#full_backtrace=" do
context "given true" do
- it "clears the backtrace clean patterns" do
+ it "clears the backtrace exclusion patterns" do
config.full_backtrace = true
- expect(config.backtrace_clean_patterns).to eq([])
+ expect(config.backtrace_exclusion_patterns).to eq([])
end
end
context "given false" do
it "restores backtrace clean patterns" do
config.full_backtrace = false
- expect(config.backtrace_clean_patterns).to eq(RSpec::Core::Configuration::DEFAULT_BACKTRACE_PATTERNS)
+ expect(config.backtrace_exclusion_patterns).to eq(RSpec::Core::BacktraceCleaner::DEFAULT_EXCLUSION_PATTERNS)
end
end
@@ -958,29 +958,58 @@ def metadata_hash(*args)
config_2 = Configuration.new
config_1.full_backtrace = true
- expect(config_2.backtrace_clean_patterns).not_to be_empty
+ expect(config_2.backtrace_exclusion_patterns).not_to be_empty
end
end
- describe "#cleaned_from_backtrace? defaults" do
+ describe "#backtrace_clean_patterns=" do
+ it "actually receives the new filter values" do
+ RSpec.stub(:warn_deprecation)
+ config = Configuration.new
+ config.backtrace_clean_patterns = [/.*/]
+ expect(config.backtrace_cleaner.exclude? "this").to be_true
+ end
+ end
+
+ describe "#backtrace_clean_patterns" do
+ it "is deprecated" do
+ RSpec.stub(:warn_deprecation)
+ RSpec.should_receive(:warn_deprecation)
+ config = Configuration.new
+ config.backtrace_clean_patterns
+ end
+
+ it "can be appended to" do
+ RSpec.stub(:warn_deprecation)
+ config = Configuration.new
+ config.backtrace_clean_patterns << /.*/
+ expect(config.backtrace_cleaner.exclude? "this").to be_true
+ end
+ end
+
+ describe ".backtrace_cleaner#exclude? defaults" do
it "returns true for rspec files" do
- expect(config.cleaned_from_backtrace?("lib/rspec/core.rb")).to be_true
+ expect(config.backtrace_cleaner.exclude?("lib/rspec/core.rb")).to be_true
end
it "returns true for spec_helper" do
- expect(config.cleaned_from_backtrace?("spec/spec_helper.rb")).to be_true
+ expect(config.backtrace_cleaner.exclude?("spec/spec_helper.rb")).to be_true
end
it "returns true for java files (for JRuby)" do
- expect(config.cleaned_from_backtrace?("org/jruby/RubyArray.java:2336")).to be_true
+ expect(config.backtrace_cleaner.exclude?("org/jruby/RubyArray.java:2336")).to be_true
end
it "returns true for files within installed gems" do
- expect(config.cleaned_from_backtrace?('ruby-1.8.7-p334/gems/mygem-2.3.0/lib/mygem.rb')).to be_true
+ expect(config.backtrace_cleaner.exclude?('ruby-1.8.7-p334/gems/mygem-2.3.0/lib/mygem.rb')).to be_true
end
it "returns false for files in projects containing 'gems' in the name" do
- expect(config.cleaned_from_backtrace?('code/my-gems-plugin/lib/plugin.rb')).to be_false
+ expect(config.backtrace_cleaner.exclude?('code/my-gems-plugin/lib/plugin.rb')).to be_false
+ end
+
+ it "returns false for something in the current working directory" do
+ expect(config.backtrace_cleaner.exclude?("#{Dir.getwd}/arbitrary")).to be_false
end
end
@@ -33,6 +33,7 @@ module Formatters
out.set_encoding("utf-8") if out.respond_to?(:set_encoding)
command_line = RSpec::Core::CommandLine.new(options)
+ command_line.instance_variable_get("@configuration").backtrace_cleaner.inclusion_patterns = []
command_line.run(err, out)
out.string.gsub(/\d+\.\d+(s| seconds)/, "n.nnnn\\1")
end
@@ -33,6 +33,7 @@ module Formatters
out.set_encoding("utf-8") if out.respond_to?(:set_encoding)
command_line = RSpec::Core::CommandLine.new(options)
+ command_line.instance_variable_get("@configuration").backtrace_cleaner.inclusion_patterns = []
command_line.run(err, out)
out.string.gsub(/\d+\.\d+(s| seconds)/, "n.nnnn\\1")
end

0 comments on commit 8ac0f7e

Please sign in to comment.