Cleanup and comment

This commit is contained in:
Tuncer Ayaz 2012-08-20 13:55:55 +02:00
parent 60516dc406
commit 3c0d97bf2c
3 changed files with 95 additions and 57 deletions

View file

@ -297,13 +297,16 @@ generate-upgrade previous_release=path Build an upgrade package
generate-appups previous_release=path Generate appup files generate-appups previous_release=path Generate appup files
eunit [suites=foo] Run eunit tests [foo.erl and test/foo_tests.erl] eunit [suites=foo] Run eunit tests in foo.erl and
[suites=foo] [tests=bar] Run specific eunit tests [first test name starting test/foo_tests.erl
with 'bar' in foo.erl and test/foo_tests.erl] [suites=foo] [tests=bar] Run specific eunit tests [first test name
[tests=bar] For every existing suite, run the first test whose starting with 'bar' in foo.erl and
name starts with bar and, if no such test exists, test/foo_tests.erl]
run the test whose name starts with bar in [tests=bar] For every existing suite, run the first
the suite's _tests module test whose name starts with bar and, if
no such test exists, run the test whose
name starts with bar in the suite's
_tests module
ct [suites=] [case=] Run common_test suites ct [suites=] [case=] Run common_test suites

View file

@ -119,7 +119,7 @@ run_eunit(Config, CodePath, SrcErls) ->
AllModules = [rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- AllBeamFiles], AllModules = [rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- AllBeamFiles],
{SuitesProvided, FilteredModules} = filter_suites(Config, AllModules), {SuitesProvided, FilteredModules} = filter_suites(Config, AllModules),
%% build the tests %% Get matching tests
Tests = get_tests(Config, SuitesProvided, ModuleBeamFiles, FilteredModules), Tests = get_tests(Config, SuitesProvided, ModuleBeamFiles, FilteredModules),
SrcModules = [rebar_utils:erl_to_mod(M) || M <- SrcErls], SrcModules = [rebar_utils:erl_to_mod(M) || M <- SrcErls],
@ -169,6 +169,10 @@ setup_code_path() ->
true = code:add_pathz(rebar_utils:ebin_dir()), true = code:add_pathz(rebar_utils:ebin_dir()),
CodePath. CodePath.
%%
%% == filter suites ==
%%
filter_suites(Config, Modules) -> filter_suites(Config, Modules) ->
RawSuites = rebar_config:get_global(Config, suites, ""), RawSuites = rebar_config:get_global(Config, suites, ""),
SuitesProvided = RawSuites =/= "", SuitesProvided = RawSuites =/= "",
@ -180,65 +184,59 @@ filter_suites1(Modules, []) ->
filter_suites1(Modules, Suites) -> filter_suites1(Modules, Suites) ->
[M || M <- Modules, lists:member(M, Suites)]. [M || M <- Modules, lists:member(M, Suites)].
%%
%% == get matching tests ==
%%
get_tests(Config, SuitesProvided, ModuleBeamFiles, FilteredModules) -> get_tests(Config, SuitesProvided, ModuleBeamFiles, FilteredModules) ->
Modules = case SuitesProvided of Modules = case SuitesProvided of
false -> false ->
%% No specific suites have been provided, use ModuleBeamFiles %% No specific suites have been provided, use
%% which filters out "*_tests" modules so eunit won't doubly run %% ModuleBeamFiles which filters out "*_tests" modules
%% them and cover only calculates coverage on production code. %% so eunit won't doubly run them and cover only
%% However, keep "*_tests" modules that are not automatically %% calculates coverage on production code. However,
%% keep "*_tests" modules that are not automatically
%% included by eunit. %% included by eunit.
%% %%
%% From 'Primitives' in the EUnit User's Guide %% From 'Primitives' in the EUnit User's Guide
%% http://www.erlang.org/doc/apps/eunit/chapter.html %% http://www.erlang.org/doc/apps/eunit/chapter.html
%% "In addition, EUnit will also look for another module whose %% "In addition, EUnit will also look for another
%% name is ModuleName plus the suffix _tests, and if it exists, %% module whose name is ModuleName plus the suffix
%% all the tests from that module will also be added. (If %% _tests, and if it exists, all the tests from that
%% ModuleName already contains the suffix _tests, this is not %% module will also be added. (If ModuleName already
%% done.) E.g., the specification {module, mymodule} will run all %% contains the suffix _tests, this is not done.) E.g.,
%% tests in the modules mymodule and mymodule_tests. Typically, %% the specification {module, mymodule} will run all
%% the _tests module should only contain test cases that use the %% tests in the modules mymodule and mymodule_tests.
%% public interface of the main module (and no other code)." %% Typically, the _tests module should only contain
[rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- ModuleBeamFiles]; %% test cases that use the public interface of the main
%% module (and no other code)."
[rebar_utils:beam_to_mod(?EUNIT_DIR, N) ||
N <- ModuleBeamFiles];
true -> true ->
%% Specific suites have been provided, return the filtered modules %% Specific suites have been provided, return the
%% filtered modules
FilteredModules FilteredModules
end, end,
build_tests(Config, Modules). get_matching_tests(Config, Modules).
build_tests(Config, Modules) -> get_matching_tests(Config, Modules) ->
RawFunctions = rebar_utils:get_experimental_global(Config, tests, ""), RawFunctions = rebar_utils:get_experimental_global(Config, tests, ""),
Tests = [list_to_atom(F1) || F1 <- string:tokens(RawFunctions, ",")], Tests = [list_to_atom(F1) || F1 <- string:tokens(RawFunctions, ",")],
case Tests of case Tests of
[] -> [] ->
Modules; Modules;
Functions -> Functions ->
case build_tests1(Modules, Functions, []) of case get_matching_tests1(Modules, Functions, []) of
[] -> [] ->
[]; [];
RawTests -> RawTests ->
?CONSOLE(" Running test function(s):~n", []), make_test_wrappers(RawTests)
F = fun({M, F2}, Acc) ->
?CONSOLE(" ~p:~p/0~n", [M, F2]),
FNameStr = atom_to_list(F2),
NewFunction = case re:run(FNameStr, "_test_") =/= nomatch of
true ->
%% Generator
{generator, eunit_test:function_wrapper(M, F2)};
_ ->
%% Normal test
eunit_test:function_wrapper(M, F2)
end,
[NewFunction|Acc]
end,
lists:foldl(F, [], RawTests)
end end
end. end.
build_tests1([], _Functions, TestFunctions) -> get_matching_tests1([], _Functions, TestFunctions) ->
TestFunctions; TestFunctions;
build_tests1([Module|TModules], Functions, TestFunctions) -> get_matching_tests1([Module|TModules], Functions, TestFunctions) ->
%% Get module exports %% Get module exports
ModuleStr = atom_to_list(Module), ModuleStr = atom_to_list(Module),
ModuleExports = get_beam_test_exports(ModuleStr), ModuleExports = get_beam_test_exports(ModuleStr),
@ -246,11 +244,12 @@ build_tests1([Module|TModules], Functions, TestFunctions) ->
TestModuleStr = string:concat(ModuleStr, "_tests"), TestModuleStr = string:concat(ModuleStr, "_tests"),
TestModuleExports = get_beam_test_exports(TestModuleStr), TestModuleExports = get_beam_test_exports(TestModuleStr),
%% Build tests {M, F} list %% Build tests {M, F} list
Tests = build_tests2(Functions, {Module, ModuleExports}, Tests = get_matching_tests2(Functions, {Module, ModuleExports},
{list_to_atom(TestModuleStr), TestModuleExports}), {list_to_atom(TestModuleStr), TestModuleExports}),
build_tests1(TModules, Functions, lists:merge([TestFunctions, Tests])). get_matching_tests1(TModules, Functions,
lists:merge([TestFunctions, Tests])).
build_tests2(Functions, {Mod, ModExports}, {TestMod, TestModExports}) -> get_matching_tests2(Functions, {Mod, ModExports}, {TestMod, TestModExports}) ->
%% Look for matching functions into ModExports %% Look for matching functions into ModExports
ModExportsStr = [atom_to_list(E1) || E1 <- ModExports], ModExportsStr = [atom_to_list(E1) || E1 <- ModExports],
TestModExportsStr = [atom_to_list(E2) || E2 <- TestModExports], TestModExportsStr = [atom_to_list(E2) || E2 <- TestModExports],
@ -308,6 +307,34 @@ get_beam_test_exports(ModuleStr) ->
[] []
end. end.
make_test_wrappers(RawTests) ->
?CONSOLE(" Running test function(s):~n", []),
F = fun({M, F2}, Acc) ->
?CONSOLE(" ~p:~p/0~n", [M, F2]),
FNameStr = atom_to_list(F2),
NewFunction =
case re:run(FNameStr, "_test_") of
nomatch ->
%% Normal test
eunit_test(M, F2);
_ ->
%% Generator
eunit_generator(M, F2)
end,
[NewFunction|Acc]
end,
lists:foldl(F, [], RawTests).
eunit_test(M, F) ->
eunit_test:function_wrapper(M, F).
eunit_generator(M, F) ->
{generator, eunit_test:function_wrapper(M, F)}.
%%
%% == run tests ==
%%
perform_eunit(Config, Tests) -> perform_eunit(Config, Tests) ->
EunitOpts = get_eunit_opts(Config), EunitOpts = get_eunit_opts(Config),
@ -334,6 +361,10 @@ get_eunit_opts(Config) ->
BaseOpts ++ rebar_config:get_list(Config, eunit_opts, []). BaseOpts ++ rebar_config:get_list(Config, eunit_opts, []).
%%
%% == code coverage ==
%%
perform_cover(Config, BeamFiles, SrcModules) -> perform_cover(Config, BeamFiles, SrcModules) ->
perform_cover(rebar_config:get(Config, cover_enabled, false), perform_cover(rebar_config:get(Config, cover_enabled, false),
Config, BeamFiles, SrcModules). Config, BeamFiles, SrcModules).
@ -486,7 +517,7 @@ cover_write_index(Coverage, SrcModules) ->
cover_write_index_section(_F, _SectionName, []) -> cover_write_index_section(_F, _SectionName, []) ->
ok; ok;
cover_write_index_section(F, SectionName, Coverage) -> cover_write_index_section(F, SectionName, Coverage) ->
%% Calculate total coverage % %% Calculate total coverage
{Covered, NotCovered} = lists:foldl(fun({_Mod, C, N}, {CAcc, NAcc}) -> {Covered, NotCovered} = lists:foldl(fun({_Mod, C, N}, {CAcc, NAcc}) ->
{CAcc + C, NAcc + N} {CAcc + C, NAcc + N}
end, {0, 0}, Coverage), end, {0, 0}, Coverage),
@ -548,14 +579,18 @@ percentage(0, 0) ->
percentage(Cov, NotCov) -> percentage(Cov, NotCov) ->
integer_to_list(trunc((Cov / (Cov + NotCov)) * 100)) ++ "%". integer_to_list(trunc((Cov / (Cov + NotCov)) * 100)) ++ "%".
get_app_names() -> %%
[AppName || {AppName, _, _} <- application:loaded_applications()]. %% == reset_after_eunit ==
%%
status_before_eunit() -> status_before_eunit() ->
Apps = get_app_names(), Apps = get_app_names(),
AppEnvs = [{App, application:get_all_env(App)} || App <- Apps], AppEnvs = [{App, application:get_all_env(App)} || App <- Apps],
{erlang:processes(), erlang:is_alive(), AppEnvs, ets:tab2list(ac_tab)}. {erlang:processes(), erlang:is_alive(), AppEnvs, ets:tab2list(ac_tab)}.
get_app_names() ->
[AppName || {AppName, _, _} <- application:loaded_applications()].
reset_after_eunit({OldProcesses, WasAlive, OldAppEnvs, _OldACs}) -> reset_after_eunit({OldProcesses, WasAlive, OldAppEnvs, _OldACs}) ->
IsAlive = erlang:is_alive(), IsAlive = erlang:is_alive(),
if not WasAlive andalso IsAlive -> if not WasAlive andalso IsAlive ->