Erlang 为什么Eunit不要求导出测试函数?

Erlang 为什么Eunit不要求导出测试函数?,erlang,eunit,Erlang,Eunit,我正在阅读中的EUnit一章,从所有代码示例中我注意到的一件事是,-export()子句中从未声明过测试函数 为什么EUnit能够选择这些测试功能?: 在Erlang模块中使用EUnit的最简单方法是在模块开头添加以下行(在-module声明之后,但在任何函数定义之前): 这将产生以下效果: 创建导出函数test()(除非测试已关闭,且模块尚未包含test()函数),该函数可用于运行模块中定义的所有单元测试 使名称匹配的所有函数自动从模块导出(除非关闭测试,或定义了EUNIT\u NOAUT

我正在阅读中的EUnit一章,从所有代码示例中我注意到的一件事是,
-export()
子句中从未声明过测试函数

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

:

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

这将产生以下效果:

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

  • 使名称匹配的所有函数自动从模块导出(除非关闭测试,或定义了
    EUNIT\u NOAUTO
    宏)


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

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

0包含EUnit的头文件 根据本文,第一步是
-include_lib(“eunit/include/eunit.hrl”)。
在测试的模块中,所以我假设这就是神奇发生的地方

1.(第79-91行) 1.1编译({parse_transform,eunit_autoexport})是什么意思? 从Erlang参考手册的模块章节():

-编译(选项)。

编译器选项。选项是单个选项或选项列表。在以下情况下,此属性将添加到选项列表中: 编译模块。请参阅编译器中的手册页

关于:

{parse_transform,Module}

导致解析转换函数 模块:parse_transform/2将应用于 检查代码是否有错误

从模块中:

此模块执行Erlang代码的标识解析转换。 它是作为一个示例提供给希望编写自己的代码的用户的 解析变压器。如果选项
{parse_transform,Module}
被传递给 编译器,一个用户编写的函数
parse_transform/2
,由 在检查代码是否有错误之前,先检查编译器

基本上,如果模块M包含
{parse_transform,module}
编译选项,那么可以使用
模块:parse_transform/2
的实现来迭代M的所有函数和属性。它的第一个参数是
Forms
,这是在Erlang中描述的M的模块声明(如中所述)

2. 此模块仅导出
parse\u transfrom/2
以满足
{parse\u transform,module}
编译选项,其首要任务是确定测试用例函数和生成器的配置后缀。如果未手动设置,则分别使用
\u test
\u test
(via)

然后,它使用扫描模块的所有函数和属性,并构建一个要导出的函数列表,其中上面的后缀匹配(加上原始函数。这一点我可能错了…)

最后,从原始的
Forms
(作为第一个参数提供给)和要导出的函数列表(由上面的
form/5
提供)构建一个模块声明。在该声明上插入了中提到的
test/0
函数

-include_lib("eunit/include/eunit.hrl").
%% 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.