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

Apply simplecov filters #38

Merged
merged 2 commits into from
Dec 1, 2018
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
## Unreleased ([changes](https://github.com/infertux/bashcov/compare/v1.8.2...master))

* TBD
* [FEATURE] Bashcov omits from the coverage results any files that match one
or more of the filters in `SimpleCov.filters`.
* [FEATURE] Ensure that files matching the `SimpleCov.tracked_files` glob
pattern are included in the coverage results, regardless of
whether `Bashcov.skip_uncovered` is enabled.

## v1.8.2, 2018-03-27 ([changes](https://github.com/infertux/bashcov/compare/v1.8.1...v1.8.2))

Expand Down
33 changes: 30 additions & 3 deletions lib/bashcov/runner.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "simplecov"

require "bashcov/detective"
require "bashcov/errors"
require "bashcov/field_stream"
Expand Down Expand Up @@ -126,15 +128,40 @@ def with_xtrace_flag
# Add files which have not been executed at all (i.e. with no coverage)
# @return [void]
def find_bash_files!
return if Bashcov.skip_uncovered

Pathname.new(Bashcov.root_directory).find do |filename|
filtered_files.each do |filename|
if !@coverage.include?(filename) && @detective.shellscript?(filename)
@coverage[filename] = []
end
end
end

# @return [Array<Pathname>] the list of files that should be included in
# coverage results, unless filtered by one or more SimpleCov filters
def tracked_files
return @tracked_files if defined? @tracked_files

mandatory = SimpleCov.tracked_files ? Pathname.glob(SimpleCov.tracked_files) : []
under_root = Bashcov.skip_uncovered ? [] : Pathname.new(Bashcov.root_directory).find.to_a

@tracked_files = (mandatory + under_root).uniq
end

# @return [Array<Pathname>] the list of files that should be included in
# coverage results
def filtered_files
return @filtered_files if defined? @filtered_files

source_files = tracked_files.map do |file|
SimpleCov::SourceFile.new(file.to_s, @coverage.fetch(file, []))
end

source_file_to_tracked_file = Hash[source_files.zip(tracked_files)]

@filtered_files = SimpleCov.filtered(source_files).map do |source_file|
source_file_to_tracked_file[source_file]
end
end

# @return [void]
def expunge_invalid_files!
@coverage.each_key do |filename|
Expand Down
35 changes: 35 additions & 0 deletions spec/bashcov/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
end
end

before(:each) do
# SimpleCov uses a block-based filter to reject from the coverage results
# any files that do not live under SimpleCov.root by matching filenames
# against a regular expression containing the value of SimpleCov.root.
# This regular expression is memoized during the first use of the filter in
# question, and is not re-initialized if SimpleCov.root changes. By mocking
# up an empty filter list, we ensure that no files are omitted from the
# runner's coverage results because they don't live under whatever
# directory happens to have been the value of SimpleCov.root at the time
# the filter was first run.
allow(SimpleCov).to receive(:filters).and_return([])
end

describe "#with_xtrace_flag" do
context "without a SHELLOPTS variable" do
before do
Expand Down Expand Up @@ -204,6 +217,14 @@
runner.run
expect(runner.result.keys & uncovered_files).to be_empty
end

context "when SimpleCov.tracked_files is defined" do
it "includes matching files even if they are uncovered" do
expect(SimpleCov).to receive(:tracked_files).at_least(:once).and_return(uncovered_files.first)
runner.run
expect(runner.result.keys & uncovered_files).to contain_exactly(*uncovered_files.first)
end
end
end

context "with mute = true" do
Expand All @@ -219,5 +240,19 @@
runner.run
end
end

context "with SimpleCov filters in effect" do
before(:each) do
SimpleCov.configure do
expected_omitted.each_key { |filter| add_filter(filter) }
end
end

it "omits files matching one or more SimpleCov filters from the results hash" do
runner.run
result = runner.result
expect(result.keys).to contain_exactly(*(expected_coverage.keys - expected_omitted.values.flatten))
end
end
end
end
3 changes: 2 additions & 1 deletion spec/bashcov/xtrace_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ def case_result

context "when shell expansion triggers subshell execution" do
it "causes extra hits to be reported" do
allow(Bashcov).to receive(:skip_uncovered).at_least(:once).and_return(true)

result_without_subshell = case_result

allow(Bashcov).to receive(:skip_uncovered).and_return(true)
allow(Bashcov::Xtrace).to receive(:ps4).and_return(subshell_ps4)

result_with_subshell = case_result
Expand Down
2 changes: 1 addition & 1 deletion spec/bashcov_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

describe Bashcov do
it "preserves the exit status" do
system("./bin/bashcov ./spec/test_app/scripts/exit_non_zero.sh")
system("./bin/bashcov --root ./spec/test_app ./spec/test_app/scripts/exit_non_zero.sh")
expect($?.exitstatus).not_to eq(0)
end

Expand Down
20 changes: 20 additions & 0 deletions spec/support/test_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,23 @@ def expected_missing
"#{test_app}/scripts/no_extension/usr_local_bin_gawk",
]
end

def expected_omitted
{
->(source_file) { File.basename(File.dirname(source_file.project_filename)) != "scripts" } => [
"#{test_app}/never_called.sh",
],
/multiline(?:\d)*/ => [
"#{test_app}/multiline.sh",
"#{test_app}/multiline2.sh",
"#{test_app}/multiline3.sh",
],
"/no_extension/" => [
"#{test_app}/scripts/no_extension/bin_bash",
"#{test_app}/scripts/no_extension/bin_bash_with_args",
"#{test_app}/scripts/no_extension/bin_dash",
"#{test_app}/scripts/no_extension/bin_sh",
"#{test_app}/scripts/no_extension/usr_bin_env_bash",
],
}
end