aboutsummaryrefslogtreecommitdiff
path: root/test/eunit_progress.erl
diff options
context:
space:
mode:
authorinoas <mail@inoas.com>2023-01-22 17:37:02 +0100
committerLouis Pilfold <louis@lpil.uk>2023-01-23 10:04:21 +0000
commit870e9d4f2b55887c965991ac0661b30e5a161251 (patch)
treed16d825069e6cf8ab7622b6382c5f97bd70b7b99 /test/eunit_progress.erl
parente6d553af85c42681fe948f2fad5a326cdc0701ce (diff)
downloadgleam_stdlib-870e9d4f2b55887c965991ac0661b30e5a161251.tar.gz
gleam_stdlib-870e9d4f2b55887c965991ac0661b30e5a161251.zip
backport eunit_progress from gleeunit
Diffstat (limited to 'test/eunit_progress.erl')
-rw-r--r--test/eunit_progress.erl133
1 files changed, 75 insertions, 58 deletions
diff --git a/test/eunit_progress.erl b/test/eunit_progress.erl
index 153130f..77939fd 100644
--- a/test/eunit_progress.erl
+++ b/test/eunit_progress.erl
@@ -1,31 +1,12 @@
-%% eunit_formatters https://github.com/seancribbs/eunit_formatters
-%% Changes made to the original code:
-%% - Embedded binomial_heap.erl file contents into current file.
-%% - ignore warnings for heap implementation to keep complete implementation.
-%% - removed "namespaced_dicts" dependant preprocessor directive,
-%% as it does not apply for our project, we just assume OTP version >= 17.
-%% This is because the previous verison uses rebar, and we won't do that.
-
-%% Copyright 2014 Sean Cribbs
-%%
-%% Licensed under the Apache License, Version 2.0 (the "License");
-%% you may not use this file except in compliance with the License.
-%% You may obtain a copy of the License at
-%%
-%% http://www.apache.org/licenses/LICENSE-2.0
-%%
-%% Unless required by applicable law or agreed to in writing, software
-%% distributed under the License is distributed on an "AS IS" BASIS,
-%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-%% See the License for the specific language governing permissions and
-%% limitations under the License.
+%% Except for its module name, this file is verbatim copy of gleeunit 0.10.0's <https://raw.githubusercontent.com/lpil/gleeunit/main/src/gleeunit_progress.erl>
+%% A formatter adapted from Sean Cribb's https://github.com/seancribbs/eunit_formatters
%% @doc A listener/reporter for eunit that prints '.' for each
%% success, 'F' for each failure, and 'E' for each error. It can also
%% optionally summarize the failures at the end.
-compile({nowarn_unused_function, [insert/2, to_list/1, to_list/2, size/1]}).
--module(eunit_progress).
+-module(eunit_progress). % Renamed from gleeunit_progress
-behaviour(eunit_listener).
-define(NOTEST, true).
-include_lib("eunit/include/eunit.hrl").
@@ -292,12 +273,53 @@ print_failure_fun(#state{status=Status}=State) ->
Count + 1
end.
+print_gleam_location(#{function := Function, line := Line, module := Module }, State) ->
+ X = indent(5, "location: ~s.~s:~p~n", [Module, Function, Line]),
+ print_colored(X, ?CYAN, State);
+print_gleam_location(_, _) ->
+ ok.
+
+inspect(X) ->
+ gleam@string:inspect(X).
+
+print_gleam_failure_reason(
+ #{gleam_error := assert, message := Message, value := Value},
+ State
+) ->
+ print_colored(indent(5, "~s~n", [Message]), ?RED, State),
+ print_colored(indent(5, " value: ", []), ?RED, State),
+ print_colored(indent(0, "~s~n", [inspect(Value)]), ?RESET, State);
+print_gleam_failure_reason(
+ #{gleam_error := todo, message := Message},
+ State
+) ->
+ print_colored(indent(5, "todo expression run~n", []), ?RED, State),
+ print_colored(indent(5, " message: ", []), ?RED, State),
+ print_colored(indent(0, "~s~n", [Message]), ?RESET, State);
+print_gleam_failure_reason(Error, State) ->
+ print_colored(indent(5, "~p~n", [Error]), ?RED, State).
+
+% New Gleeunit specific formatters
+print_failure_reason(
+ {error, {error, #{gleam_error := _} = Error, Stack}}, Output, State
+) when is_list(Stack) ->
+ print_gleam_failure_reason(Error, State),
+ print_gleam_location(Error, State),
+ print_stack(Stack, State),
+ print_failure_output(5, Output, State);
+print_failure_reason({error, {error, {case_clause, Value}, Stack}}, Output, State) when is_list(Stack) ->
+ print_colored(indent(5, "No case clause matched~n", []), ?RED, State),
+ print_colored(indent(5, "Value: ", []), ?CYAN, State),
+ print_colored(indent(0, "~s~n", [inspect(Value)]), ?RESET, State),
+ print_stack(Stack, State),
+ print_failure_output(5, Output, State);
+% From the original Erlang version
print_failure_reason({skipped, Reason}, _Output, State) ->
print_colored(io_lib:format(" ~ts~n", [format_pending_reason(Reason)]),
?RED, State);
-print_failure_reason({error, {_Class, Term, Stack}}, Output, State) when
+print_failure_reason({error, {_Class, Term, _}}, Output, State) when
is_tuple(Term), tuple_size(Term) == 2, is_list(element(2, Term)) ->
- print_assertion_failure(Term, Stack, Output, State),
+ print_assertion_failure(Term, State),
print_failure_output(5, Output, State);
print_failure_reason({error, {error, Error, Stack}}, Output, State) when is_list(Stack) ->
print_colored(indent(5, "Failure: ~p~n", [Error]), ?RED, State),
@@ -307,15 +329,19 @@ print_failure_reason({error, Reason}, Output, State) ->
print_colored(indent(5, "Failure: ~p~n", [Reason]), ?RED, State),
print_failure_output(5, Output, State).
+gleam_format_module_name(Module) ->
+ string:replace(atom_to_list(Module), "@", "/", all).
+
print_stack(Stack, State) ->
- print_colored(indent(5, "Stacktrace:~n", []), ?CYAN, State),
+ print_colored(indent(5, "stacktrace:~n", []), ?CYAN, State),
print_stackframes(Stack, State).
print_stackframes([{eunit_test, _, _, _} | Stack], State) ->
print_stackframes(Stack, State);
print_stackframes([{eunit_proc, _, _, _} | Stack], State) ->
print_stackframes(Stack, State);
print_stackframes([{Module, Function, _Arity, _Location} | Stack], State) ->
- print_colored(indent(7, "~p.~p~n", [Module, Function]), ?CYAN, State),
+ GleamModule = gleam_format_module_name(Module),
+ print_colored(indent(7, "~s.~p~n", [GleamModule, Function]), ?CYAN, State),
print_stackframes(Stack, State);
print_stackframes([], _State) ->
ok.
@@ -324,19 +350,11 @@ print_stackframes([], _State) ->
print_failure_output(_, <<>>, _) -> ok;
print_failure_output(_, undefined, _) -> ok;
print_failure_output(Indent, Output, State) ->
- print_colored(indent(Indent, "Output: ~ts", [Output]), ?CYAN, State).
+ print_colored(indent(Indent, "output: ~ts", [Output]), ?CYAN, State).
-print_assertion_failure({Type, Props}, Stack, Output, State) ->
+print_assertion_failure({Type, Props}, State) ->
FailureDesc = format_assertion_failure(Type, Props, 5),
- {M,F,A,Loc} = lists:last(Stack),
- LocationText = io_lib:format(" %% ~ts:~p:in `~ts`", [proplists:get_value(file, Loc),
- proplists:get_value(line, Loc),
- format_function_name(M,F,A)]),
print_colored(FailureDesc, ?RED, State),
- io:nl(),
- print_colored(LocationText, ?CYAN, State),
- io:nl(),
- print_failure_output(5, Output, State),
io:nl().
print_pending(#state{skips=[]}) ->
@@ -432,8 +450,9 @@ print_colored(Text, _Color, #state{colored=false}) ->
%%------------------------------------------
%% Generic data formatters
%%------------------------------------------
-format_function_name(M, F, A) ->
- io_lib:format("~ts:~ts/~p", [M, F, A]).
+format_function_name(M, F) ->
+ M1 = gleam_format_module_name(M),
+ io_lib:format("~ts.~ts", [M1, F]).
format_optional_result(0, _) ->
[];
@@ -441,7 +460,7 @@ format_optional_result(Count, Text) ->
io_lib:format(", ~p ~ts", [Count, Text]).
format_test_identifier(Data) ->
- {Mod, Fun, Arity} = proplists:get_value(source, Data),
+ {Mod, Fun, _} = proplists:get_value(source, Data),
Line = case proplists:get_value(line, Data) of
0 -> "";
L -> io_lib:format(":~p", [L])
@@ -450,7 +469,7 @@ format_test_identifier(Data) ->
undefined -> "";
DescText -> io_lib:format(": ~ts", [DescText])
end,
- io_lib:format("~ts~ts~ts", [format_function_name(Mod, Fun, Arity), Line, Desc]).
+ io_lib:format("~ts~ts~ts", [format_function_name(Mod, Fun), Line, Desc]).
format_time(undefined) ->
"? seconds";
@@ -458,9 +477,11 @@ format_time(Time) ->
io_lib:format("~.3f seconds", [Time / 1000]).
format_pending_reason({module_not_found, M}) ->
- io_lib:format("Module '~ts' missing", [M]);
-format_pending_reason({no_such_function, {M,F,A}}) ->
- io_lib:format("Function ~ts undefined", [format_function_name(M,F,A)]);
+ M1 = gleam_format_module_name(M),
+ io_lib:format("Module '~ts' missing", [M1]);
+format_pending_reason({no_such_function, {M,F,_}}) ->
+ M1 = gleam_format_module_name(M),
+ io_lib:format("Function ~ts undefined", [format_function_name(M1,F)]);
format_pending_reason({exit, Reason}) ->
io_lib:format("Related process exited with reason: ~p", [Reason]);
format_pending_reason(Reason) ->
@@ -485,8 +506,8 @@ format_assertion_failure(Type, Props, I) when Type =:= assertion_failed
end];
HasHamcrestProps ->
[indent(I, "Failure: ?assertThat(~p)~n", [proplists:get_value(matcher, Props)]),
- indent(I, " expected: ~p~n", [proplists:get_value(expected, Props)]),
- indent(I, " got: ~p", [proplists:get_value(actual, Props)])];
+ indent(I, " expected: ~p~n", [inspect(proplists:get_value(expected, Props))]),
+ indent(I, " got: ~p", [inspect(proplists:get_value(actual, Props))])];
true ->
[indent(I, "Failure: unknown assert: ~p", [Props])]
end;
@@ -511,22 +532,18 @@ format_assertion_failure(Type, Props, I) when Type =:= assertNotMatch_failed
format_assertion_failure(Type, Props, I) when Type =:= assertEqual_failed
; Type =:= assertEqual ->
- Expr = proplists:get_value(expression, Props),
- Expected = proplists:get_value(expected, Props),
- Value = proplists:get_value(value, Props),
- [indent(I, "Failure: ?assertEqual(~w, ~ts)~n", [Expected,
- Expr]),
- indent(I, " expected: ~p~n", [Expected]),
- indent(I, " got: ~p", [Value])];
+ Expected = inspect(proplists:get_value(expected, Props)),
+ Value = inspect(proplists:get_value(value, Props)),
+ [indent(I, "Values were not equal~n", []),
+ indent(I, "expected: ~s~n", [Expected]),
+ indent(I, " got: ~s", [Value])];
format_assertion_failure(Type, Props, I) when Type =:= assertNotEqual_failed
; Type =:= assertNotEqual ->
- Expr = proplists:get_value(expression, Props),
- Value = proplists:get_value(value, Props),
- [indent(I, "Failure: ?assertNotEqual(~p, ~ts)~n",
- [Value, Expr]),
- indent(I, " expected not: == ~p~n", [Value]),
- indent(I, " got: ~p", [Value])];
+ Value = inspect(proplists:get_value(value, Props)),
+ [indent(I, "Values were equal~n", []),
+ indent(I, "expected: not ~s~n,", [Value]),
+ indent(I, " got: ~s", [Value])];
format_assertion_failure(Type, Props, I) when Type =:= assertException_failed
; Type =:= assertException ->