Rspec初心者が使って便利だと思ったRspecオプション

始めまして。 システム事業部の鈴木と申します。

1年間 Ruby on Rails の案件に参画してきましたが、Rails のテストフレームワークであるRspecに触れる機会が多々ありました。
その際に私が初めて使って、とても便利に感じたオプションについて、事例とそれを解消できるオプションについて書いて行きたいと思います。

そもそもオプションとは?

 Rspec を実行する時に指定する便利機能のことです。
$ bundle exec rspec "オプション" "ファイル名等"
 で指定することができます。
 また、.rspecファイルにオプションを書くことで、実行時には
 $ bundle exec rspec
 だけで、.rspecファイルの中のオプションを書いたものとして、実行してくれます。
 .rspecファイルの保存先と 記述例を書いておきます。 ファイル構造
 Railstest
├ Gemfile
├ app
└ .rspec
(要するにGemfileと同じ階層に作成します)

.rspecファイル 記述例

-f documentation  
-o rspec.txt  

では次から実際に起きた事例とそれに応じたオプションの使い方を説明します

事例 1. 今すぐに失敗しているテストを調査したい!!

業務で超大量のテストコードを実行し、それのテストが失敗している部分の調査を行いました。1回全て通して実行してみると、何個かテストが失敗している部分がありました。実行結果を見て修正をしましたが、それでも何個か落ちてしまっていました。 超大量のテストコードなので、実行時間もかなり時間がかかってしまいます。1回1回テストコードの終了を待っていたら何日あってもたりないので、テストコード実行中に失敗したテストの調査をし始める必要がありました。 しかし出力は .....FFFFF.... となんかのテストの成功と失敗しか分かりません。 そこで使用するのが次のオプションになります。

-f [出力形式]

出力形式については 1. progress 2. documentation 3. html 4. json

があります。 では出力形式によってどういった違いがあるのか、例を使って見てみます。

例:

context '検索が成功した場合' do  
  it 'レスポンスが成功している事' do  
 end  
  it 'レスポンスが200である事' do  
  end  
end  

というテストを
$ bundle exec rspec -f [出力形式] コマンドラインで実行
または
.rspec-f [出力形式] を追記した後、実行したとき

1.のprogress は 事例1 のように

$ bundle exec rspec  
Randomized with seed 00000  
....  
Finished in 0.70694 seconds (files took 7.7 seconds to load)  
4 examples, 0 failures  
Randomized with seed 00000  

と表示されます。 これは -f を省略したときにも表示されます 

2.のdocumentation は

$ 検索が成功した場合  
$ レスポンスが成功している事  
$ レスポンスが200である事  

のように progress より、分かりやすく、読みやすい形で出力してくれます

3.のhtmlについては以下のようにhtml形式で出力されます。

<div id=“div_group_4” class=“example_group passed”>
 <dl style=“margin-left: 30px;“>
 <dt id=“example_group_4” class=“passed”>検索が成功した場合</dt>
  <script type=“text/javascript”>moveProgressBar(75.0);</script>
  <dd class=“example passed”><span class=“passed_spec_name”>レスポンスが成功している事</span><span class=‘duration’>0.01757s</span></dd>
  <script type=“text/javascript”>moveProgressBar(100.0);</script>
  <dd class=“example passed”><span class=“passed_spec_name”>レスポンスが200である事</span><span class=‘duration’>0.01371s</span></dd>
 </dl>
</div>

ブラウザで開くとこうなります

f:id:zenet-tech:20201012192230p:plain
Rsepc_htmlde

最後に4.のjson もhtml形式と同様にjsonという形式で出力されます。これについては初心者の方は考えなくてもいいと思います。

{version”:“3.9.2",“seed”:29794,“examples”:[{id”:“./spec/controllers/*********_spec.rb[1:1:1:1]“,”description”:“レスポンスが成功している事“,
   ”full_description”:“TargetListsController GET #index 検索が成功した場合 レスポンスが成功している事“,
   ”status”:“passed”,“file_path”:“./spec/controllers/**************_spec.rb”,“line_number”:6,“run_time”:0.214949,“pending_message”:null},
   {id”:“./spec/controllers/*******_spec.rb[1:1:1:2]“,”description”:“レスポンスが200である事“
 ~~~~~中略~~~~~
 ,“summary”:{duration”:0.52153,“example_count”:4,“failure_count”:0,“pending_count”:0,“errors_outside_of_examples_count”:0},
 “summary_line”:“4 examples, 0 failures}

今回のように、途中でテストコードの調査をしたい場合は、2 の documentation を 選択すると、初心者でも分かりやすく表示してくれます。

またオプションにはテストコード実行時にコマンドラインで書く方法($ bundle exec rspec -f [出力形式])と.rspecに記述する方法の2通りありますが、このオプションについては、ずっと変更していてほしいなら.rspecに、場合によって出力を切り替え対場合はコマンドラインで書いたほうが良いです。 ちなみに私はテスト実行時に書いています。

事例 2. テストコードがたまにしか失敗しなくて、原因がわからない。

事例1では、テスト中から調査をし始めて修正を行って、全部成功にしたと思いましたが、念のため超大量のテストコードもう一度実行すると、別のところのテストが失敗していました。   しかし1回前の実行ではそれは成功していたのです。 ファイル単体でテストを回してみると、今度は成功してしまいました。
その後も何度かテストコード全体で実行しても、失敗したり成功したりまちまちでした。 私はテストコードが失敗している部分が見たいのに、ファイル単体では成功してしまい、全体でテストコードを実行しても、たまにしか失敗しない。 そんなときに使用下のが次のオプションになります

 --seed [シード値]

シード値とは?

乱数を生成するときの最初の設定値のことです。 シード値が同じであると生成する乱数は全く同じになります。
Rspecのテスト実行順序はランダムであるため、乱数と同様に、同じシード値を指定すると同じ実行順序になります。
例えば、以下はテスト実行時のログになります。最後の行のRandomized with seed 0000 の 00000 部分がシード値になります。

$ bundle exec rspec  
Randomized with seed 00000  
....  
Finished in 0.70694 seconds (files took 7.7 seconds to load)  
4 examples, 0 failures  
Randomized with seed 00000  

例:最後に [ Randomized with seed 12345 ] と表示されたテストと同じ順序でテストを行いたい場合は
$ bundle exec rspec --seed 12345コマンドラインで実行する。
または
.rspec--seed 12345 を追記した後、Rspecを実行します。

しかし、.rspec に書いて置くと別のテストコードを実行するとき等に、順序が固定されてしまい、
実行順序で失敗するコードに気づかない危険性があるため、 めんどくさいですが、コマンドラインで実行するときに書きましょう。

事例 3. テストの実行結果を保存したい。

こんどは超大量のテストコードの実行結果を見せてほしいといわれました。
しかしまだまだ大量にテストが失敗している状況で、実行結果をターミナルからコピーしようとしたとき、最初の部分が消えてしまい、うまくログが取れなかったことがあります。 でも、どうしてもすべてのログを取得したかったので、その時使用したのが、次のオプションになります。

-o [ファイル名]

これを使うと[ファイル名]に記載したファイルに実行結果を出力してくれます。
例えば
$ bundle exec rspec -o rspec.txt コマンドラインで実行
または
.rspec-o rspec.txt を追記した後、実行したとき
.rspecと同じ階層にrspec.txtが生成され、そのファイルに実行結果を出力してくれます。

注意点として、ターミナルには実行結果が表示されなくなってしまうため
別のターミナルで $ tail -f [ファイル名] を使うと、今まで通りにリアルタイムに実行結果を見れます。

事例1,事例2のオプションと違い、実行結果は常に取っておいてもいいと思いますので、 .rspecに記述したほうが良いと思います。

最後に

 Rspecを最初触った時は何をしたらいいのかよくわからずにテストコードを書いていました。実行しても、....FFFFFのように何をやっているかよくわかりませんでした。オプションなどの便利機能を使い始めるとわからないなりにもわかるように出力してくれたり、面倒くさいこともやってくれたりするので、初心者にこそ使ってほしいです。