1

I'm learning erlang and I have created a cache_server module implementing gen_server behaviour.

This module is responsible for creating ets tables and has an api to insert, lookup, etc.

I wanted to make test suite for the module and to run test cases for insertion and lookup in one group of tests as a sequence because first function populates the table and other searches for inserted keys.

I tried to call cache_server:start_link([]) in init_per_suite hook function of the suite but in test cases I don't see my cache_server process when I call registered() function.

And I get

{noproc,{gen_server,call,[cache_server,{lookup,numbers,1}]}}

error.

I also tried to move call cache_server:start_link() from the init_per_suite to the first test case but in the subsequent test cases the process gets unavailable.

When I test my code by hands using rebar3 shell, everything works as expected.

Is it possible to share a named gen_server process between test cases in common test test suite?

AndreyKo
  • 1,421
  • 2
  • 11
  • 25
  • 1
    Have you tried staring the server with gen_server:start(…) instead of gen_server:start_link(…)? (i.e. don't link it to the process evaluating init_per_suite/1) – Brujo Benavides Dec 02 '20 at 07:22
  • Hi, Brujo! Thanks for replying, No, I didn't try to do this. I call cache_server:start_link() which is defined like this: start_link(Opts) -> gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []). What is the difference of calling gen_server:start instead of gen_server:start_link()? – AndreyKo Dec 02 '20 at 07:59
  • By the way, if I put the call cache_server:start_link([]), insert data into tables and lookup data all together in one test case, it passes ok. But I wanted to split it to test cases by module functions. I've read the common test library documentation, specifically about it's not recommended to create dependent test cases, but in my case they are so closely dependent by nature. – AndreyKo Dec 02 '20 at 08:09
  • 1
    start_link links the started process with the current one, start doesn't. More info: https://learnyousomeerlang.com/errors-and-processes – Brujo Benavides Dec 02 '20 at 15:11
  • Thanks, Brujo! That worked, I changed cache_server:start_link([{drop_interval, 10}]) to gen_server:start({local, cache_server}, cache_server, [{drop_interval, 10}], []) in my init_per_suite function and my server process stayed alive, test cases passed! Please add an answer for me to accept it. – AndreyKo Dec 02 '20 at 19:18

1 Answers1

0

Try calling cache_server:start_link() in init_per_testcase. As this function is executed before each test case, you would also need to stop the cache_server process in end_per_testcase.

Another option is to group all cache_server related test cases in one group and call cache_server:start_link() in init_per_group and stop the process in end_per_group

  • Thanks, but my test cases are grouped and the group has [sequence] property and I already tried to call cache_server:start_link() in init_per_group, it didn't help. – user3357257 Dec 02 '20 at 19:02
  • 1
    If you have structured you code as an OTP app, (named say `cache_server`), then try `application:ensure_all_started(cache_server)` in `init_per_suite` and then call `cache_server:start_link()` in `init_per_suite` – Venkatakumar Srinivasan Dec 02 '20 at 21:31
  • Thanks for your help, that may work but I wanted to test my module without starting the whole application. I've already got the working solution from Brujo in comments to my question: instead of calling cache_server:start_link([{drop_interval, 10}]) I need to call gen_server:start({local, cache_server}, cache_server, [{drop_interval, 10}], []) in init_per_suite. This trick works because the server process started this way is not linked to the calling process, apparently the new process is spawned for every test case including init_per_suite preparation – AndreyKo Dec 03 '20 at 04:11