Backtrace cleaner #843

Merged
merged 21 commits into from Mar 26, 2013
Select commit
+202 −39
View
42 lib/rspec/core/backtrace_cleaner.rb
@@ -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
@myronmarston
RSpec member

Nice work moving full_backtrace here -- I had forgotten about it but it definitely belongs here!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ private
+
+ def matches_an_exclusion_pattern?(line)
+ @exclusion_patterns.any? {|p| line =~ p}
+ end
+ end
+ end
+end
View
90 lib/rspec/core/configuration.rb
@@ -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.
@myronmarston
RSpec member

Also, seeing this documentation go away reminds me that we need to document the methods you added below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
- 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)
View
2 lib/rspec/core/formatters/helpers.rb
@@ -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
View
56 spec/rspec/core/backtrace_cleaner_spec.rb
@@ -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
View
49 spec/rspec/core/configuration_spec.rb
@@ -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
View
1 spec/rspec/core/formatters/html_formatter_spec.rb
@@ -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
View
1 spec/rspec/core/formatters/text_mate_formatter_spec.rb
@@ -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