Getting test results from Eunit in Erlang

2019-02-14 14:47发布

问题:

I am working with Erlang and EUnit to do unit tests, and I would like to write a test runner to automate the running of my unit tests. The problem is that eunit:test/1 seems to only return "error" or "ok" and not a list of tests and what they returned in terms of what passed or failed.

So is there a way to run tests and get back some form of a data structure of what tests ran and their pass/fail state?

回答1:

If you are using rebar you don't have to implement your own runner. You can simply run:

rebar eunit

Rebar will compile and run all tests in the test directory (as well as eunit tests inside your modules). Furthermore, rebar allows you set the same options in the rebar.config as in the shell:

{eunit_opts, [verbose, {report,{eunit_surefire,[{dir,"."}]}}]}.

You can use these options also in the shell:

> eunit:test([foo], [verbose, {report,{eunit_surefire,[{dir,"."}]}}]).

See also documentation for verbose option and structured report.

An alternative option would be to use Common Test instead of Eunit. Common Test comes with a runner (ct_run command) and gives you more flexibility in your test setup but is also a little more complex to use. Common Test lacks on the available macros but produces very comprehensible html reports.



回答2:

No easy or documented way, but there are currently two ways you can do this. One is to give the option 'event_log' when you run the tests:

eunit:test(my_module, [event_log])

(this is undocumented and was really only meant for debugging). The resulting file "eunit-events.log" is a text file that can be read by Erlang using file:consult(Filename).

The more powerful way (and not really all that difficult) is to implement a custom event listener and give it as an option to eunit:

eunit:test(my_module, [{report, my_listener_module}])

This isn't documented yet, but it ought to be. A listener module implements the eunit_listener behaviour (see src/eunit_listener.erl). There are only five callback functions to implement. Look at src/eunit_tty.erl and src/eunit_surefire.erl for examples.



回答3:

I've just pushed to GitHub a very trivial listener, which stores the EUnit results in a DETS table. This can be useful, if you need to further process those data, since they're stored as Erlang terms in the DETS table.

https://github.com/prof3ta/eunit_terms

Example of usage:

> eunit:test([fact_test], [{report,{eunit_terms,[]}}]).
All 3 tests passed.
ok
> {ok, Ref} = dets:open_file(results).
{ok,#Ref<0.0.0.114>}
> dets:lookup(Ref, testsuite).
[{testsuite,<<"module 'fact_test'">>,8,<<>>,3,0,0,0,
        [{testcase,{fact_test,fact_zero_test,0,0},[],ok,0,<<>>},
         {testcase,{fact_test,fact_neg_test,0,0},[],ok,0,<<>>},
         {testcase,{fact_test,fact_pos_test,0,0},[],ok,0,<<>>}]}]

Hope this helps.



标签: erlang eunit