Elixir集成测试出现假阳性未报错原因及防假阳性方案
问题1:测试假阳性的根本原因
你遇到的假阳性完全是assert语句的写法错误导致的,和你把两个模块放在同一个文件没有任何关系:
- 你先给
result变量绑定了预期的正确TodoList结构体,后续assert result = TodoList.CsvImporter.import("todos.csv")的写法中,=是Elixir的模式匹配操作符,但对于已经绑定过值的变量,默认行为是重新绑定变量而非用已有值做匹配,所以不管import函数返回什么内容,都会直接赋值给result变量,这个表达式永远返回真值,assert自然永远通过。 - 你运行测试时看到的警告也不是误报,就是Elixir编译器提示你
result变量被重复绑定的预警信息,恰好指向了问题根源。 - 额外补充:如果你是想做值相等比较,用的是
==而不是=,如果是想用已有变量做模式匹配,需要加^针运算符固定变量值。
问题2:避免这类假阳性的方案
修正测试写法
有三种常用的正确写法可选:
- 直接把预期结构放在
assert左侧,不需要提前绑定变量:
assert %TodoList{ auto_id: 4, entries: %{ 1 => %{date: ~D[2018-12-19], title: "Dentist"}, 2 => %{date: ~D[2018-12-20], title: "Shopping"}, 3 => %{date: ~D[2018-12-19], title: "Movies"} } } = TodoList.CsvImporter.import("todos.csv")
这种写法下左侧是结构体模式,匹配失败直接抛出断言错误。
2. 如果要提前把预期值存为变量,匹配时加^固定变量值:
expected = %TodoList{...正确结构...} assert ^expected = TodoList.CsvImporter.import("todos.csv")
- 直接用全等比较做断言:
expected = %TodoList{...正确结构...} assert expected == TodoList.CsvImporter.import("todos.csv")
其他规避手段
- 重视所有编译警告,Elixir的编译警告几乎都是潜在问题的提示,不要当成误报忽略。
- 可以在测试文件的
ExUnit.start()调用中添加strict: true参数,把所有编译警告转化为错误,强制要求修复后才能运行测试。 - 遵循测试先行的开发流程,实现功能前先写好测试,先确保测试能失败,再做功能实现,避免测试本身的逻辑漏洞。
学习资源推荐
- Elixir官方文档的ExUnit章节
- 专门讲解Elixir测试的书籍《Testing Elixir》
- Elixir官方指南中的测试相关章节
内容的提问来源于stack exchange,提问作者jacksonbenete
相关产品推荐
相关产品推荐

