我有一个通用的测试套件,试图创建一个可在所有套件和所有测试用例中使用的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).
运行此命令,我发现它的功能很漂亮。
我对这种行为感到困惑,无法确定为什么会发生这种情况,形成docs。问题:
最佳答案
正如Pascal的答案中已经提到的,以及User Guide中讨论的那样,只有init_per_testcase
和end_per_testcase
与测试用例在同一过程中运行。由于ETS表绑定(bind)到所有者进程,因此在整个套件或组中保留ETS表的唯一方法是放弃或定义继承进程。
您可以轻松地在init_per_suite
或init_per_group
函数中生成一个进程,将其设置为ETS表的继承人,并在配置中传递其pid。
要清理所有内容,请在end_per_suite
或end_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).
您还需要通过将其设置为
protected
或public
来确保您仍然可以从测试用例过程中访问表关于testing - 为什么ets表可以生存ct :init_per_testcase but not init_per_suite?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15631369/