We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Test CLI input and output with `CaptureIO`
almirsarajcic
Test terminal behavior through the real IO calls instead of replacing IO.gets/1 or IO.write/2 with mocks. ExUnit.CaptureIO.capture_io/2 supplies stdin, captures stdout, and restores the test process’s IO device afterward.
defmodule MyApp.CLITest do
use ExUnit.Case, async: true
import ExUnit.CaptureIO
test "confirms account deletion" do
output =
capture_io("delete\n", fn ->
assert MyApp.CLI.confirm_deletion() == :confirmed
end)
assert output == "Type delete to confirm: "
end
end
The first argument becomes the input returned by calls such as IO.gets/1 inside the callback. The function returns everything written to the captured standard IO device, so one test can verify both the decision and the exact prompt a user sees.
This works by replacing the current process’s group leader for the duration of the callback. Code that uses the standard IO device follows that group leader automatically, which makes the test exercise the same calls as production code.
CaptureIO is process-oriented: output from unrelated processes is not automatically part of the capture. If the command starts a task, pass the capture device to that process with capture_io(device_pid, fun) or keep the assertion at the synchronous CLI boundary.
Use ExUnit.CaptureLog for Logger messages. Logger handlers are separate from the standard IO device, so console output and application logs need different test helpers.
copied to clipboard