summaryrefslogtreecommitdiff
path: root/src/cth_fail_fast.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cth_fail_fast.erl')
-rw-r--r--src/cth_fail_fast.erl118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/cth_fail_fast.erl b/src/cth_fail_fast.erl
new file mode 100644
index 0000000..13b3557
--- /dev/null
+++ b/src/cth_fail_fast.erl
@@ -0,0 +1,118 @@
+-module(cth_fail_fast).
+
+%% Callbacks
+-export([id/1]).
+-export([init/2]).
+
+-export([pre_init_per_suite/3]).
+-export([post_init_per_suite/4]).
+-export([pre_end_per_suite/3]).
+-export([post_end_per_suite/4]).
+
+-export([pre_init_per_group/3]).
+-export([post_init_per_group/4]).
+-export([pre_end_per_group/3]).
+-export([post_end_per_group/4]).
+
+-export([pre_init_per_testcase/3]).
+-export([post_end_per_testcase/4]).
+
+-export([on_tc_fail/3]).
+-export([on_tc_skip/3, on_tc_skip/4]).
+
+-export([terminate/1]).
+
+%% We work by setting an 'abort' variable on each test case that fails
+%% and then triggering the failure before starting the next test. This
+%% ensures that all other hooks have run for the same event, and
+%% simplifies error reporting.
+-record(state, {abort=false}).
+
+%% @doc Return a unique id for this CTH.
+id(_Opts) ->
+ {?MODULE, make_ref()}.
+
+%% @doc Always called before any other callback function. Use this to initiate
+%% any common state.
+init(_Id, _Opts) ->
+ {ok, #state{}}.
+
+%% @doc Called before init_per_suite is called.
+pre_init_per_suite(_Suite,_Config,#state{abort=true}) ->
+ abort();
+pre_init_per_suite(_Suite,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after init_per_suite.
+post_init_per_suite(_Suite,_Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called before end_per_suite.
+pre_end_per_suite(_Suite,_Config,#state{abort=true}) ->
+ abort();
+pre_end_per_suite(_Suite,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after end_per_suite.
+post_end_per_suite(_Suite,_Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called before each init_per_group.
+pre_init_per_group(_Group,_Config,#state{abort=true}) ->
+ abort();
+pre_init_per_group(_Group,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each init_per_group.
+post_init_per_group(_Group,_Config,Return, State) ->
+ {Return, State}.
+
+%% @doc Called after each end_per_group.
+pre_end_per_group(_Group,_Config,#state{abort=true}) ->
+ abort();
+pre_end_per_group(_Group,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each end_per_group.
+post_end_per_group(_Group,_Config,Return, State) ->
+ {Return, State}.
+
+%% @doc Called before each test case.
+pre_init_per_testcase(_TC,_Config,#state{abort=true}) ->
+ abort();
+pre_init_per_testcase(_TC,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each test case.
+post_end_per_testcase(_TC,_Config,ok,State) ->
+ {ok, State};
+post_end_per_testcase(_TC,_Config,Error,State) ->
+ {Error, State#state{abort=true}}.
+
+%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% post_end_per_group and post_end_per_testcase if the suite, group or test case failed.
+on_tc_fail(_TC, _Reason, State) ->
+ State.
+
+%% @doc Called when a test case is skipped by either user action
+%% or due to an init function failing. (>= 19.3)
+on_tc_skip(_Suite, _TC, {tc_auto_skip, _}, State) ->
+ State#state{abort=true};
+on_tc_skip(_Suite, _TC, _Reason, State) ->
+ State.
+
+%% @doc Called when a test case is skipped by either user action
+%% or due to an init function failing. (Pre-19.3)
+on_tc_skip(_TC, {tc_auto_skip, _}, State) ->
+ State#state{abort=true};
+on_tc_skip(_TC, _Reason, State) ->
+ State.
+
+%% @doc Called when the scope of the CTH is done
+terminate(#state{}) ->
+ ok.
+
+%%% Helpers
+abort() ->
+ io:format(user, "Detected test failure. Aborting~n", []),
+ halt(1).