运行以下代码时,我得到警告:
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
的值,但在断言中未定义。
为什么会这样?
答案 0 :(得分:3)
ExUnit.test/3
是a macro,它为您定义了一个功能。
每次在Elixir中定义新功能时,它都会启动一个新作用域。这意味着在函数外部定义的任何变量将在函数内部不可用。例如,您不能执行以下操作:
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
定义模块属性后,显然可以在模块中的任何位置看到它们。