erlangcommon-test

Erlang ct:run_test dependencies


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?


Solution

  • 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!