【RSpec】システムスペックとリクエストスペックはどう使い分けるの？


## はじめに
最近RSpecの勉強をはじめたのですが、ある疑問が出てきました。

「**RSpecって、統合テストにシステムスペックとリクエストスペックの2種類があるけど、どう使い分ければいいんだろう？**🤔」

そんな時に、[EverydayRails](https://leanpub.com/everydayrailsrspec-jp)の翻訳者および[チェリー本](https://www.amazon.co.jp/プロを目指す人のためのRuby入門-言語仕様からテスト駆動開発・デバッグ技法まで-Software-Design-plusシリーズ/dp/4774193976)の著者として知られる、伊藤淳一さん(@jnchito)がご執筆された次の記事を発見。

[【動画付き】Railsチュートリアルの統合テスト(integration test)は、RSpecのリクエストスペックに置き換えるのがラクです - Qiita](https://qiita.com/jnchito/items/8d8d579cdca131c0db14)

何か選択基準はないものかと読んでみるのですが

「**これってRailsチュートリアル関係無く、どんなRailsアプリでも統合テストを書くならリクエストスペックを採用するべきってこと？でもシステムスペックでの置き換えも紹介されてるし...結局どっちで書けばいいんだ！**」

ってな感じでモヤモヤが晴れず...

最終的に「ええい、もうご本人に聞いちゃえ」ということで、思い切ってその記事に質問コメントを書いたところ...**なんと動画でレスポンスを頂きました（！）**

[https://www.youtube.com/watch?v=P98vOhU1O1I![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453435/e69ceea6-0f89-b3ce-4956-f1b8097529e8.png)](https://www.youtube.com/watch?v=P98vOhU1O1I)

この動画では、

- **システムスペックとリクエストスペックの使い分け方**
- **Railsチュートリアルの統合テストをリクエストスペックで書く理由**

について詳しくご回答頂いております。同じような疑問を持つ人であれば、この動画を見るだけでも十分為になると思うのですが、

>（そして、もし納得いただけたなら、僕の動画の内容をきれいにまとめてQiita記事にしてもらえると、ちょっと嬉しいかも・・・ｗ）

という伊藤さんご本人からのお達し（？）がありましたので、質問者であるこの私が**記事として再度まとめさせて頂くことになりました。**

なるべく動画の内容に忠実にするつもりでしたが、文章としての整合性をとろうとした結果、私自身の解釈も多少含んだ記事になってしまったので、もしおかしい点がありましたらご指摘をお願いします。

（そもそものやり取りの詳細は、[当該記事](https://qiita.com/jnchito/items/8d8d579cdca131c0db14)のコメント欄をご参照ください）

## まず結論
伊藤さんの普段の業務では、**モデルスペックとシステムスペックを書くことがほとんど**だそうです。
一方でリクエストスペックは、アプリケーションがAPIを用意していて**API系のテストの必要がある場合に書く**とのこと。

つまり「`システムスペックとリクエストスペックはどう使い分けるの？`」という問いに、簡単に結論を出すと

- **基本、統合テストはシステムスペックを書きましょう**
- **API系のテストがあるなら、別でリクエストスペックを書きましょう**

ということになります。


## Railsチュートリアルに関して
[【動画付き】Railsチュートリアルの統合テスト(integration test)は、RSpecのリクエストスペックに置き換えるのがラクです - Qiita](https://qiita.com/jnchito/items/8d8d579cdca131c0db14)

しかし、**RailsチュートリアルのサンプルアプリにはAPIの実装がありません**。それなのに伊藤さんは↑の記事で統合テストをリクエストスペックに書き換えることをおすすめされています。なぜでしょうか？

これはRailsチュートリアルのテストがちょっと特殊というか、実務ではあまり見られない書き方になっていることが理由のようです。

### 前提知識
バージョン5.1以降のRailsが標準で備えているテスト機能に、システムテスト(SystemTestCase)と結合テスト(IntegrationTest)があるのですが（名称は[Railsガイド](https://railsguides.jp/testing.html)を準拠）、それらに対応するスペックが以下になります

システムテスト(SystemTestCase) → **システムスペック(System Spec)**
結合テスト(IntegrationTest) → **リクエストスペック(Request Spec)**

そして、対応するスペックへの変換作業というのは比較的スムーズに行うことができます。例えば、システムテストをRSpecで変換するなら**システムスペックに置き換えた方がラク**なわけです。
一方、結合テストからシステムスペックに変換するとなると、CapybaraというDSLの知識が必要であり、その分**学習コストがかかってしまいます**。

### Railsチュートリアルでは？
本来はRails標準のテストを用いる場合、実務を意識するならシステムテストを使ったほうがいいです。
しかし現在のRailsチュートリアル（第4版）では、どういうわけか**結合テストがいまだに使われている**ようです。そのため、RSpecにするなら**リクエストスペックに書き換えるほうが手間がかからない**のです。

つまり上の記事で伊藤さんが書かれていることは、

「初学者がRailsチュートリアルのテストを**ラクにRSpecで書き換えたい**のであれば、リクエストスペックを使ったほうがいいよ！もちろんシステムスペックにもできるけど、そのときは**ちょっと面倒**かもよ！」

ということだったんですね（まあ私が理解できなかっただけで、よくみるとタイトル通りなわけですが...）

### 余談
さきほども申し上げた通り、現在のRailsチュートリアルはRails5.1に対応しており、当然システムテストを使うことができるはずなのですが、依然として結合テストが採用されています。これには以下の理由があるのではと思われます（が、実際のところは不明です）

- **歴史的な経緯により、結合テストを使い続けている？**
- **（Capybaraを説明したり、Chromeのセットアップが必要になったりで）コンテンツボリュームが増えるため、初心者の負担を減らすためにあえてシステムテストを避けている？**

もしかしたら将来のアップデートでシステムテストに置き換えられる可能性があるかもしれません。

## まとめ
- 仕事あるいは自作で作っているRailsアプリケーションがあって、新しく統合テストを追加する必要があるなら、**基本的にシステムスペックを書くようにしよう！**

- RailsチュートリアルのテストをRSpecで書き直すのであれば、**手間をかけたくないならリクエストスペック**、Capybara知らないと面倒だけど**実務を意識するならシステムスペック**を使うといいよ！

## 「テスト用語に自信がない...」という人へ
この記事には以下のようなワードが登場したわけですが

**『統合（とうごう）テスト』『結合（けつごう）テスト』
『IntegrationTest』『システムテスト』
『システムスペック』『リクエストスペック』...etc**

これらをみて、ちょっと混乱してしまった方はいませんか？自分がそうでした笑

実はこれらのテスト用語についても私の方から伊藤さんに質問をしておりまして、これまた動画にて非常にわかりやすい回答を頂いております。もしそういった理由で理解が進まないのであれば、次の動画が役に立つと思うので是非ご参照下さい（これも近い内に記事にまとめるつもりです）

[【Rails】結合テストと統合テストとシステムテストは違うの？同じなの？ - YouTube![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453435/fb21d4e1-ca6a-58a9-76a6-e1e2aef2cd46.png)](https://www.youtube.com/watch?v=Em8rYg0Qvms)