为什么ets表在ct:init_per_testcase中存活但不存在init_per_suite?

时间:2013-03-26 07:13:57

标签: 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).

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。问题:

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

2 个答案:

答案 0 :(得分:3)

正如Pascal在答案中已经提到的那样,User Guide中仅讨论init_per_testcaseend_per_testcase在与测试用例相同的过程中运行。由于ETS表绑定到所有者进程,因此在整个套件或组中保留ETS表的唯一方法是将其放弃或定义继承进程。

您可以在init_per_suiteinit_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).

您还需要确保仍然可以通过protectedpublic

从测试用例流程访问您的表格

答案 1 :(得分:0)

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

作为common tets doc中的状态,每个测试用例和init_per_suite以及end_per_suite都在不同的进程中运行,因此只要离开init_per_suite函数就会销毁ets表。

fron common_test doc

  

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

来自ets doc

  

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