2

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?

Galina
  • 75
  • 1
  • 4
  • `eredis` and `eredis_client` are two separate modules. – Greg Apr 11 '16 at 09:44
  • Thnx [Amiramix](http://stackoverflow.com/users/745250/amiramix). It was my typo. Actually eredis_client is part of [eredis](https://github.com/wooga/) and it also was loaded: `> eredis:module_info(). [{exports,[{start_link,0}, {start_link,2}, ... {start_link,6}` ct:run_test for two different test runs gave me two different errors but now I want to figure out why ct:run_test command fails with any dependency. – Galina Apr 11 '16 at 10:22
  • Your question now doesn't list `start_link/3` in the exports list that the error is complaining that it doesn't exist. Are you sure `start_link/3` is exported? if so, please edit the question appropriately. – Greg Apr 11 '16 at 10:27

1 Answers1

0

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!

Galina
  • 75
  • 1
  • 4