summaryrefslogtreecommitdiff
path: root/src/rebar_prv_common_test.erl
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2018-12-17 12:17:47 -0500
committerFred Hebert <mononcqc@ferd.ca>2018-12-17 12:17:47 -0500
commit76d8803a5dd0940054b5a22b16cbe43b6c677c9e (patch)
tree0ffa227ad2da75320e563c4770436c74a980e8ad /src/rebar_prv_common_test.erl
parent8e28561d4e14ea85d42d17ab5a0f17f5f1c696d2 (diff)
Add a --fail_fast switch to common test
This switch aborts the rebar3 run after the first test failure is reported. Since Common Test does not support this feature and it can be useful for interactive development (a demand from one of the teams I work with), I decided to add the feature as an experimental CT hook. The hook notices any test failure, and forcefully aborts the current script execution, but only during the initialization phase of the next test; this ensure that all other hooks for a post-test failure have the time to do things right. The CT logs _will_ be interupted, and hooks of all kinds may also suffer. Since this might be a bit tricky to support internally, I will be fine with a review that results in "no, Fred. Please test this in a project plugin first" or if I get told to use profiles to mature the feature (i.e. `rebar3 as failfast ct ...`) with a custom hook declaration.
Diffstat (limited to 'src/rebar_prv_common_test.erl')
-rw-r--r--src/rebar_prv_common_test.erl26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl
index 3d3bd8a..c31c060 100644
--- a/src/rebar_prv_common_test.erl
+++ b/src/rebar_prv_common_test.erl
@@ -171,6 +171,9 @@ transform_opts([{cover, _}|Rest], Acc) ->
%% drop verbose from opts, ct doesn't care about it
transform_opts([{verbose, _}|Rest], Acc) ->
transform_opts(Rest, Acc);
+%% drop fail_fast from opts, ct doesn't care about it
+transform_opts([{fail_fast, _}|Rest], Acc) ->
+ transform_opts(Rest, Acc);
%% getopt should handle anything else
transform_opts([Opt|Rest], Acc) ->
transform_opts(Rest, [Opt|Acc]).
@@ -224,15 +227,21 @@ ensure_opts([V|Rest], Acc) ->
ensure_opts(Rest, [V|Acc]).
add_hooks(Opts, State) ->
+ FailFast = case fails_fast(State) of
+ true -> [cth_fail_fast];
+ false -> []
+ end,
case {readable(State), lists:keyfind(ct_hooks, 1, Opts)} of
{false, _} ->
Opts;
{Other, false} ->
- [{ct_hooks, [cth_readable_failonly, readable_shell_type(Other), cth_retry]} | Opts];
+ [{ct_hooks, [cth_readable_failonly, readable_shell_type(Other),
+ cth_retry] ++ FailFast} | Opts];
{Other, {ct_hooks, Hooks}} ->
%% Make sure hooks are there once only.
- ReadableHooks = [cth_readable_failonly, readable_shell_type(Other), cth_retry],
- AllReadableHooks = [cth_readable_failonly, cth_retry,
+ ReadableHooks = [cth_readable_failonly, readable_shell_type(Other),
+ cth_retry] ++ FailFast,
+ AllReadableHooks = [cth_readable_failonly, cth_retry, cth_fail_fast,
cth_readable_shell, cth_readable_compact_shell],
NewHooks = (Hooks -- AllReadableHooks) ++ ReadableHooks,
lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks})
@@ -445,6 +454,10 @@ readable(State) ->
undefined -> rebar_state:get(State, ct_readable, compact)
end.
+fails_fast(State) ->
+ {RawOpts, _} = rebar_state:command_parsed_args(State),
+ proplists:get_value(fail_fast, RawOpts) == true.
+
test_dirs(State, Apps, Opts) ->
case proplists:get_value(spec, Opts) of
undefined ->
@@ -773,7 +786,8 @@ ct_opts(_State) ->
{setcookie, undefined, "setcookie", atom, help(setcookie)},
{sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list
{compile_only, undefined, "compile_only", boolean, help(compile_only)},
- {retry, undefined, "retry", boolean, help(retry)}
+ {retry, undefined, "retry", boolean, help(retry)},
+ {fail_fast, undefined, "fail_fast", {boolean, false}, help(fail_fast)}
].
help(compile_only) ->
@@ -846,5 +860,9 @@ help(setcookie) ->
"Sets the cookie if the node is distributed";
help(retry) ->
"Experimental feature. If any specification for previously failing test is found, runs them.";
+help(fail_fast) ->
+ "Experimental feature. If any test fails, the run is aborted. Since common test does not "
+ "support this natively, we abort the rebar3 run on a failure. This May break CT's disk logging and "
+ "other rebar3 features.";
help(_) ->
"".