При запуске следующего кода я получаю предупреждение:
warning: variable "char" does not exist and is being expanded to "char()", please use parentheses to remove the ambiguity or change the variable name
test/my_module_test.exs:7
После неудачного теста:
== Compilation error in file test/my_module_test.exs ==
** (CompileError) test/my_module_test.exs:7: undefined function char/0
(stdlib) lists.erl:1338: :lists.foreach/2
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir) lib/code.ex:767: Code.require_file/2
(elixir) lib/kernel/parallel_compiler.ex:209: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6
defmodule MyModule do
use ExUnit.Case, async: true
doctest MyModule
Enum.each ~w(a b c), fn char ->
test "test involving #{char}" do
assert char == char
end
end
end
Кажется, что в блоке Enum.each
значение char
определено для строки test "... #{char}" do
, но становится неопределенным в утверждениях.
Почему это происходит?
ExUnit.test/3
— это макрос, который определяет для вас функцию.
Каждый раз, когда вы определяете новую функцию в Эликсире, она запускает новую область видимости. Это означает, что любая переменная, определенная вне функции, не будет доступна внутри функции. Например, вы не можете сделать это:
foo = 1
def some_function() do
foo
end
Есть несколько способов обойти этот механизм. Один из них — использовать unquote
для ввода некоторых значений в качестве AST. Однако в этом случае самый простой подход — поместить значение в атрибут модуля, чтобы вы могли прочитать его внутри функции:
@foo 1
def some_function() do
@foo
end
Если вы хотите запустить один и тот же тест с разными входными данными (хотя это, вероятно, означает наличие проблем с дизайном структуры теста), вы можете использовать ExUnit.Callbacks.setup_all/2
для настройки контекста тестов или использовать атрибуты модуля, как показано в документации для ExUnit.Case.test/3
.
Enum.each ~w(a b c), fn char ->
@char char
test "test involving #{char}", ctx do
assert @char == @char
end
end
Атрибуты модуля, очевидно, видны из любого места в модуле после того, как они определены.