Testing 为什么ets表在ct:init_per_测试用例中存活,而不是在init_per_套件中存活?

Testing 为什么ets表在ct:init_per_测试用例中存活,而不是在init_per_套件中存活?,testing,erlang,common-test,Testing,Erlang,Common Test,我有一个公共测试套件,它试图创建一个ets表,用于所有套件和所有测试用例。看起来是这样的: -模块(示例套件)。 -include_lib(“common_test/include/ct.hrl”)。 -编译(全部导出)。 all()->[ets_测试]。 初始化每个套件(配置)-> TabId=ets:新(连接,[设置]), ets:insert(TabId,{foo,2131}), [{table,TabId}| Config]。 每个套件结束(配置)-> ets:删除(?配置(表,配置))

我有一个公共测试套件,它试图创建一个ets表,用于所有套件和所有测试用例。看起来是这样的:

-模块(示例套件)。
-include_lib(“common_test/include/ct.hrl”)。
-编译(全部导出)。
all()->[ets_测试]。
初始化每个套件(配置)->
TabId=ets:新(连接,[设置]),
ets:insert(TabId,{foo,2131}),
[{table,TabId}| Config]。
每个套件结束(配置)->
ets:删除(?配置(表,配置))。
ets_测试(配置)->
TabId=?配置(表,配置),
[{foo,2131}]=ets:lookup(TabId,foo)。
ets_tests
功能因badarg失败。根据测试用例创建/销毁ets表,如下所示:

-模块(示例套件)。
-include_lib(“common_test/include/ct.hrl”)。
-编译(全部导出)。
all()->[ets_测试]。
初始化每个测试用例(配置)->
TabId=ets:新(连接,[设置]),
ets:insert(TabId,{foo,2131}),
[{table,TabId}| Config]。
结束每个测试用例(配置)->
ets:删除(?配置(表,配置))。
ets_测试(配置)->
TabId=?配置(表,配置),
[{foo,2131}]=ets:lookup(TabId,foo)。
运行这个,我发现它的功能非常好

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

  • 为什么会发生这种情况
  • 如何在每个套件和每个测试用例之间共享ets表
ets表格附在流程上,并在流程结束后立即销毁,除非您使用“放弃”功能(我担心在这种情况下这是不可行的)

正如公共tets文档中的状态一样,每个测试用例以及每个套件的init_和end_都在单独的进程中运行,因此一旦您离开init_per_套件函数,ets表就会被销毁

普通测试文件

init_per_套件和end_per_套件将在专用Erlang上执行 过程,就像测试用例一样。这些功能的结果 但是,不包括在成功的测试运行统计数据中, 失败和跳过的案例

来自ets文件

默认所有者是创建表的进程。桌子 所有权可以通过使用继承人在流程终止时转让 选项或通过调用give_away/3显式调用


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

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

要清理,您只需在
end\u per\u suite
end\u per\u 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).

您还需要确保您仍然可以从testcase进程访问您的表,方法是将其设置为
受保护的
公共的

修复了工作示例(只是非工作示例的一个副本)在我的代码中添加了一个工作示例,现在对我来说运行正常这是可行的。。。请参阅我的回答。它们确实在同一进程上运行。引用erlang文档“由于init_per_testcase和end_per_testcase与测试用例在同一erlang进程上执行,这些配置函数的打印输出包含在测试用例日志文件中。”