経緯
※タイトルでピンとくる方は「何を今更・・」という情報だと思います。
RSpecの基本的な利用法を覚えるためにrspecコマンドの各オプションを一つずつ実行していました。
rspec --pattern(または-P)を試そうとして以下のような構成でテストコードを作りました。
本来はプロダクトコードが必要ですが、rspecのpatternオプションの検証には不要なので
specのみを作成しました。
構成
$ tree ┗ spec ┣ helper.rb ┣ it | ┣ scenario1_spec.rb | ┣ scenario2_spec.rb | ┗ scenario3_spec.rb ┣ spec_helper.rb ┗ ut ┣ hage_spec.rb ┣ hige_spec.rb ┗ hoge_spec.rb
全体を実行
$ rspec -fs Run options: include {:focus=>true} All examples were filtered out; ignoring {:focus=>true} Scenario1 scenario1_1 scenario1_2 Scenario2 scenario2_1 scenario2_2 Scenario3 scenario3_1 scenario3_2 Hage hage1 1 hage1 2 hage2 Hige hige1 1 hige1 2 hige2 Hoge hoge1 1 hoge1 2 hoge2 Finished in 0.00387 seconds 15 examples, 0 failures
単体テスト(ut)のみを実行
まずUbuntu環境。
※オプションの指定は「-P」「--pattern」のどちらでもよい。
$ rspec -fs -P "spec/ut/*.rb" Run options: include {:focus=>true} All examples were filtered out; ignoring {:focus=>true} Hage hage1 1 hage1 2 hage2 Hige hige1 1 hige1 2 hige2 Hoge hoge1 1 hoge1 2 hoge2 Finished in 0.00217 seconds 9 examples, 0 failures
想定通り動きました。
しかし、Windows7環境では下記のようになりました。
$ rspec -fs -P "spec/ut/*_spec.rb" Run options: include {:focus=>true} All examples were filtered out; ignoring {:focus=>true} Hige hige1 1 hige1 2 hige2 Hoge hoge1 1 hoge1 2 hoge2 Finished in 0.001 seconds 6 examples, 0 failures
Hageクラス関連のspecが動いて居ません。
runner.rbをデバッグして内容を確認
rspec_coreのrunner.rbのRSpec::Core::Runner.self.autorunの処理開始直後でARGVの中身を確認。
Ubuntu環境
["-fs", "-P", "spec/ut/*_spec.rb"]
Windows環境
["-fs", "-P", "spec/ut/hage_spec.rb", "spec/ut/hige_spec.rb", "spec/ut/hoge_spec.rb"]
Windows環境はワイルドカードが展開されてしまいました。
それらしき情報がないかググったらRuby公式に載っていました。
http://docs.ruby-lang.org/ja/2.0.0/doc/spec=2frubycmd.html
Windows環境はそういう仕様なんですね。
ということで下記のようにシングルクォートで指定したらWindows環境でも正しく動作しました。
rspec -fs -P 'spec/ut/*_spec.rb'
ただcmdを利用した場合は上記で良いのですが、cygwinのコンソール(cyglaunch含む)から実行すると
上記でもダブルクォートと同様の動きになります。
仕方がないので以下のように指定したところ、cyglaunchでも正しく動作しました。
rspec -fs -P"spec/ut/*_spec.rb"
RSpecのコードリーディング
ここまでrspec_coreのrunner.rbにしか触れていませんが
実際はもっと別の場所からデバッグしていたので色々ソースをみて解決に時間がかかったしまいました。
おかげでRSpecのコードを読むきっかけになりましたが。
主に見たのは下記のコード
https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/configuration.rb
https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/configuration_options.rb
https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/runner.rb
railsのactive_support/core_extのコードを色々と読んでいた経緯もあって対比が面白かった。
共通点はメソッドの処理が短いこと。例外的に長い部分はありますが大抵のメソッドが1行〜5行程度。
RSpecはBDDフレームワークなだけあって、人に優しい命名にこだわっていますね。
Railsと異なる部分ですが、時々とても説明的で長い変数名・メソッド名がでてきました。
1行の処理でも積極的にメソッド化していました。
・処理粒度を合わせるComposed Methodとして
・命名で処理内容を把握させるための「説明メソッド」として
・privateメソッドはコメントを付与しない代わりに特に詳しいメソッド名で読ませる
などの意味合いがあるのだろうと思いました。
※長いメソッド名の代表例2つ
def underscore_with_fix_for_non_standard_rspec_naming(string) def assert_no_example_groups_defined(config_option)
個人的に読みやすく好みのコードでした。