Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add regex filters #589

Merged
merged 7 commits into from
Jun 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ report.

### Defining custom filters

You can currently define a filter using either a String (that will then be Regexp-matched against each source file's path),
You can currently define a filter using either a String or Regexp (that will then be Regexp-matched against each source file's path),
a block or by passing in your own Filter class.

#### String filter
Expand All @@ -275,6 +275,16 @@ end

This simple string filter will remove all files that match "/test/" in their path.

#### Regex filter

```ruby
SimpleCov.start do
add_filter %r{^/test/}
end
```

This simple regex filter will remove all files that start with /test/ in their path.

#### Block filter

```ruby
Expand Down Expand Up @@ -305,6 +315,17 @@ Defining your own filters is pretty easy: Just inherit from SimpleCov::Filter an
the filter, a true return value from this method will result in the removal of the given source_file. The filter_argument method
is being set in the SimpleCov::Filter initialize method and thus is set to 5 in this example.

#### Array filter

```ruby
SimpleCov.start do
proc = Proc.new { |source_file| fales }
add_filter ["string", /regex/, proc, LineFilter.new(5)]
end
```

You can pass in an array containing any of the other filter types.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 👍


#### Ignoring/skipping code

You can exclude code from the coverage report by wrapping it in `# :nocov:`.
Expand Down
7 changes: 6 additions & 1 deletion doc/editor-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ Some editors have a graphical integration for the simplecov gem.

Adds an overview of your current test coverage to Atom.

#### [Sublime Editor: Simple​Cov](https://packagecontrol.io/packages/SimpleCov)
*by sentience*

Adds in editor live coverage highlighting, status bar coverage information, and summary coverage information.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 drive by fixes


#### [cadre](https://github.com/nyarly/cadre)
*by Judson Lester*

Includes a formatter for Simplecov that emits a Vim script to mark up code files with coverage information.
Includes a formatter for Simplecov that emits a Vim script to mark up code files with coverage information.
14 changes: 5 additions & 9 deletions lib/simplecov/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,12 @@ def add_group(group_name, filter_argument = nil, &filter_proc)
# The actual filter processor. Not meant for direct use
#
def parse_filter(filter_argument = nil, &filter_proc)
if filter_argument.is_a?(SimpleCov::Filter)
filter_argument
elsif filter_argument.is_a?(String)
SimpleCov::StringFilter.new(filter_argument)
elsif filter_proc
SimpleCov::BlockFilter.new(filter_proc)
elsif filter_argument.is_a?(Array)
SimpleCov::ArrayFilter.new(filter_argument)
filter = filter_argument || filter_proc

if filter
SimpleCov::Filter.build_filter(filter)
else
raise ArgumentError, "Please specify either a string or a block to filter with"
raise ArgumentError, "Please specify either a filter or a block to filter with"
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/simplecov/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
SimpleCov.profiles.define "rails" do
load_profile "test_frameworks"

add_filter "/config/"
add_filter "/db/"
add_filter %r{^/config/}
add_filter %r{/^/db/}

add_group "Controllers", "app/controllers"
add_group "Channels", "app/channels" if defined?(ActionCable)
Expand Down
43 changes: 39 additions & 4 deletions lib/simplecov/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,40 @@ def passes?(source_file)
warn "#{Kernel.caller.first}: [DEPRECATION] #passes? is deprecated. Use #matches? instead."
matches?(source_file)
end

def self.build_filter(filter_argument)
return filter_argument if filter_argument.is_a?(SimpleCov::Filter)
class_for_argument(filter_argument).new(filter_argument)
end

def self.class_for_argument(filter_argument)
if filter_argument.is_a?(String)
SimpleCov::StringFilter
elsif filter_argument.is_a?(Regexp)
SimpleCov::RegexFilter
elsif filter_argument.is_a?(Array)
SimpleCov::ArrayFilter
elsif filter_argument.is_a?(Proc)
SimpleCov::BlockFilter
else
raise ArgumentError, "You have provided an unrecognized filter type"
end
end
end

class StringFilter < SimpleCov::Filter
# Returns true when the given source file's filename matches the
# string configured when initializing this Filter with StringFilter.new('somestring)
def matches?(source_file)
(source_file.filename =~ /#{filter_argument}/)
(source_file.project_filename =~ /#{filter_argument}/)
end
end

class RegexFilter < SimpleCov::Filter
# Returns true when the given source file's filename matches the
# regex configured when initializing this Filter with RegexFilter.new(/someregex/)
def matches?(source_file)
(source_file.project_filename =~ filter_argument)
end
end

Expand All @@ -43,11 +70,19 @@ def matches?(source_file)
end

class ArrayFilter < SimpleCov::Filter
# Returns true if any of the file paths passed in the given array matches the string
# configured when initializing this Filter with StringFilter.new(['some/path', 'other/path'])
def initialize(filter_argument)
filter_objects = filter_argument.map do |arg|
Filter.build_filter(arg)
end

super(filter_objects)
end

# Returns true if any of the filters in the array match the given source file.
# Configure this Filter like StringFilter.new(['some/path', /^some_regex/, Proc.new {|src_file| ... }])
def matches?(source_files_list)
filter_argument.any? do |arg|
source_files_list.filename =~ /#{arg}/
arg.matches?(source_files_list)
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions lib/simplecov/source_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ def initialize(filename, coverage)
@coverage = coverage
end

# The path to this source file relative to the projects directory
def project_filename
@filename.sub(/^#{SimpleCov.root}/, "")
end

# The source code for this file. Aliased as :source
def src
# We intentionally read source code lazily to
Expand Down
74 changes: 74 additions & 0 deletions spec/filters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@
expect(SimpleCov::StringFilter.new("sample.rb")).to be_matches subject
end

it "doesn't match a parent directory with a new SimpleCov::StringFilter" do
parent_dir_name = File.basename(File.expand_path("..", File.dirname(__FILE__)))
expect(SimpleCov::StringFilter.new(parent_dir_name)).not_to be_matches subject
end

it "matches a new SimpleCov::StringFilter '/fixtures/'" do
expect(SimpleCov::StringFilter.new("sample.rb")).to be_matches subject
end

it "matches a new SimpleCov::RegexFilter /\/fixtures\//" do
expect(SimpleCov::RegexFilter.new(/\/fixtures\//)).to be_matches subject
end

it "doesn't match a new SimpleCov::RegexFilter /^\/fixtures\//" do
expect(SimpleCov::RegexFilter.new(/^\/fixtures\//)).not_to be_matches subject
end

it "matches a new SimpleCov::RegexFilter /^\/spec\//" do
expect(SimpleCov::RegexFilter.new(/^\/spec\//)).to be_matches subject
end

it "doesn't match a new SimpleCov::BlockFilter that is not applicable" do
expect(SimpleCov::BlockFilter.new(proc { |s| File.basename(s.filename) == "foo.rb" })).not_to be_matches subject
end
Expand All @@ -46,6 +67,45 @@
expect(SimpleCov::ArrayFilter.new(["sample.rb", "other_file.rb"])).to be_matches subject
end

it "doesn't match a parent directory with a new SimpleCov::ArrayFilter" do
parent_dir_name = File.basename(File.expand_path("..", File.dirname(__FILE__)))
expect(SimpleCov::ArrayFilter.new([parent_dir_name])).not_to be_matches subject
end

it "matches a new SimpleCov::ArrayFilter when /sample.rb/ is passed as array" do
expect(SimpleCov::ArrayFilter.new([/sample.rb/])).to be_matches subject
end

it "doesn't match a new SimpleCov::ArrayFilter when a file path different than /sample.rb/ is passed as array" do
expect(SimpleCov::ArrayFilter.new([/other_file.rb/])).not_to be_matches subject
end

it "matches a new SimpleCov::ArrayFilter when a block is passed as array and returns true" do
expect(SimpleCov::ArrayFilter.new([proc { true }])).to be_matches subject
end

it "doesn't match a new SimpleCov::ArrayFilter when a block that returns false is passed as array" do
expect(SimpleCov::ArrayFilter.new([proc { false }])).not_to be_matches subject
end

it "matches a new SimpleCov::ArrayFilter when a custom class that returns true is passed as array" do
filter = Class.new(SimpleCov::Filter) do
def matches?(_)
true
end
end.new(nil)
expect(SimpleCov::ArrayFilter.new([filter])).to be_matches subject
end

it "doesn't match a new SimpleCov::ArrayFilter when a custom class that returns false is passed as array" do
filter = Class.new(SimpleCov::Filter) do
def matches?(_)
false
end
end.new(nil)
expect(SimpleCov::ArrayFilter.new([filter])).not_to be_matches subject
end

context "with no filters set up and a basic source file in an array" do
before do
@prev_filters = SimpleCov.filters
Expand Down Expand Up @@ -94,5 +154,19 @@
expect(SimpleCov.filtered(subject)).to be_a SimpleCov::FileList
end
end

describe ".class_for_argument" do
it "returns SimpleCov::StringFilter for a string" do
expect(SimpleCov::Filter.class_for_argument("filestring")).to eq(SimpleCov::StringFilter)
end

it "returns SimpleCov::RegexFilter for a string" do
expect(SimpleCov::Filter.class_for_argument(/regex/)).to eq(SimpleCov::RegexFilter)
end

it "returns SimpleCov::RegexFilter for a string" do
expect(SimpleCov::Filter.class_for_argument(%w[file1 file2])).to eq(SimpleCov::ArrayFilter)
end
end
end
end
4 changes: 4 additions & 0 deletions spec/source_file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
expect(subject.src).to eq(subject.source)
end

it "has a project filename which removes the project directory" do
expect(subject.project_filename).to eq("/spec/fixtures/sample.rb")
end

it "has source_lines equal to lines" do
expect(subject.lines).to eq(subject.source_lines)
end
Expand Down