为什么 ets 表可以在 ct:init_per_testcase 中幸存下来,但在 init_per_suite 中不行?

tro*_*ine 5 testing erlang common-test

我有一个通用的测试套件,它尝试创建一个 ets 表以用于所有套件和所有测试用例。它看起来像这样:

-module(an_example_SUITE).
-include_lib("common_test/include/ct.hrl").

-compile(export_all).

all() -> [ets_tests].

init_per_suite(Config) ->
    TabId = ets:new(conns, [set]),
    ets:insert(TabId, {foo, 2131}),
    [{table,TabId} | Config].

end_per_suite(Config) ->
    ets:delete(?config(table, Config)).

ets_tests(Config) ->
    TabId = ?config(table, Config),
    [{foo, 2131}] = ets:lookup(TabId, foo).
Run Code Online (Sandbox Code Playgroud)

ets_tests函数因 badarg而失败。创建/销毁每个测试用例的 ets 表,如下所示:

-module(an_example_SUITE).
-include_lib("common_test/include/ct.hrl").

-compile(export_all).

all() -> [ets_tests].

init_per_testcase(Config) ->
    TabId = ets:new(conns, [set]),
    ets:insert(TabId, {foo, 2131}),
    [{table,TabId} | Config].

end_per_testcase(Config) ->
    ets:delete(?config(table, Config)).

ets_tests(Config) ->
    TabId = ?config(table, Config),
    [{foo, 2131}] = ets:lookup(TabId, foo).
Run Code Online (Sandbox Code Playgroud)

运行这个,我发现它运行得很好。

我对这种行为感到困惑,无法确定为什么会发生这种情况,形成docs。问题:

  • 为什么会发生这种情况?
  • 如何在每个套件和每个测试用例之间共享一个 ets 表?

Pee*_*ger 3

正如 Pascal 的回答中已经提到的以及仅在用户指南init_per_testcase中讨论的那样,并且end_per_testcase在与测试用例相同的进程中运行。由于 ETS 表绑定到所有者进程,因此让 ETS 表在整个套件或组中持续存在的唯一方法就是放弃它或定义继承进程。

init_per_suite您可以轻松地在您的或函数中生成一个进程init_per_group,将其设置为 ETS 表的继承人,并在配置中传递其 pid。

要清理所有内容,您需要在您的end_per_suiteend_per_group函数中终止此进程。

-module(an_example_SUITE).
-include_lib("common_test/include/ct.hrl").

-compile(export_all).

all() -> [ets_tests].

ets_owner() ->
    receive
        stop -> exit(normal);
        Any -> ets_owner()
    end.

init_per_suite(Config) ->
    Pid = spawn(fun ets_owner/0),
    TabId = ets:new(conns, [set, protected, {heir, Pid, []}]),
    ets:insert(TabId, {foo, 2131}),
    [{table,TabId},{table_owner, Pid} | Config].

end_per_suite(Config) ->
    ?config(table_owner, Config) ! stop.

ets_tests(Config) ->
    TabId = ?config(table, Config),
    [{foo, 2131}] = ets:lookup(TabId, foo).
Run Code Online (Sandbox Code Playgroud)

您还需要确保您仍然可以从测试用例过程中访问您的表,方法是将其设置为protectedpublic