Почему Eunit не требует экспорта тестовых функций?

Я просматриваю главу EUnit в Изучите Erlang и кое-что хочу Из всех примеров кода я заметил, что тестовые функции никогда не объявляются в предложениях -export().

Почему EUnit поддерживает эти тестовые функции?


person KallDrexx    schedule 26.03.2016    source источник


Ответы (2)


Из документации:

Самый простой способ использовать EUnit в модуле Erlang — добавить следующую строку в начало модуля (после объявления -module, но перед любыми определениями функций):

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

Это будет иметь следующий эффект:

  • Создает экспортированную функцию test() (если тестирование не отключено и модуль еще не содержит функцию test()), которую можно использовать для запуска всех модульных тестов, определенных в модуле.

  • Заставляет все функции, имена которых соответствуют ..._test() или ..._test_(), автоматически экспортироваться из модуля (если не отключено тестирование или не определен макрос EUNIT_NOAUTO).

person Greg    schedule 26.03.2016

Рад, что нашел этот вопрос, потому что он дает мне осмысленный способ откладывать, и мне было интересно, как функции создаются и экспортируются динамически.

Начал с просмотра последнего коммита, затрагивающего EUnit, в репозитории Erlang/OTP Github, который называется 4273cbd. (Единственной причиной этого было найти относительно стабильный якорь вместо веток git.)

0. Включить заголовочный файл EUnit

Согласно Руководству пользователя EUnit, первым шагом будет -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 (Предопределенные атрибуты модуля< /а>):

-compile(Options).
Опции компилятора. Опции — это одна опция или список опций. Этот атрибут добавляется в список опций при компиляции модуля. См. страницу руководства
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}, то все функции и атрибуты M можно повторить с помощью вашей реализации Module:parse_transform/2. Его первый аргумент — Forms, это объявление модуля M, описанное в абстрактном формате< /strong> (описано в пользовательском приложении Erlang Run-Time System (ERTS)). Руководство.

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< /a> в качестве первого аргумента) и список экспортируемых функций (который был предоставлен form/5 выше). В строке 82 вставляется test/0 функция, упомянутая в документации EUnit.

person toraritte    schedule 14.11.2018