Elixir:集成测试误报,为什么会失败以及如何防止进一步的误报?

Elixir: Integration test false positive, why is it failing and how to prevent further false positives?

我刚开始使用 Elixir,所以我冒着风险问一些应该直截了当的问题。很抱歉,如果这应该是显而易见或简单的事情。

我将省略一些代码以保持问题简洁,代码实际上是用于 Elixir in Action 第 4 章的练习。

我写了一个结构如下:

%TodoList{auto_id: Integer, entries: %{}}

我为该结构实现了 CRUD 功能,练习是实际从 csv 文件导入数据以创建具有预定义数据的结构。

我写了以下测试:

...
  describe "import/1" do
    test "import csv file" do
      result = %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"}}}

      assert result = TodoList.CsvImporter.import("todos.csv")
    end
  end
...

由于一个错误,代码目前还没有生成正确的结构,如果我在 repl 中 运行 import/1 函数,你可以看到我得到的结果:

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> TodoList.CsvImporter.import("todos.csv")
%TodoList{
  auto_id: 4,
  entries: %{
    1 => %{date: {:ok, ~D[2018-12-19]}, title: "Dentist"},
    2 => %{date: {:ok, ~D[2018-12-20]}, title: "Shopping"},
    3 => %{date: {:ok, ~D[2018-12-19]}, title: "Movies"}
  }
}
iex(2)> 

如您所见,错误是在地图中生成 {:ok, DATE} 而不是 DATE 日期 字段。 我知道问题出在哪里,以及如何纠正它,因为这是解析文件的步骤之一中的一个简单错误。

问题是,当我 运行 测试时,我得到了误报。

我运行是这样的:

elixir -r TodoList.CsvImporter.ex todo_tests.exs

我想展示这个是因为书中建议在同一个文件中创建两个模块(TodoList 和 TodoList.CsvImporter),我不知道这是否也是 ExUnit 套装的任何错误来源.所以我 运行 调用其中包含两个模块的单个文件和包含已编写测试的第二个文件。

我得到的是多个(假的!)警告,所有测试都通过了,而这个显然应该失败,对吧?

  1. 为什么测试没有失败?
  2. 如何防止像这样的误报?

(我想这最后一个问题很主观,可能不适合 Whosebug,但是如果有任何关于测试的书籍或资源推荐,我们将不胜感激?)

如果你刚开始使用 Elixir,这是一个典型的错误,所以不要责备自己。阅读 this chapter to catch up, especially the part about the pin operator.

所以这里你只是将测试结果分配给 result:

assert result = TodoList.CsvImporter.import("todos.csv")

试试这个:

assert ^result = TodoList.CsvImporter.import("todos.csv")

现在应该有一个 MatchError,如您所料。

也可以使用==运算符使测试失败:

assert result == TodoList.CsvImporter.import("todos.csv")

两种方法都有用,就看你想怎么比较了。 == 更严格,因为您必须准确指定输出应该是什么。 = 可能会更宽松,因为有时您只能指定所需输出的一部分,例如比较地图或地图列表时。

,应该使用pin运算符或相等运算符

assert ^result = %{foo: "bar"}
assert result == %{foo: "bar"}

有一种方法可以防止这些误报,即使用 --warnings-as-errors 标志。如果您有警告,这将不会编译您的代码:

MIX_ENV=test mix do compile --warning-as-errors, test

或者可以将其添加到 mix.exs 文件中:

elixirc_options: [warnings_as_errors: true]