Skip to content

Commit

Permalink
Enable including only selected modules in coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
srijan committed May 6, 2022
1 parent fc58a31 commit 0204b39
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src/rebar_prv_common_test.erl
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,13 @@ format_skipped({User, Auto}) ->
maybe_cover_compile(State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
State1 = case proplists:get_value(cover, RawOpts, false) of
true -> rebar_state:set(State, cover_enabled, true);
true ->
S1 = rebar_state:set(State, cover_enabled, true),
CoverInclMods = case proplists:get_value(cover_incl_mods, RawOpts) of
undefined -> undefined;
Mods -> split_string(Mods)
end,
rebar_state:set(S1, cover_incl_mods, CoverInclMods);
false -> State
end,
rebar_prv_cover:maybe_cover_compile(State1).
Expand Down Expand Up @@ -856,6 +862,7 @@ ct_opts(_State) ->
{logopts, undefined, "logopts", string, help(logopts)}, %% comma-separated list
{verbosity, undefined, "verbosity", integer, help(verbosity)}, %% Integer
{cover, $c, "cover", {boolean, false}, help(cover)},
{cover_incl_mods, undefined, "cover_incl_mods", string, help(cover_incl_mods)}, %% comma-separated list
{cover_export_name, undefined, "cover_export_name", string, help(cover_export_name)},
{repeat, undefined, "repeat", integer, help(repeat)}, %% integer
{duration, undefined, "duration", string, help(duration)}, % format: HHMMSS
Expand Down Expand Up @@ -911,6 +918,8 @@ help(verbosity) ->
"Verbosity";
help(cover) ->
"Generate cover data";
help(cover_incl_mods) ->
"List of modules to include for coverage";
help(cover_export_name) ->
"Base name of the coverdata file to write";
help(repeat) ->
Expand Down
36 changes: 32 additions & 4 deletions src/rebar_prv_cover.erl
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ do(State) ->

-spec maybe_cover_compile(rebar_state:t()) -> ok.
maybe_cover_compile(State) ->
maybe_cover_compile(State, apps).
case rebar_state:get(State, cover_incl_mods, undefined) of
undefined -> maybe_cover_compile(State, apps);
Mods -> maybe_cover_compile(State, {modules, Mods})
end.

-spec maybe_cover_compile(rebar_state:t(), [file:name()] | apps) -> ok.
-spec maybe_cover_compile(rebar_state:t(), [file:name()] | apps | {modules, [module()]}) -> ok.
maybe_cover_compile(State, Dirs) ->
case rebar_state:get(State, cover_enabled, false) of
true -> cover_compile(State, Dirs);
Expand Down Expand Up @@ -92,8 +95,14 @@ analyze(State) ->
%% in order for cover data to be reloaded
%% this maybe breaks if modules have been deleted
%% since code coverage was collected?
{ok, S} = rebar_prv_compile:do(State),
ok = cover_compile(S, apps),
{ok, S1} = rebar_prv_compile:do(State),
{RawOpts, _} = rebar_state:command_parsed_args(S1),
CoverInclMods = case proplists:get_value(cover_incl_mods, RawOpts) of
undefined -> undefined;
Mods -> rebar_string:lexemes(Mods, [$,])
end,
S2 = rebar_state:set(S1, cover_incl_mods, CoverInclMods),
ok = maybe_cover_compile(S2),
do_analyze(State).

do_analyze(State) ->
Expand Down Expand Up @@ -319,6 +328,17 @@ cover_compile(State, apps) ->
Apps = filter_checkouts_and_excluded(rebar_state:project_apps(State), ExclApps),
AppDirs = app_dirs(Apps),
cover_compile(State, lists:filter(fun(D) -> ec_file:is_dir(D) end, AppDirs));
cover_compile(State, {modules, Mods}) ->
rebar_paths:set_paths([deps], State),
%% start the cover server if necessary
{ok, CoverPid} = start_cover(),
%% redirect cover output
true = redirect_cover_output(State, CoverPid),
?DEBUG("cover compiling modules: ~p", [Mods]),
lists:foreach(fun(Module) ->
cover_compile_module(erlang:list_to_atom(Module))
end, Mods),
ok;
cover_compile(State, Dirs) ->
rebar_paths:set_paths([deps], State),
%% start the cover server if necessary
Expand Down Expand Up @@ -354,6 +374,12 @@ is_ignored(Dir, File, ExclMods) ->
Ignored andalso ?DEBUG("cover ignoring ~p ~p", [Dir, File]),
Ignored.

cover_compile_module(Module) ->
case catch cover:compile_beam(Module) of
{ok, _} -> ok;
Error -> ?WARN("Cover compilation failed: ~p", [Error])
end.

cover_compile_file(FileName) ->
case catch(cover:compile_beam(FileName)) of
{error, Reason} ->
Expand Down Expand Up @@ -436,8 +462,10 @@ cover_dir(State) ->
cover_opts(_State) ->
[{reset, $r, "reset", boolean, help(reset)},
{verbose, $v, "verbose", boolean, help(verbose)},
{cover_incl_mods, undefined, "cover_incl_mods", string, help(cover_incl_mods)}, %% comma-separated list
{min_coverage, $m, "min_coverage", integer, help(min_coverage)}].

help(reset) -> "Reset all coverdata.";
help(verbose) -> "Print coverage analysis.";
help(cover_incl_mods) -> "List of modules to include for coverage";
help(min_coverage) -> "Mandate a coverage percentage required to succeed (0..100)".
10 changes: 9 additions & 1 deletion src/rebar_prv_eunit.erl
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,13 @@ apply_sys_config(State) ->
maybe_cover_compile(State) ->
{RawOpts, _} = rebar_state:command_parsed_args(State),
State1 = case proplists:get_value(cover, RawOpts, false) of
true -> rebar_state:set(State, cover_enabled, true);
true ->
S1 = rebar_state:set(State, cover_enabled, true),
CoverInclMods = case proplists:get_value(cover_incl_mods, RawOpts) of
undefined -> undefined;
Mods -> rebar_string:lexemes(Mods, [$,])
end,
rebar_state:set(S1, cover_incl_mods, CoverInclMods);
false -> State
end,
rebar_prv_cover:maybe_cover_compile(State1).
Expand All @@ -561,6 +567,7 @@ eunit_opts(_State) ->
[{app, undefined, "app", string, help(app)},
{application, undefined, "application", string, help(app)},
{cover, $c, "cover", boolean, help(cover)},
{cover_incl_mods, undefined, "cover_incl_mods", string, help(cover_incl_mods)},
{cover_export_name, undefined, "cover_export_name", string, help(cover_export_name)},
{profile, $p, "profile", boolean, help(profile)},
{dir, $d, "dir", string, help(dir)},
Expand All @@ -577,6 +584,7 @@ eunit_opts(_State) ->

help(app) -> "Comma separated list of application test suites to run. Equivalent to `[{application, App}]`.";
help(cover) -> "Generate cover data. Defaults to false.";
help(cover_incl_mods) -> "List of modules to include for coverage";
help(cover_export_name) -> "Base name of the coverdata file to write";
help(profile) -> "Show the slowest tests. Defaults to false.";
help(dir) -> "Comma separated list of dirs to load tests from. Equivalent to `[{dir, Dir}]`.";
Expand Down

0 comments on commit 0204b39

Please sign in to comment.