diff --git a/README.md b/README.md index cb32dcf..a4dfeb5 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,12 @@ Optionally, the `ignore_paths` option can be a list of path prefixes to ignore w ] ``` +Optionally, the `ignore_modules` option can be a list of module names as atoms and regular expressions that are matched against the module names to ignore when generating the coverage report. + +```elixir +test_coverage: [tool: LcovEx, output: "cover", ignore_modules: [MyApp.IgnoreModule, ~r/.*Test/]], +``` + ## TODOs - Add missing `FN` lines, for the sake of completion. diff --git a/example_project/lib/example_project/example_ignore_module.ex b/example_project/lib/example_project/example_ignore_module.ex new file mode 100644 index 0000000..a213ae3 --- /dev/null +++ b/example_project/lib/example_project/example_ignore_module.ex @@ -0,0 +1,11 @@ +defmodule ExampleProject.ExampleIgnoreModule do + @moduledoc false + + def cover() do + get_value() + end + + defp get_value() do + :covered + end +end diff --git a/example_project/lib/example_project/example_ignore_regex_module.ex b/example_project/lib/example_project/example_ignore_regex_module.ex new file mode 100644 index 0000000..4a522b8 --- /dev/null +++ b/example_project/lib/example_project/example_ignore_regex_module.ex @@ -0,0 +1,11 @@ +defmodule ExampleProject.ExampleIgnoreRegexModule do + @moduledoc false + + def cover() do + get_value() + end + + defp get_value() do + :covered + end +end diff --git a/lib/lcov_ex.ex b/lib/lcov_ex.ex index 19a4258..39188b5 100644 --- a/lib/lcov_ex.ex +++ b/lib/lcov_ex.ex @@ -21,7 +21,8 @@ defmodule LcovEx do output = opts[:output] caller_cwd = opts[:cwd] || File.cwd!() - ignored_paths = Keyword.get(opts, :ignore_paths, []) + ignored_paths = opts[:ignore_paths] || [] + ignored_modules = opts[:ignore_modules] || [] fn -> log_info("\nGenerating lcov file...") @@ -29,7 +30,9 @@ defmodule LcovEx do lcov = :cover.modules() |> Enum.sort() - |> Enum.map(&calculate_module_coverage(&1, ignored_paths, caller_cwd)) + |> Enum.reject(&ignored_module?(&1, ignored_modules)) + |> Enum.reject(&ignored_path?(&1, ignored_paths, caller_cwd)) + |> Enum.map(&calculate_module_coverage(&1, caller_cwd)) File.mkdir_p!(output) path = "#{output}/lcov.info" @@ -41,17 +44,24 @@ defmodule LcovEx do end end - defp calculate_module_coverage(mod, ignored_paths, cwd) do + defp ignored_module?(mod, ignored_modules), + do: Enum.any?(ignored_modules, &ignored_any?(mod, &1)) + + defp ignored_any?(mod, %Regex{} = re), do: Regex.match?(re, inspect(mod)) + defp ignored_any?(mod, other), do: mod == other + + # Ignore compiled modules with path: + # - not relative to the app (e.g. generated by umbrella dependencies) + # - ignored by configuration + defp ignored_path?(mod, ignored_paths, cwd) do path = mod.module_info(:compile)[:source] |> to_string() |> Path.relative_to(cwd) - # Ignore compiled modules with path: - # - not relative to the app (e.g. generated by umbrella dependencies) - # - ignored by configuration - if Path.type(path) != :relative or Enum.any?(ignored_paths, &String.starts_with?(path, &1)) do - [] - else - calculate_and_format_coverage(mod, path) - end + Path.type(path) != :relative or Enum.any?(ignored_paths, &String.starts_with?(path, &1)) + end + defp calculate_module_coverage(mod, cwd) do + path = mod.module_info(:compile)[:source] |> to_string() |> Path.relative_to(cwd) + + calculate_and_format_coverage(mod, path) end defp calculate_and_format_coverage(mod, path) do diff --git a/test/lcov_ex_test.exs b/test/lcov_ex_test.exs index 91305a9..a9d26e0 100644 --- a/test/lcov_ex_test.exs +++ b/test/lcov_ex_test.exs @@ -6,7 +6,13 @@ defmodule LcovExTest do setup do mix_path = "#{File.cwd!()}/example_project/mix.exs" |> String.replace("//", "/") MixFileHelper.backup(mix_path) - config = [test_coverage: [tool: LcovEx, ignore_paths: ["deps/"]]] + config = [ + test_coverage: [ + tool: LcovEx, + ignore_paths: ["deps/"], + ignore_modules: [ExampleProject.ExampleIgnoreModule, ~r/.*ExampleIgnoreRegex.*/] + ] + ] MixFileHelper.update_project_config(mix_path, config) on_exit(fn -> diff --git a/test/tasks/lcov_test.exs b/test/tasks/lcov_test.exs index 82d4921..29acc9c 100644 --- a/test/tasks/lcov_test.exs +++ b/test/tasks/lcov_test.exs @@ -151,6 +151,28 @@ defmodule LcovEx.Tasks.LcovTest do LF:1 LH:1 end_of_record + TN:Elixir.ExampleProject.ExampleIgnoreModule + SF:lib/example_project/example_ignore_module.ex + FNDA:0,cover/0 + FNDA:0,get_value/0 + FNF:2 + FNH:0 + DA:5,0 + DA:8,0 + LF:2 + LH:0 + end_of_record + TN:Elixir.ExampleProject.ExampleIgnoreRegexModule + SF:lib/example_project/example_ignore_regex_module.ex + FNDA:0,cover/0 + FNDA:0,get_value/0 + FNF:2 + FNH:0 + DA:5,0 + DA:8,0 + LF:2 + LH:0 + end_of_record TN:Elixir.ExampleProject.ExampleModule SF:lib/example_project/example_module.ex FNDA:1,cover/0