3

次のメソッドで戻り値と IO 出力をテストしたいと思います。

defmodule Speaker do
  def speak do
    receive do
      { :say, msg } ->
        IO.puts(msg)
        speak
      _other ->
        speak # throw away the message
    end
  end
end

ExUnit.CaptureIOdocsには、次のようなこれを行うサンプル テストがあります。

test "checking the return value and the IO output" do
  fun = fn ->
    assert Enum.each(["some", "example"], &(IO.puts &1)) == :ok
  end
  assert capture_io(fun) == "some\nexample\n"
end

spawnそれを考えると、同様のアクションを実行するがed プロセスを使用する次のテストを記述できると思いました。

test ".speak with capture io" do
  pid = Kernel.spawn(Speaker, :speak, [])
  fun = fn ->
    assert send(pid, { :say, "Hello" }) == { :say, "Hello" }
  end
  assert capture_io(fun) == "Hello\n"
end

ただし、端末に出力が表示されていても、出力がなかったことを示す次のエラー メッセージが表示されます。

1) test .speak with capture io (SpeakerTest)
   test/speaker_test.exs:25
   Assertion with == failed
   code: capture_io(fun) == "Hello\n"
   lhs:  ""
   rhs:  "Hello\n"
   stacktrace:
     test/speaker_test.exs:30: (test)

それで、マクロspawnを使用する ed プロセスまたはメソッドのテストに関して、おそらく何かが欠けていますか? receiveテストに合格するように変更するにはどうすればよいですか?

4

2 に答える 2

5

CaptureIOここでやろうとしていることには適していない可能性があります。関数を実行し、その関数が戻るときにキャプチャされた出力を返します。しかし、あなたの関数は決して返らないので、これはうまくいかないようです。次の回避策を思いつきました。

test ".speak with capture io" do
  test_process = self()
  pid = spawn(fn ->
    Process.group_leader(self(), test_process)
    Speaker.speak
  end)

  send(pid, {:say, "Hello"})

  assert_receive {:io_request, _, _, {:put_chars, :unicode, "Hello\n"}}

  # Just to cleanup pid which dies upon not receiving a correct response
  # to the :io_request after a timeout
  Process.exit(pid, :kill)
end

Process.group_leaderテストされたプロセスの IO メッセージの受信者として現在のプロセスを設定し、これらのメッセージが到着したことをアサートします。

于 2016-06-27T23:52:02.410 に答える