Before copying the .erl files to the .eunit directory ensure that they
are deleted if they already exist. This prevents EACCES errors to happen
when trying to re-copy .erl files that are read-only.
Avoid error reports like this one:
prompt$ rebar eunit
==> dummy (eunit)
Test passed.
=ERROR REPORT==== 29-Dec-2011::23:22:11 ===
** Generic server inet_gethost_native_sup terminating
** Last message in was {'EXIT',<0.62.0>,killed}
** When Server state == {state,inet_gethost_native,undefined,<0.62.0>,
{local,inet_gethost_native_sup}}
** Reason for termination ==
** killed
Previously, it could happen if an eunit test did something that
required a name lookup, like in this example:
-module(dummy_tests).
-include_lib("eunit/include/eunit.hrl").
x_test() ->
{ok, _Hostent} = inet:gethostbyname(localhost).
The inet_gethost_native is a process, started on demand, under a
supervisor_bridge under the kernel_sup, but it is not a gen_server
process or the like, so it has nothing in '$ancestors' in its process
dictionary to indicate it is part of kernel.
This means that applications get a chance to shut down themselves,
before rebar will start killing their processes. This avoids ERROR
REPORTS from application supervisors.
Added new property to `eunit_opts` option list:
reset_after_eunit::boolean() - default = true.
If true, try to "reset" VM state to approximate state prior to
running the EUnit tests:
* Stop net_kernel if it was started
* Stop OTP applications not running before EUnit tests were run
* Kill processes not running before EUnit tests were run
* Reset OTP application environment variables
Previous patch erroneously assumed that cover:start() returned
{already_started,Pid} in the cases where cover was already started. We
now turn {error,{already_started,Pid}} into {ok, Pid} and return
{error, Reason} if we encounter an error we do not know about, this
will cause a nice and violent badmatch to stop everything.
The cover module calls io:format and io:fwrite directly for several types of
informational messages and warnings. When using meck to mock covered modules
these warnings are triggered and can cause severe polution of the test output.
We can avoid this by starting cover explicitly then setting the group_leader
of that process to a file handle.
This patch allows the 'suite' argument to eunit to be a comma separated
list of modules to test instead of being a single module. This allows
fine-grained testing when one test suite interferes with another and its
not clear which suite is causing the problem. It also lets you run the
test suite in a different order for a similar reason.
The other enhancement is to add a new eunit parameter; 'skip_app' which
like 'app' is a comma separated list of modules to skip testing on. This
parameter is only applied if the app parameter is not passed. Its
purpose is to avoid forcing you to specify all the apps to test if you
only want to skip a handful and there are many apps to test.
The eunit_dir() does use the ?EUNIT_DIR macro internally, but it also builds, what I guess is, an absolute path, which might be better :) At least it's more consistent.
Normally the ebin directory doesn't contain any source files. Therefore it won't be kept in the repository by, at least, mercurial and also maybe git unless you put some .keep file in it or do some other hack. The ebin directory is created by rebar compile, but if rebar eunit is called before rebar compile, you end up with a {'EXIT', {{badmatch,{error,bad_directory}},...}. Another approach would be not to match cod:add_pathz(ebin_dir()) with ok, but I think this is an ok solution as well.
Add a coverage report similar to the one output to index.html except
that it is output to the terminal if the new rebar.conf option
'cover_print_enabled' is set to true.
Modules that include the EUnit header get an implicit test/0 fun,
which cover considers a runnable line, but eunit:(TestRepresentation)
never calls. Result: prod modules with tests can never reach 100%
coverage. Ironic. In this case, fix it by decrementing the NotCovered
counter returned by cover:analyze/3.
1. When running the eunit command with the convention of putting
tests in "*_tests" modules, eunit would run those tests twice. This
is because: 1) eunit:test/1 will naturally look for foo's tests both
in foo, and in foo_tests, and 2) eunit:test/1 was being folded over
all project modules. The fix is to filter "*_tests" modules from the
list passed to eunit:test/1.
2. When running the eunit command with cover enabled and tests in a
'test' directory, cover would error because it couldn't find the
source code for those tests. This is because cover:analyze/3 will
only find module source in "." and "../src". This is hard-coded in
cover :-(. Since cover shouldn't be calculating code coverage on test
code anyway, the fix is to not fold cover:analyze/3 over
non-production code.
3. When running the eunit command with cover enabled and a test suite
defined, cover would only attempt to calculate coverage on the the
test suite itself. This was because only the suite was passed to
cover:analyze/3. The fix is to fold cover:analyze/3 over all the
production code, filtering out the suite module if it is defined.