test-unitさえあればご飯大盛り三杯はイケる
rspec3 に疲弊している皆さんこんにちは。今日は rspec3 に疲れた皆さんへ憩いの場として test-unit gem のお話を提供したいと思います。
test-unit gem について
「Rubyのテスティングフレームワークの歴史(2014年版)」の記事に詳しく書いてありますが、test-unit gem は古来にあった test/unit とも minitest とも違う第3の(第4?5?よくわかりません)の単体テストライブラリです。
Ruby コミッタでもある @kou 氏が精力的にメンテナンスを続けてくれており、 Ruby 2.2 に標準で bundle される今をときめくテスティングライブラリです。
古来の test/unit に比べて多くの機能が入っており、大変便利になっています。
テストの書き方
本来ならばここで、テストの記法について語るのでしょうが、@repeatedly 氏が以前に書いてくれた 「Test::Unit でテストを書く」の記事が大変参考になるので、そちらにおまかせします。
本記事では、それに対する補完として、test-unit のコマンドラインオプションについて記載します。
ファイルを指定してテストを実行する。
rspec では、以下のようにファイルを指定してテストを実行できました。
rspec spec/xxx_spec.rb
これは test-unit でもできます。require 'test/unit'
しているファイルを直接指定して、ruby スクリプトとして実行すれば OK です。
# test/test_xxx.rb require 'test/unit' class TestXXX < Test::Unit::TestCase end
$ ruby test/test_xxx.rb
ちなみに、require してクラス定義しているだけなのに、なんでスクリプト実行されるの?メソッド呼んでないよ?という気になりますが、どうやら以下のような挙動になっているらしいです。
上の例では、テストクラスを「定義しただけ」で、テストが実行されています。 これは、require 'test/unit'した時に Test::Unit.autorunを実行し ているためです。その結果、終了時の後処理として実行されるようになってい ます。
cf. http://docs.ruby-lang.org/ja/2.1.0/library/test=2funit.html (正確には見るべきドキュメントが違いますが似たような挙動でしょう)
ヘルプ
-h
オプションでヘルプを参照できます。test-unit には rspec のようなコマンドはないので、これも require 'unit/test'
しているファイルを指定して、-h
オプションを指定します。
ruby test/test_xxx.rb -h
とりあえずヘルプを全部貼っておきます。
Test::Unit automatic runner. Usage: test_xxx.rb [options] [-- untouched arguments] -r, --runner=RUNNER Use the given RUNNER. (c[onsole], e[macs], x[ml]) --collector=COLLECTOR Use the given COLLECTOR. (de[scendant], di[r], l[oad], o[bject]_space) -n, --name=NAME Runs tests matching NAME. (patterns may be used). --ignore-name=NAME Ignores tests matching NAME. (patterns may be used). -t, --testcase=TESTCASE Runs tests in TestCases matching TESTCASE. (patterns may be used). --ignore-testcase=TESTCASE Ignores tests in TestCases matching TESTCASE. (patterns may be used). --location=LOCATION Runs tests that defined in LOCATION. LOCATION is one of PATH:LINE, PATH or LINE --attribute=EXPRESSION Runs tests that matches EXPRESSION. EXPRESSION is evaluated as Ruby's expression. Test attribute name can be used with no receiver in EXPRESSION. EXPRESSION examples: !slow tag == 'important' and !slow --[no-]priority-mode Runs some tests based on their priority. --default-priority=PRIORITY Uses PRIORITY as default priority (h[igh], i[mportant], l[ow], m[ust], ne[ver], no[rmal]) -I, --load-path=DIR[:DIR...] Appends directory list to $LOAD_PATH. --color-scheme=SCHEME Use SCHEME as color scheme. (d[efault]) --config=FILE Use YAML fomat FILE content as configuration file. --order=ORDER Run tests in a test case in ORDER order. (a[lphabetic], d[efined], r[andom]) --max-diff-target-string-size=SIZE Shows diff if both expected result string size and actual result string size are less than or equal SIZE in bytes. (1000) -v, --verbose=[LEVEL] Set the output level (default is verbose). (important-only, n[ormal], p[rogress], s[ilent], v[erbose]) --[no-]use-color=[auto] Uses color output (default is auto) --progress-row-max=MAX Uses MAX as max terminal width for progress mark (default is auto) --no-show-detail-immediately Shows not passed test details immediately. (default is yes) --output-file-descriptor=FD Outputs to file descriptor FD -- Stop processing options so that the remaining options will be passed to the test. -h, --help Display this help. Deprecated options: --console Console runner (use --runner).
行番号を指定して実行する
rspec の時は、以下のようにして行番号を指定して、特定のテストを実行することができました。
$ rspec spec/xxx_spec.rb:12
これができないテスティングフレームワークへの移行などできるはずもないわけですが、test-unit gem でもできます!--location
オプションに行番号を指定してテストを実行することができます。
$ ruby test/test_xxx.rb --location 12
やった! ╭( ・ㅂ・)و ̑̑
テスト名を指定して実行する
--name
オプションで特定のテスト(メソッド)を指定してテストを実行することができます。
# test/test_xxx.rb require 'test/unit' class TestXXX < Test::Unit::TestCase def test_foo assert_true(true) end def test_bar assert_false(true) end end
$ ruby test/test_xxx.rb --name test_foo
test_foo
のテストだけが実行されます。注意点としては、以下のような test 文字列 do; end
の記法を使うと --name
オプションを使用できなくなるところです。
# test/test_xxx.rb require 'test/unit' class TestXXX < Test::Unit::TestCase test "test_foo" do assert_true(true) end test "test_bar" do assert_false(true) end end
--location
使えればなんとかなると思っているので、個人的にはあまり気にしていません。
タグを指定して実行する
rspec にはタグという機能があって、タグを指定してテストをフィルタリングして実行することができました。
# stack_spec.rb describe Stack do context "when new" do it '#empty?', :current => true do should be_empty end it '#items', :type => 'getter' do should have(0).items end end end
$ rspec stack_spec.rb --tag current $ rspec stack_spec.rb --tag type:getter
test-unit gem には属性という機能があって、属性をつけてフィルタリングすることができます。
require 'test/unit' class TestXXX < Test::Unit::TestCase attribute :current, true test "test_foo" do assert_true(true) end attribute :type, 'getter' test "test_bar" do assert_false(true) end end
$ ruby test_xxx.rb --attribute current $ ruby test_xxx.rb --attribute 'type == "getter"'
Ruby の文法で複雑な条件も指定できます。
$ ruby test_xxx.rb --attribute 'current || type == "getter"'
まとめ
rspec ではできたオプションを test-unit gem ではどのように指定するのか解説してみました。 test-unit gem には他にも priority 指定の機能などもあったりするので、是非調べてみてください!
ドキュメントページ にもこの辺書いてあるといいんだどなぁ|ω・`)チラ