5

我有一个通用测试套件,它尝试创建一个 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).

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).

运行它,我发现它的功能很漂亮。

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

  • 为什么会这样?
  • 如何在每个套件和每个测试用例之间共享一个 ets 表?
4

2 回答 2

3

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

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

要清理所有你需要的是在你的end_per_suiteorend_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).

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

于 2013-03-26T10:21:44.670 回答
2

一个 ets 表附加到一个进程并在进程结束后立即销毁,除非您使用 give_away 函数(我担心在这种情况下这是不可行的)

作为通用 tets 文档中的状态,每个测试用例以及 init_per_suite 和 end_per_suite 都在单独的进程中运行,因此一旦您离开 init_per_suite 函数,ets 表就会被销毁。

来自 common_test 文档

init_per_suite 和 end_per_suite 将在专用的 Erlang 进程上执行,就像测试用例一样。然而,这些函数的结果不包括在成功、失败和跳过案例的测试运行统计中。

来自 ets 文档

默认所有者是创建表的进程。表所有权可以在进程终止时通过使用 heir 选项或通过调用 give_away/3 显式转移。

于 2013-03-26T08:26:25.613 回答