aboutsummaryrefslogtreecommitdiffstats
path: root/lib/eunit
diff options
context:
space:
mode:
Diffstat (limited to 'lib/eunit')
-rw-r--r--lib/eunit/doc/src/notes.xml40
-rw-r--r--lib/eunit/src/eunit_surefire.erl56
-rw-r--r--lib/eunit/vsn.mk2
3 files changed, 78 insertions, 20 deletions
diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml
index a9960153e5..a02d76c5b9 100644
--- a/lib/eunit/doc/src/notes.xml
+++ b/lib/eunit/doc/src/notes.xml
@@ -32,6 +32,46 @@
</header>
<p>This document describes the changes made to the EUnit application.</p>
+<section><title>Eunit 2.1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Increase depth of error messages in Eunit Surefire
+ reports</p>
+ <p>
+ Currently, error messages in Eunit Surefire reports are
+ shortened just like when written to a terminal. However,
+ the space limitations that constrain terminal output do
+ not apply here, so it's more useful to include more of
+ the error message. The new depth of 100 should be enough
+ for most cases, while protecting against runaway errors.
+ (Thanks to Magnus Henoch)</p>
+ <p>
+ Own Id: OTP-9220</p>
+ </item>
+ <item>
+ <p>
+ Don't let eunit_surefire report back to eunit when
+ stopping</p>
+ <p>
+ When eunit is terminating, a stop message is sent to all
+ listeners and eunit then waits for *one* result message
+ but previously both eunit_tty and eunit_surefire sent a
+ response on error. Don't send a result message from
+ eunit_surefire; let eunit_tty take care of all result
+ reporting, both positive and negative to avoid race
+ conditions and inconsistencies. (Thanks to Klas
+ Johansson)</p>
+ <p>
+ Own Id: OTP-9269</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Eunit 2.1.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/eunit/src/eunit_surefire.erl b/lib/eunit/src/eunit_surefire.erl
index dfb08c90b2..25b5cde09c 100644
--- a/lib/eunit/src/eunit_surefire.erl
+++ b/lib/eunit/src/eunit_surefire.erl
@@ -64,6 +64,7 @@
}).
-record(testsuite,
{
+ id = 0 :: integer(),
name = <<>> :: binary(),
time = 0 :: integer(),
output = <<>> :: binary(),
@@ -76,7 +77,7 @@
-record(state, {verbose = false,
indent = 0,
xmldir = ".",
- testsuite = #testsuite{}
+ testsuites = [] :: [#testsuite{}]
}).
start() ->
@@ -89,55 +90,60 @@ init(Options) ->
XMLDir = proplists:get_value(dir, Options, ?XMLDIR),
St = #state{verbose = proplists:get_bool(verbose, Options),
xmldir = XMLDir,
- testsuite = #testsuite{}},
+ testsuites = []},
receive
{start, _Reference} ->
St
end.
terminate({ok, _Data}, St) ->
- TestSuite = St#state.testsuite,
+ TestSuites = St#state.testsuites,
XmlDir = St#state.xmldir,
- write_report(TestSuite, XmlDir),
+ write_reports(TestSuites, XmlDir),
ok;
terminate({error, _Reason}, _St) ->
%% Don't report any errors here, since eunit_tty takes care of that.
%% Just terminate.
ok.
-handle_begin(group, Data, St) ->
+handle_begin(Kind, Data, St) when Kind == group; Kind == test ->
+ %% Run this code both for groups and tests; test is a bit
+ %% surprising: This is a workaround for the fact that we don't get
+ %% a group (handle_begin(group, ...) for testsuites (modules)
+ %% which only have one test case. In that case we get a test case
+ %% with an id comprised of just one integer - the group id.
NewId = proplists:get_value(id, Data),
case NewId of
[] ->
St;
- [_GroupId] ->
+ [GroupId] ->
Desc = proplists:get_value(desc, Data),
- TestSuite = St#state.testsuite,
- NewTestSuite = TestSuite#testsuite{name = Desc},
- St#state{testsuite=NewTestSuite};
+ TestSuite = #testsuite{id = GroupId, name = Desc},
+ St#state{testsuites=store_suite(TestSuite, St#state.testsuites)};
%% Surefire format is not hierarchic: Ignore subgroups:
_ ->
St
- end;
-handle_begin(test, _Data, St) ->
- St.
+ end.
handle_end(group, Data, St) ->
%% Retrieve existing test suite:
case proplists:get_value(id, Data) of
[] ->
St;
- [_GroupId|_] ->
- TestSuite = St#state.testsuite,
+ [GroupId|_] ->
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Update TestSuite data:
Time = proplists:get_value(time, Data),
Output = proplists:get_value(output, Data),
NewTestSuite = TestSuite#testsuite{ time = Time, output = Output },
- St#state{testsuite=NewTestSuite}
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}
end;
handle_end(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -149,7 +155,7 @@ handle_end(test, Data, St) ->
TestCase = #testcase{name = Name, description = Desc,
time = Time,output = Output},
NewTestSuite = add_testcase_to_testsuite(Result, TestCase, TestSuite),
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
%% Cancel group does not give information on the individual cancelled test case
%% We ignore this event
@@ -157,7 +163,9 @@ handle_cancel(group, _Data, St) ->
St;
handle_cancel(test, Data, St) ->
%% Retrieve existing test suite:
- TestSuite = St#state.testsuite,
+ [GroupId|_] = proplists:get_value(id, Data),
+ TestSuites = St#state.testsuites,
+ TestSuite = lookup_suite_by_group_id(GroupId, TestSuites),
%% Create test case:
Name = format_name(proplists:get_value(source, Data),
@@ -171,7 +179,7 @@ handle_cancel(test, Data, St) ->
NewTestSuite = TestSuite#testsuite{
skipped = TestSuite#testsuite.skipped+1,
testcases=[TestCase|TestSuite#testsuite.testcases] },
- St#state{testsuite=NewTestSuite}.
+ St#state{testsuites=store_suite(NewTestSuite, TestSuites)}.
format_name({Module, Function, Arity}, Line) ->
lists:flatten([atom_to_list(Module), ":", atom_to_list(Function), "/",
@@ -183,6 +191,12 @@ format_desc(Desc) when is_binary(Desc) ->
format_desc(Desc) when is_list(Desc) ->
Desc.
+lookup_suite_by_group_id(GroupId, TestSuites) ->
+ #testsuite{} = lists:keyfind(GroupId, #testsuite.id, TestSuites).
+
+store_suite(#testsuite{id=GroupId} = TestSuite, TestSuites) ->
+ lists:keystore(GroupId, #testsuite.id, TestSuites, TestSuite).
+
%% Add testcase to testsuite depending on the result of the test.
add_testcase_to_testsuite(ok, TestCaseTmp, TestSuite) ->
TestCase = TestCaseTmp#testcase{ result = ok },
@@ -214,6 +228,10 @@ add_testcase_to_testsuite({error, Exception}, TestCaseTmp, TestSuite) ->
%% Write a report to the XML directory.
%% This function opens the report file, calls write_report_to/2 and closes the file.
%% ----------------------------------------------------------------------------
+write_reports(TestSuites, XmlDir) ->
+ lists:foreach(fun(TestSuite) -> write_report(TestSuite, XmlDir) end,
+ TestSuites).
+
write_report(#testsuite{name = Name} = TestSuite, XmlDir) ->
Filename = filename:join(XmlDir, lists:flatten(["TEST-", escape_suitename(Name)], ".xml")),
case file:open(Filename, [write, raw]) of
diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk
index e1965630e3..d7edd7977b 100644
--- a/lib/eunit/vsn.mk
+++ b/lib/eunit/vsn.mk
@@ -1 +1 @@
-EUNIT_VSN = 2.1.6
+EUNIT_VSN = 2.1.7