为什么Eunit不需要导出测试功能?

时间:2016-03-26 16:08:04

标签: erlang eunit

我正在浏览Learn You Some Erlang中的EUnit章节,我从所有代码示例中注意到的一件事是测试函数永远不会在-export()子句中声明。

为什么EUnit能够选择这些测试功能?

2 个答案:

答案 0 :(得分:2)

From the documentation

  

在Erlang模块中使用EUnit的最简单方法是在模块的开头添加以下行(在-module声明之后,但在任何函数定义之前):

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

这将产生以下效果:

     
      
  • 创建导出的函数 test()(除非测试已关闭,模块尚未包含test()函数),可用于运行所有模块中定义的单元测试

  •   
  • 导致名称匹配 ..._test()..._test_() 的所有功能自动从模块中导出(除非测试已关闭) ,或定义了EUNIT_NOAUTO宏)

  •   

答案 1 :(得分:0)

很高兴我发现了这个问题,因为它为我提供了一种有意义的拖延方式,我想知道如何动态创建和导出函数。

首先在4273cbd的Erlang / OTP Github存储库中查看影响EUnit的最新提交。 (这样做的唯一原因是找到一个相对稳定的锚点,而不是git分支。)

0。包含EUnit的头文件

根据EUnit's User's Guide,第一步是在经过测试的模块中进入-include_lib("eunit/include/eunit.hrl").,所以我认为这就是神奇的地方。

1。 otp/lib/eunit/include/eunit.hrl(第79-91行)

%% Parse transforms for automatic exporting/stripping of test functions.
%% (Note that although automatic stripping is convenient, it will make
%% the code dependent on this header file and the eunit_striptests
%% module for compilation, even when testing is switched off! Using
%% -ifdef(EUNIT) around all test code makes the program more portable.)

-ifndef(EUNIT_NOAUTO).
-ifndef(NOTEST).
-compile({parse_transform, eunit_autoexport}).
-else.
-compile({parse_transform, eunit_striptests}).
-endif.
-endif.

1.1 -compile({parse_transform, eunit_autoexport}).是什么意思?

从《 Erlang参考手册》的“模块”一章(Pre-Defined Module Attributes):

  

-compile(Options).
   编译器选项。选项是单个选项或选项列表。该属性在以下情况下添加到选项列表中:   编译模块。请参见Compiler中的 compile(3) 手册页。

转到compile(3)

  

{parse_transform,Module}
   引起解析转换功能   Module:parse_transform / 2将在解析代码之前应用于   检查代码是否存在错误。

通过erl_id_trans模块:

  

此模块执行Erlang代码的身份解析转换。   它是为想要编写自己的用户的示例提供的   解析变压器。如果将选项{parse_transform,Module}传递给   在编译器中,用户编写的函数parse_transform/2由   在检查代码之前是否有错误。

基本上,如果模块M包含{parse_transform, Module}编译选项,则可以通过使用Module:parse_transform/2的实现来迭代M的所有功能和属性。它的第一个参数是Forms,它是Erlang的abstract format(在Erlang Run-Time System Application (ERTS) User's Guide中描述的M的模块声明。

2。 otp/lib/eunit/src/eunit_autoexport.erl

此模块仅导出parse_transfrom/2来满足{parse_transform, Module}的编译选项,其首要任务是确定测试用例函数和生成器的已配置后缀是什么。如果未手动设置,则分别使用_test_test_(通过lib/eunit/src/eunit_internal.hrl)。

然后它使用eunit_autoexport:form/5扫描模块的所有功能和属性,并建立一个要导出的功能列表,其中上述后缀匹配(加上原始功能。我对此可能是错的。) )。

最后,eunit_autoexport:rewrite/2从原始的Forms(作为第一个参数赋予eunit_autoexport:parse_transform/2)和要导出的功能列表(由{{ 1}})。在line 82上注入EUnit documentation中提到的form/5函数。