elixir - Enum.each 在循环 ExUnit 测试时丢失变量
问题描述
运行以下代码时,我收到警告:
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
是一个为您定义函数的宏。
每次你在 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
模块属性在定义后在模块中的任何位置都明显可见。
推荐阅读
- css - 手机上的翻转框问题
- django - 为什么 django 不为 GenericForeignkey 的 object_id 创建 db_index?
- c# - Microsoft.ML 由于路径非法而无法保存模型?
- git - 是否有一种自动方法可以将 -SNAPSHOT 添加到分支开发中的 pom
- ssl - 没有 TLS 的 Nifi 安全性?
- azure-active-directory - 从 Postman 获取访问令牌:为“单页应用程序”客户端类型发布的令牌只能通过跨域请求兑换
- python - 被阻止从 python 中的网站抓取数据
- r - 如何将负二项式函数拟合到由 R ggplot 中的一个因子包裹的 facet_wrap 的数据?
- linux - Odroidh2 Debian - 无法 ping 网络网关/没有网络连接
- html - 选择选项后,如何将 Angular Material mat-autocomplete 文本颜色更改为白色?