はじめに
この記事を書いている人も完全には理解していないが、一応解決したので、似たような状況で困っている人のヒントになるように記事を残す。
バインディングを作っている時に、「有る操作を行うと、バインディングのC側のグローバル変数みたいなものが変更されてしまうため、後続のテストに影響を与えないようにフォークしてテストを行いたい」というような面倒なケースがある。
Minitestには、assert_output
という便利なメソッドがあり、stdoutやstderrのテストができる。しかし、これらはサブプロセスのIOまでは掌握してくれなかったりする。
かといって、spawn使って bundle exec ruby -r minimap2 -e "hogefuga"
みたいなのを書くというのも嫌な感じがする。なにしろこの場合、bundlerを使わないとテストが成功しない。それはどうなのか。
capture_subprocess_io を使う
うまい解決策はないだろうか? 実は Minitestの assert_output
のドキュメントを見ると
NOTE: this uses capture_io, not capture_subprocess_io.
という注釈がある。どうやら、サブプロセスのIOを把握する方法もあるけれども、それは遅いから assert_output
では使ってないよということらしい。そこでcapture_subprocess_io
を利用する。これとForkを組み合わせることで、サブプロセスの実行するプロセスのIOのテストが可能になる。こんな感じである。
def test_execute_with_string_arg
out, err = capture_subprocess_io do
pid = fork do
MM2.execute('--version') # ここの操作をフォークして行いたい
end
Process.waitpid(pid)
end
assert_equal "2.24-r1122\n", out
assert_equal "", err
end
この記事は、やや適当な記事で、技術的には間違っている部分もあるかもしれないが、ネットでググってもあまりめぼしい情報がヒットしないので記事にした。間違っている場合は、コメント欄で教えてください。
この記事は以上です。