I try to run common test suites from erl shell with command:
> ct:run_test([{spec,"test/spec"}]).
Test suite fails with an error:
undefined function eredis:start_link/3
But if I type in the shell this:
> eredis:module_info().
I can see that dependent module eredis was loaded:
[{exports,[{start_link,0},
{start_link,2},
...
{start_link,6},
...
Why ct:run_test does not see dependent modules and how to run it correctly from erl shell?
I found that the problem is not in dependencies. I wrote sample code that reproduces the problem.
One should always set absolute path to ebin directory (with -pa option) when running ct:run_test/1 from erlang shell.
Otherwise common tests started from erlang shell with the command:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct:run_test([{spec,"test/spec"}]).
will fail with the error:
=== ERROR! init_per_testcase crashed!
Location: [{ct_fail,start_link},
{fail_SUITE,init_per_testcase,16},
{test_server,do_init_per_testcase,1191},
{test_server,run_test_case_eval1,955},
{test_server,run_test_case_eval,926}]
Reason: {undef,[{ct_fail,start_link,[1,2],[]},
{fail_SUITE,init_per_testcase,2,
[{file,"fail_SUITE.erl"},{line,16}]},
{test_server,do_init_per_testcase,2,
[{file,"test_server.erl"},{line,1191}]},
{test_server,run_test_case_eval1,6,
[{file,"test_server.erl"},{line,955}]},
{test_server,run_test_case_eval,9,
[{file,"test_server.erl"},{line,926}]}]}
The most interesting part is that when module_info
command is executed before test running:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct_fail:module_info().
ct_fail:module_info().
[{module,ct_fail},
{exports,[{start_link,0},
{start_link,1},
{start_link,2},
{start_link,3},
{start_link,4},
{init,1},
...
> ct:run_test([{spec,"test/spec"}]).
then tests will succeed!
By the way when test fails:
$ ./rebar3.1 compile && erl -pa _build/default/lib/ct_fail/ebin/
> ct:run_test([{spec,"test/spec"}]).
...
function call that caused test failure disappears from module exports list:
> ct_fail:module_info().
[{module,ct_fail},
{exports,[{start_link,0},
{start_link,1},
{start_link,3},
{start_link,4},
{init,1},
...
ct_fail:start_link/2
is not exported anymore!