【问题标题】:Why do no third party assertion libraries exist for Common Test?为什么 Common Test 不存在第三方断言库?
【发布时间】:2015-02-16 23:21:22
【问题描述】:

在编写测试时,我发现自己编写了各种小的辅助函数来进行断言。我搜索了一个断言库,但没有找到任何东西。在我的测试中,我经常有这样的事情:

value_in_list(_Value, []) ->
  false;
value_in_list(Value, [Item|List]) ->
  case Value == Item of
    true ->
      true;
    false ->
      value_in_list(Value, List)
  end.

test_start_link(_Config) ->
  % should return the pid and register the process as my_app
  {ok, Pid} = my_app:start_link(),
  true = is_pid(Pid),
  value_in_list(my_app, registered()).

我最终不得不编写一个完整的函数来检查 my_app 是否是一个注册进程。如果我可以打电话给assertion:value_in_list(my_app, registered())assertion:is_registered(my_app) 这样的东西会更好。

我来自 Ruby 背景,所以我讨厌为了做出一些断言而不得不使用实用函数来混淆我的测试。如果我能这样做会更干净:

test_start_link(_Config) ->
  % should return the pid and register the process as my_app
  {ok, Pid} = my_app:start_link(),
  true = is_pid(Pid),
  assertion:value_in_list(my_app, registered()).

所以我的问题是:

  • 为什么没有用于 Common Test 的断言库?
  • 是否可以构建一个在所有测试期间都可以访问的第三方库?

【问题讨论】:

  • 与 Common Test 无关,但我会说如果你想做出断言,你应该使用 EUnit。 EUnit 提供了大量的断言宏(尽管不包括 is_registered 案例;相反,您必须执行类似 ?assert(lists:member(my_app, registered()) 之类的操作)
  • 另外,看看 Berzemus 的回答(以及 LYSE 的链接),因为它很好地解释了 EUnit 和 Common Test 的不同用例:stackoverflow.com/questions/18031247/eunit-vs-common-test
  • 也许我误用了断言这个词。我的意思是当某些东西返回意外的值时会引发异常。例如,在我上面的代码中,我认为true = is_pid(Pid) 是一个断言。如果Pid 不是 pid,则会引发异常。
  • 其实这个想多了,没必要测试这个。标准 OTP 测试应确保按预期进行。
  • 这可能是一个糟糕的示例选择。无需测试该进程是否已注册。我试图说明这样一个事实,即我们经常需要使用辅助函数来混淆我们的测试,以确定我们正在测试的函数是否按照我们期望的方式工作。

标签: unit-testing erlang assertion common-test


【解决方案1】:

对此的一些想法:

将您的应用程序启动移动到套件的启动部分:

init_per_suite(Config) ->
  {ok, Pid} = my_app:start_link(),
  true = is_pid(Pid),
  [{app, Pid} | Config].

然后将您的测试注册写为:

test_registration(Config) ->
  Pid = ?config(app, Config),
  true = lists:member(Pid, registered()).

没有必要通过显式断言函数来断言事物,因为它们是“内置的”。只需像上面那样进行失败的匹配,测试过程就会崩溃。因此报告测试用例出错了。每个测试用例都在自己的进程中运行。这也是您要在 init_per_suite/1 回调中启动应用程序的原因。否则,my_app 将在您的测试用例运行后终止,因为您已链接到每个测试用例的进程。

所以答案是:断言是内置的。因此对断言库的需求较少。

【讨论】:

    【解决方案2】:

    顺便说一句,在签名中编写模式匹配中的第一个块比添加大小写更简洁、更有效。

    value_in_list(_Value, []           ) -> false;
    value_in_list( Value, [Value|List] ) -> true;
    value_in_list( Value, [ _   |List] ) -> value_in_list(Value, List).
    

    我意识到这可能只是对原始问题的评论,但如果没有等宽和换行符,这将很难阅读。

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
    • 好吧,对不起,我几乎不使用堆栈溢出,而且我不太了解当地的规则。在这种语言中,这是一个主要的性能差异。我只是想给他一个有用的提示。
    【解决方案3】:

    您可以只在 Common Test 中使用 EUnit 断言。

    -include_lib("eunit/include/eunit.hrl").
    

    所有常规断言都可用。

    【讨论】:

      【解决方案4】:

      我决定写一个Erlang assertion library 来帮助处理这样的案例。它提供了这个功能。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-10
        • 1970-01-01
        • 1970-01-01
        • 2014-05-17
        • 2016-02-03
        相关资源
        最近更新 更多