summaryrefslogtreecommitdiff
path: root/src/rebar_eunit.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_eunit.erl')
-rw-r--r--src/rebar_eunit.erl119
1 files changed, 71 insertions, 48 deletions
diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl
index 1341f9d..aee487c 100644
--- a/src/rebar_eunit.erl
+++ b/src/rebar_eunit.erl
@@ -1,4 +1,4 @@
-%% -*- tab-width: 4;erlang-indent-level: 4;indent-tabs-mode: nil -*-
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ts=4 sw=4 et
%% -------------------------------------------------------------------
%%
@@ -36,15 +36,15 @@
%% <li>suite="foo"" - runs test/foo_tests.erl</li>
%% </ul>
%% Additionally, for projects that have separate folders for the core
-%% implementation, and for the unit tests, then the following <code>rebar.config</code>
-%% option can be provided: <code>{eunit_compile_opts, [{src_dirs, ["dir"]}]}.</code>.
+%% implementation, and for the unit tests, then the following
+%% <code>rebar.config</code> option can be provided:
+%% <code>{eunit_compile_opts, [{src_dirs, ["dir"]}]}.</code>.
%% @copyright 2009, 2010 Dave Smith
%% -------------------------------------------------------------------
-module(rebar_eunit).
--export([eunit/2]).
-
--compile([export_all]).
+-export([eunit/2,
+ clean/2]).
-include("rebar.hrl").
@@ -78,16 +78,17 @@ eunit(Config, AppFile) ->
ok = filelib:ensure_dir(eunit_dir() ++ "/foo"),
ok = filelib:ensure_dir(ebin_dir() ++ "/foo"),
- %% Setup code path prior to compilation so that parse_transforms and the like
- %% work properly. Also, be sure to add ebin_dir() to the END of the code path
- %% so that we don't have to jump through hoops to access the .app file
+ %% Setup code path prior to compilation so that parse_transforms
+ %% and the like work properly. Also, be sure to add ebin_dir()
+ %% to the END of the code path so that we don't have to jump
+ %% through hoops to access the .app file
CodePath = code:get_path(),
true = code:add_patha(eunit_dir()),
true = code:add_pathz(ebin_dir()),
%% Obtain all the test modules for inclusion in the compile stage.
- %% Notice: this could also be achieved with the following rebar.config option:
- %% {eunit_compile_opts, [{src_dirs, ["test"]}]}
+ %% Notice: this could also be achieved with the following
+ %% rebar.config option: {eunit_compile_opts, [{src_dirs, ["test"]}]}
TestErls = rebar_utils:find_files("test", ".*\\.erl\$"),
%% Copy source files to eunit dir for cover in case they are not directly
@@ -99,7 +100,8 @@ eunit(Config, AppFile) ->
%% Compile erlang code to ?EUNIT_DIR, using a tweaked config
%% with appropriate defines for eunit, and include all the test modules
%% as well.
- rebar_erlc_compiler:doterl_compile(eunit_config(Config), ?EUNIT_DIR, TestErls),
+ rebar_erlc_compiler:doterl_compile(eunit_config(Config),
+ ?EUNIT_DIR, TestErls),
%% Build a list of all the .beams in ?EUNIT_DIR -- use this for cover
%% and eunit testing. Normally you can just tell cover and/or eunit to
@@ -111,7 +113,7 @@ eunit(Config, AppFile) ->
string:str(N, "_tests.beam") =:= 0],
Modules = [rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- BeamFiles],
SrcModules = [rebar_utils:erl_to_mod(M) || M <- SrcErls],
-
+
cover_init(Config, BeamFiles),
EunitResult = perform_eunit(Config, Modules),
perform_cover(Config, Modules, SrcModules),
@@ -175,37 +177,47 @@ get_eunit_opts(Config) ->
BaseOpts ++ rebar_config:get_list(Config, eunit_opts, []).
eunit_config(Config) ->
- EqcOpts = case is_quickcheck_avail() of
- true ->
- [{d, 'EQC'}];
- false ->
- []
- end,
+ EqcOpts = eqc_opts(),
+ PropErOpts = proper_opts(),
ErlOpts = rebar_config:get_list(Config, erl_opts, []),
EunitOpts = rebar_config:get_list(Config, eunit_compile_opts, []),
Opts = [{d, 'TEST'}, debug_info] ++
- ErlOpts ++ EunitOpts ++ EqcOpts,
- rebar_config:set(Config, erl_opts, Opts).
+ ErlOpts ++ EunitOpts ++ EqcOpts ++ PropErOpts,
+ Config1 = rebar_config:set(Config, erl_opts, Opts),
+
+ FirstErls = rebar_config:get_list(Config1, eunit_first_files, []),
+ rebar_config:set(Config1, erl_first_files, FirstErls).
+
+
+eqc_opts() ->
+ define_if('PROPER', is_lib_avail(is_eqc_avail, eqc,
+ "eqc.hrl", "QuickCheck")).
+proper_opts() ->
+ define_if('EQC', is_lib_avail(is_proper_avail, proper,
+ "proper.hrl", "PropEr")).
+
+define_if(Def, true) -> [{d, Def}];
+define_if(_Def, false) -> [].
-is_quickcheck_avail() ->
- case erlang:get(is_quickcheck_avail) of
+is_lib_avail(DictKey, Mod, Hrl, Name) ->
+ case erlang:get(DictKey) of
undefined ->
- case code:lib_dir(eqc, include) of
- {error, bad_name} ->
- IsAvail = false;
- Dir ->
- IsAvail = filelib:is_file(filename:join(Dir, "eqc.hrl"))
- end,
- erlang:put(is_quickcheck_avail, IsAvail),
- ?DEBUG("Quickcheck availability: ~p\n", [IsAvail]),
+ IsAvail = case code:lib_dir(Mod, include) of
+ {error, bad_name} ->
+ false;
+ Dir ->
+ filelib:is_regular(filename:join(Dir, Hrl))
+ end,
+ erlang:put(DictKey, IsAvail),
+ ?DEBUG("~s availability: ~p\n", [Name, IsAvail]),
IsAvail;
IsAvail ->
IsAvail
end.
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).
perform_cover(false, _Config, _BeamFiles, _SrcModules) ->
@@ -227,7 +239,8 @@ cover_analyze(Config, Modules, SrcModules) ->
%% Write coverage details for each file
lists:foreach(fun({M, _, _}) ->
- {ok, _} = cover:analyze_to_file(M, cover_file(M), [html])
+ {ok, _} = cover:analyze_to_file(M, cover_file(M),
+ [html])
end, Coverage),
Index = filename:join([rebar_utils:get_cwd(), ?EUNIT_DIR, "index.html"]),
@@ -260,7 +273,12 @@ cover_init(true, BeamFiles) ->
%% It's not an error for cover compilation to fail partially,
%% but we do want to warn about them
- _ = [?CONSOLE("Cover compilation warning for ~p: ~p", [Beam, Desc]) || {Beam, {error, Desc}} <- Compiled],
+ PrintWarning =
+ fun(Beam, Desc) ->
+ ?CONSOLE("Cover compilation warning for ~p: ~p",
+ [Beam, Desc])
+ end,
+ _ = [PrintWarning(Beam, Desc) || {Beam, {error, Desc}} <- Compiled],
ok
end;
cover_init(Config, BeamFiles) ->
@@ -287,18 +305,19 @@ is_eunitized(Mod) ->
has_eunit_test_fun(Mod) ->
[F || {exports, Funs} <- Mod:module_info(),
- {F, 0} <- Funs, F =:= test] =/= [].
+ {F, 0} <- Funs, F =:= test] =/= [].
has_header(Mod, Header) ->
- Mod1 = case code:which(Mod) of
- cover_compiled ->
+ Mod1 = case code:which(Mod) of
+ cover_compiled ->
{file, File} = cover:is_compiled(Mod),
File;
non_existing -> Mod;
preloaded -> Mod;
L -> L
end,
- {ok, {_, [{abstract_code, {_, AC}}]}} = beam_lib:chunks(Mod1, [abstract_code]),
+ {ok, {_, [{abstract_code, {_, AC}}]}} = beam_lib:chunks(Mod1,
+ [abstract_code]),
[F || {attribute, 1, file, {F, 1}} <- AC,
string:str(F, Header) =/= 0] =/= [].
@@ -310,7 +329,7 @@ align_notcovered_count(Module, Covered, NotCovered, true) ->
cover_write_index(Coverage, SrcModules) ->
{ok, F} = file:open(filename:join([?EUNIT_DIR, "index.html"]), [write]),
ok = file:write(F, "<html><head><title>Coverage Summary</title></head>\n"),
- IsSrcCoverage = fun({Mod,_C,_N}) -> lists:member(Mod, SrcModules) end,
+ IsSrcCoverage = fun({Mod,_C,_N}) -> lists:member(Mod, SrcModules) end,
{SrcCoverage, TestCoverage} = lists:partition(IsSrcCoverage, Coverage),
cover_write_index_section(F, "Source", SrcCoverage),
cover_write_index_section(F, "Test", TestCoverage),
@@ -331,9 +350,13 @@ cover_write_index_section(F, SectionName, Coverage) ->
ok = file:write(F, ?FMT("<h3>Total: ~s</h3>\n", [TotalCoverage])),
ok = file:write(F, "<table><tr><th>Module</th><th>Coverage %</th></tr>\n"),
+ FmtLink =
+ fun(Module, Cov, NotCov) ->
+ ?FMT("<tr><td><a href='~s.COVER.html'>~s</a></td><td>~s</td>\n",
+ [Module, Module, percentage(Cov, NotCov)])
+ end,
lists:foreach(fun({Module, Cov, NotCov}) ->
- ok = file:write(F, ?FMT("<tr><td><a href='~s.COVER.html'>~s</a></td><td>~s</td>\n",
- [Module, Module, percentage(Cov, NotCov)]))
+ ok = file:write(F, FmtLink(Module, Cov, NotCov))
end, Coverage),
ok = file:write(F, "</table>\n").
@@ -345,13 +368,13 @@ cover_print_coverage(Coverage) ->
%% Determine the longest module name for right-padding
Width = lists:foldl(fun({Mod, _, _}, Acc) ->
- case length(atom_to_list(Mod)) of
- N when N > Acc ->
- N;
- _ ->
- Acc
- end
- end, 0, Coverage) * -1,
+ case length(atom_to_list(Mod)) of
+ N when N > Acc ->
+ N;
+ _ ->
+ Acc
+ end
+ end, 0, Coverage) * -1,
%% Print the output the console
?CONSOLE("~nCode Coverage:~n", []),