查看源代码 ExUnit.CaptureIO (ExUnit v1.16.2)

用于捕获测试中 IO 的功能。

示例

defmodule AssertionTest do
  use ExUnit.Case

  import ExUnit.CaptureIO

  test "example" do
    assert capture_io(fn -> IO.puts("a") end) == "a\n"
  end

  test "another example" do
    assert with_io(fn ->
      IO.puts("a")
      IO.puts("b")
      2 + 2
    end) == {4, "a\nb\n"}
  end
end

概述

函数

捕获执行 fun 时生成的 IO。

捕获执行 fun 时生成的 IO。

捕获执行 fun 时生成的 IO。

调用给定的 fun 并返回结果和捕获的输出。

调用给定的 fun 并返回结果和捕获的输出。

调用给定的 fun 并返回结果和捕获的输出。

函数

@spec capture_io((-> any())) :: String.t()

捕获执行 fun 时生成的 IO。

返回捕获的输出的二进制数据。

默认情况下,capture_io 会替换当前进程的 group_leader (:stdio)。 捕获组领导者是在每个进程中完成的,因此可以并发地完成。

但是,任何其他命名设备(例如 :stderr)的捕获在全局范围内进行,并在函数结束之前一直持续。虽然这意味着在许多情况下,使用 async: true 运行测试是安全的,但捕获的输出可能包含来自其他测试的输出,在异步使用 capture_io 与命名进程时,需要格外小心。

开发者可以设置字符串作为输入。默认输入为空字符串。如果异步捕获命名设备,则只能向第一个捕获提供输入。对该设备上的任何后续捕获提供输入将引发异常,并表明测试应同步运行。

类似地,一旦命名设备上的捕获开始,在后续并发捕获中就不能更改该设备上的编码。在这种情况下将引发错误。

IO 设备

您可以捕获来自任何已注册的 IO 设备的 IO。给定的设备名称必须是一个原子,代表已注册进程的名称。此外,Elixir 提供了两个快捷方式

  • :stdio - :standard_io 的快捷方式,它映射到 Erlang 中的当前 Process.group_leader/0

  • :stderr - Erlang 中提供的命名进程 :standard_error 的快捷方式

选项

  • :input - IO 设备的输入,默认为 ""

  • :capture_prompt - 定义是否捕获提示(指定为 IO.get* 函数的参数)。默认为 true。对于除 :stdio 之外的 IO 设备,该选项被忽略。

  • :encoding (自 v1.10.0 起) - IO 设备的编码。允许的值为 :unicode (默认) 和 :latin1

示例

要捕获标准 IO

iex> capture_io(fn -> IO.write("john") end) == "john"
true

iex> capture_io("this is input", fn ->
...>   input = IO.gets("> ")
...>   IO.write(input)
...> end) == "> this is input"
true

iex> capture_io([input: "this is input", capture_prompt: false], fn ->
...>   input = IO.gets("> ")
...>   IO.write(input)
...> end) == "this is input"
true

请注意,使用 == 处理标准 IO 是可以的,因为内容是针对每个测试进程捕获的。但是,:stderr 在所有测试之间共享,因此如果您要进行异步测试,则应使用 =~ 而不是 ==:stderr 进行断言

iex> capture_io(:stderr, fn -> IO.write(:stderr, "john") end) =~ "john"
true

iex> capture_io(:standard_error, fn -> IO.write(:stderr, "john") end) =~ "john"
true

特别地,避免在异步测试中对 :stderr 进行空捕获

iex> capture_io(:stderr, fn -> :nothing end) == ""
true

否则,如果捕获了任何其他测试的标准错误,则测试将失败。

返回值

如上面的示例所示,capture_io 会返回捕获的输出。如果您还想捕获执行的函数的结果,请使用 with_io/2

链接到此函数

capture_io(device_input_or_options, fun)

查看源代码
@spec capture_io(atom() | String.t() | keyword(), (-> any())) :: String.t()

捕获执行 fun 时生成的 IO。

有关更多信息,请参见 capture_io/1

链接到此函数

capture_io(device, input_or_options, fun)

查看源代码
@spec capture_io(atom(), String.t() | keyword(), (-> any())) :: String.t()

捕获执行 fun 时生成的 IO。

有关更多信息,请参见 capture_io/1

链接到此函数

with_io(fun)

查看源代码 (自 1.13.0 起)
@spec with_io((-> any())) :: {any(), String.t()}

调用给定的 fun 并返回结果和捕获的输出。

它接受与 capture_io/1 相同的参数和选项。

示例

{result, output} =
  with_io(fn ->
    IO.puts("a")
    IO.puts("b")
    2 + 2
  end)

assert result == 4
assert output == "a\nb\n"
链接到此函数

with_io(device_input_or_options, fun)

查看源代码 (自 1.13.0 起)
@spec with_io(atom() | String.t() | keyword(), (-> any())) :: {any(), String.t()}

调用给定的 fun 并返回结果和捕获的输出。

有关更多信息,请参见 with_io/1

链接到此函数

with_io(device, input_or_options, fun)

查看源代码 (自 1.13.0 起)
@spec with_io(atom(), String.t() | keyword(), (-> any())) :: {any(), String.t()}

调用给定的 fun 并返回结果和捕获的输出。

有关更多信息,请参见 with_io/1