summaryrefslogtreecommitdiff
path: root/lib/eunit
diff options
context:
space:
mode:
authorSergey Prokhorov <seriy.pr@gmail.com>2020-02-12 16:15:20 +0100
committerSergey Prokhorov <seriy.pr@gmail.com>2020-02-27 19:37:06 +0100
commit1916f4fe0659aa8da5d3a0739f367a229a14230d (patch)
tree8f6aa9a9709c2e9f832233df6dc8f03c928c7e30 /lib/eunit
parent8eefeda8d81996bfe8249017fa0be2595eb64cff (diff)
downloaderlang-1916f4fe0659aa8da5d3a0739f367a229a14230d.tar.gz
Add print_depth option to eunit:test
It can be set to change the max print depth of exceptions generated by eunit test suites. Current hardcoded limit of 20 can be considered too small in many cases.
Diffstat (limited to 'lib/eunit')
-rw-r--r--lib/eunit/src/eunit.erl2
-rw-r--r--lib/eunit/src/eunit_lib.erl44
-rw-r--r--lib/eunit/src/eunit_tty.erl53
3 files changed, 54 insertions, 45 deletions
diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl
index 1ace85ffde..0238885708 100644
--- a/lib/eunit/src/eunit.erl
+++ b/lib/eunit/src/eunit.erl
@@ -133,6 +133,8 @@ test(Tests) ->
%% <dl>
%% <dt>`verbose'</dt>
%% <dd>Displays more details about the running tests.</dd>
+%% <dt>`print_depth'</dt>
+%% <dd>Maximum depth to which terms are printed in case of error.</dd>
%% </dl>
%%
%% Options in the environment variable EUNIT are also included last in
diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl
index 771541354c..5b7d90ab0d 100644
--- a/lib/eunit/src/eunit_lib.erl
+++ b/lib/eunit/src/eunit_lib.erl
@@ -35,9 +35,10 @@
-export([dlist_next/1, uniq/1, fun_parent/1, is_string/1, command/1,
command/2, command/3, trie_new/0, trie_store/2, trie_match/2,
split_node/1, consult_file/1, list_dir/1, format_exit_term/1,
- format_exception/1, format_exception/2, format_error/1,
+ format_exception/1, format_exception/2, format_error/1, format_error/2,
is_not_test/1]).
+-define(DEFAULT_DEPTH, 20).
%% Type definitions for describing exceptions
%%
@@ -56,7 +57,7 @@
%% ---------------------------------------------------------------------
%% Formatting of error descriptors
format_exception(Exception) ->
- format_exception(Exception, 20).
+ format_exception(Exception, ?DEFAULT_DEPTH).
format_exception({Class,Term,Trace}, Depth)
when is_atom(Class), is_list(Trace) ->
@@ -159,38 +160,41 @@ is_op(erlang, F, A) ->
is_op(_M, _F, _A) ->
false.
-format_error({bad_test, Term}) ->
- error_msg("bad test descriptor", "~tP", [Term, 15]);
-format_error({bad_generator, {{M,F,A}, Term}}) ->
+format_error(Error) ->
+ format_error(Error, ?DEFAULT_DEPTH).
+
+format_error({bad_test, Term}, Depth) ->
+ error_msg("bad test descriptor", "~tP", [Term, Depth]);
+format_error({bad_generator, {{M,F,A}, Term}}, Depth) ->
error_msg(io_lib:format("result from generator ~w:~tw/~w is not a test",
[M,F,A]),
- "~tP", [Term, 15]);
-format_error({generator_failed, {{M,F,A}, Exception}}) ->
+ "~tP", [Term, Depth]);
+format_error({generator_failed, {{M,F,A}, Exception}}, Depth) ->
error_msg(io_lib:format("test generator ~w:~tw/~w failed",[M,F,A]),
- "~ts", [format_exception(Exception)]);
-format_error({no_such_function, {M,F,A}})
+ "~ts", [format_exception(Exception, Depth)]);
+format_error({no_such_function, {M,F,A}}, _)
when is_atom(M), is_atom(F), is_integer(A) ->
error_msg(io_lib:format("no such function: ~w:~tw/~w", [M,F,A]),
"", []);
-format_error({module_not_found, M}) ->
+format_error({module_not_found, M}, _) ->
error_msg("test module not found", "~tp", [M]);
-format_error({application_not_found, A}) when is_atom(A) ->
+format_error({application_not_found, A}, _) when is_atom(A) ->
error_msg("application not found", "~w", [A]);
-format_error({file_read_error, {_R, Msg, F}}) ->
+format_error({file_read_error, {_R, Msg, F}}, _) ->
error_msg("error reading file", "~ts: ~ts", [Msg, F]);
-format_error({setup_failed, Exception}) ->
+format_error({setup_failed, Exception}, Depth) ->
error_msg("context setup failed", "~ts",
- [format_exception(Exception)]);
-format_error({cleanup_failed, Exception}) ->
+ [format_exception(Exception, Depth)]);
+format_error({cleanup_failed, Exception}, Depth) ->
error_msg("context cleanup failed", "~ts",
- [format_exception(Exception)]);
-format_error({{bad_instantiator, {{M,F,A}, Term}}, _DummyException}) ->
+ [format_exception(Exception, Depth)]);
+format_error({{bad_instantiator, {{M,F,A}, Term}}, _DummyException}, Depth) ->
error_msg(io_lib:format("result from instantiator ~w:~tw/~w is not a test",
[M,F,A]),
- "~tP", [Term, 15]);
-format_error({instantiation_failed, Exception}) ->
+ "~tP", [Term, Depth]);
+format_error({instantiation_failed, Exception}, Depth) ->
error_msg("instantiation of subtests failed", "~ts",
- [format_exception(Exception)]).
+ [format_exception(Exception, Depth)]).
error_msg(Title, Fmt, Args) ->
Msg = io_lib:format("**"++Fmt, Args), % gets indentation right
diff --git a/lib/eunit/src/eunit_tty.erl b/lib/eunit/src/eunit_tty.erl
index 2c9a598628..ca6aa3b525 100644
--- a/lib/eunit/src/eunit_tty.erl
+++ b/lib/eunit/src/eunit_tty.erl
@@ -38,7 +38,8 @@
terminate/2]).
-record(state, {verbose = false,
- indent = 0
+ indent = 0,
+ print_depth = 20
}).
start() ->
@@ -48,7 +49,9 @@ start(Options) ->
eunit_listener:start(?MODULE, Options).
init(Options) ->
- St = #state{verbose = proplists:get_bool(verbose, Options)},
+ PrintDepth = proplists:get_value(print_depth, Options, 20),
+ St = #state{verbose = proplists:get_bool(verbose, Options),
+ print_depth = PrintDepth},
put(no_tty, proplists:get_bool(no_tty, Options)),
receive
{start, _Reference} ->
@@ -89,8 +92,8 @@ terminate({ok, Data}, St) ->
end,
sync_end(error)
end;
-terminate({error, Reason}, _St) ->
- fwrite("Internal error: ~tP.\n", [Reason, 25]),
+terminate({error, Reason}, #state{print_depth = Depth}) ->
+ fwrite("Internal error: ~tP.\n", [Reason, Depth]),
sync_end(error).
sync_end(Result) ->
@@ -147,7 +150,7 @@ handle_end(test, Data, St) ->
if St#state.verbose -> ok;
true -> print_test_begin(St#state.indent, Data)
end,
- print_test_error(Status, Data),
+ print_test_error(Status, Data, St),
St
end.
@@ -161,10 +164,10 @@ handle_cancel(group, Data, St) ->
Reason ->
Desc = proplists:get_value(desc, Data),
if Desc =/= "", Desc =/= undefined, St#state.verbose ->
- print_group_cancel(I, Reason);
+ print_group_cancel(I, Reason, St);
true ->
print_group_start(I, Desc),
- print_group_cancel(I, Reason)
+ print_group_cancel(I, Reason, St)
end,
St#state{indent = I - 1}
end;
@@ -173,7 +176,7 @@ handle_cancel(test, Data, St) ->
if St#state.verbose -> ok;
true -> print_test_begin(St#state.indent, Data)
end,
- print_test_cancel(proplists:get_value(reason, Data)),
+ print_test_cancel(proplists:get_value(reason, Data), St),
St.
@@ -218,9 +221,9 @@ print_test_end(Data) ->
end,
fwrite("~tsok\n", [T]).
-print_test_error({error, Exception}, Data) ->
+print_test_error({error, Exception}, Data, #state{print_depth = Depth}) ->
Output = proplists:get_value(output, Data),
- fwrite("*failed*\n~ts", [eunit_lib:format_exception(Exception)]),
+ fwrite("*failed*\n~ts", [eunit_lib:format_exception(Exception, Depth)]),
case Output of
<<>> ->
fwrite("\n\n");
@@ -229,7 +232,7 @@ print_test_error({error, Exception}, Data) ->
_ ->
fwrite(" output:<<\"~ts\">>\n\n", [Output])
end;
-print_test_error({skipped, Reason}, _) ->
+print_test_error({skipped, Reason}, _, St) ->
fwrite("*did not run*\n::~ts\n", [format_skipped(Reason)]).
format_skipped({module_not_found, M}) ->
@@ -237,29 +240,29 @@ format_skipped({module_not_found, M}) ->
format_skipped({no_such_function, {M,F,A}}) ->
io_lib:fwrite("no such function: ~w:~tw/~w", [M,F,A]).
-print_test_cancel(Reason) ->
- fwrite(format_cancel(Reason)).
+print_test_cancel(Reason, #state{print_depth = Depth}) ->
+ fwrite(format_cancel(Reason, Depth)).
-print_group_cancel(_I, {blame, _}) ->
+print_group_cancel(_I, {blame, _}, _) ->
ok;
-print_group_cancel(I, Reason) ->
+print_group_cancel(I, Reason, #state{print_depth = Depth}) ->
indent(I),
- fwrite(format_cancel(Reason)).
+ fwrite(format_cancel(Reason, Depth)).
-format_cancel(undefined) ->
+format_cancel(undefined, _) ->
"*skipped*\n";
-format_cancel(timeout) ->
+format_cancel(timeout, _) ->
"*timed out*\n";
-format_cancel({startup, Reason}) ->
+format_cancel({startup, Reason}, Depth) ->
io_lib:fwrite("*could not start test process*\n::~tP\n\n",
- [Reason, 15]);
-format_cancel({blame, _SubId}) ->
+ [Reason, Depth]);
+format_cancel({blame, _SubId}, _) ->
"*cancelled because of subtask*\n";
-format_cancel({exit, Reason}) ->
+format_cancel({exit, Reason}, Depth) ->
io_lib:fwrite("*unexpected termination of test process*\n::~tP\n\n",
- [Reason, 15]);
-format_cancel({abort, Reason}) ->
- eunit_lib:format_error(Reason).
+ [Reason, Depth]);
+format_cancel({abort, Reason}, Depth) ->
+ eunit_lib:format_error(Reason, Depth).
fwrite(String) ->
fwrite(String, []).