はじめに
- どうも、プログラミングスクールにてRuby on Railsを勉強している、ななみんです。
未経験からのエンジニア転職に向けて今年の4月から学習を始めて、現在6ヶ月経ちました。
概要
-
Ruby
におけるBDD
(Behaviour-Driven-Development:振舞駆動開発者)のためのテスティングフレームワークRSpec
の特にSystem spec
を中心に書いています。 - スクールの課題の中で、RSpecを度々書く機会があるが、毎回新鮮な気持ちで取り組んでしまっています。(ぜーんぜん慣れない)
- 今回は、なかなか慣れてくれない自分へのメモも兼ねて、ひとまず2つ、RSpecあるあるとその対策を記事にまとめてみました。
※ 内容はかなり初歩の初歩です!
注意 💡 誤った知識を記載してしまう場合があります。
お気づきの点がありましたら、お手数ですがご教示いただけると幸いです。
それでは、RSpecあるある今から言うよ〜🎶
まずなにしたらいいかわからない(思いつかない)
-
よし、書くぞと思っても頭真っ白になりがち〜
もうなんにも出てこないんですね。テストってなんだっけ?となります。- 対策
- 一旦落ち着いて、テスト内容を箇条書きで書き出してみる!
- 例えば、こんな感じのユーザー登録のRSpecを書くぞとなったとき
# 初めのホーム画面から
# Sing upを押す
# Sing up画面へ遷移する
# Name 入れて
# Email 入れて
# Password 入れて
# Comfirmation 入れて
# Create my account 押す
# 成功! → Loginページにいる、成功しましたってメッセージ出る
# 失敗したら? → Sing upページにいる、失敗しましたってメッセージ出る
(入力フォームそれぞれの失敗パターンもありますが、割愛)
- 初めからコードで書こうとせず、実際に手動で確認する動作を文字に起こす。
- Rspecは、成功パターンと失敗パターンを書く。
ユーザー登録のテストは比較的簡単に書けそうです!
- 例えばこれが、ログインしたユーザーが投稿できるブログアプリのブログのテストを作るとなった時…
コード書いた後にテストを書く場合はController
に記載した内容を見てみるとテストすべき内容のヒントが得られそうです!
class ArticleController < ApplicationController
before_action :set_article, only: [:show, :edit, :update, :destroy
# 事前にログインしておかないといけないな…
...
def create
@article = current_user.articles.new(article_params)
# 記事内容の入力(article_params)は titelとcontentの2つの項目の入力だな…
if @article.save
redirect_to @article, notice: "記事を登録しました。"
# 内容が保存できたら、記事詳細に遷移、flashメッセージの表示がある…
else
flash.now[:danger] = "記事を登録できませんでした"
render :new
# 内容が保存できなかったら、新規作成に遷移、flashメッセージの表示がある…
end
end
...
private
def article_params
params.require(:article).permit(:title, :content)
end
def set_article
@article = current_user.articles.find(params[:id])
end
end
書き方がわからない
- テスト内容はなんとなくわかったけど、これをどうやってコードにするんだ?
どこにどうやって書けばいいか、ここでも頭真っ白になりがち〜 ですね。
例えば先ほどのユーザー登録に関するテストを作る場合、
System specの最初の画面はこんな感じですね。
require 'rails_helper'
RSpec.describe "Users", type: :system do
end
-
describe
,context
,it
RSpecを勉強し始めたら、何となくこの3つを書くということが思いつきますが、どうやって分けて書いたらいいんだ? となりました。
ざっくり役割を見るとこんな感じ!
名前 | 役割 |
---|---|
describe | テストの主題、テストの対象となる機能や処理 |
contex | 条件や状況、状態 |
it | 期待する動作、結果 |
describe
は、やさしく言い換えると「どこのテストをするの?」ということを書くといいでしょう。
例えば、ユーザーの新規登録であれば、以下のようにそのまま書けそうです。
describe 'ユーザーの新規登録' do
context
は、状況や条件なので、例えば、成功失敗パターンはここで分岐させて以下のように記載するようになります。
context 'フォームを正しく入力できた場合' do
...
context 'フォームを正しく入力できなかった場合' do
...
it
は、動いて欲しい結果を書きますので、最終的な動きを書いていきます。
it '新規登録が成功する' do
...
it '新規登録が失敗する' do
...
この3つと、先ほど文字に起こした内容をCapybaraに書き直せば、system specっぽくなりそうです!
require 'rails_helper'
RSpec.describe "Users", type: :system do
describe 'ユーザー新規登録' do
context 'フォームを正しく入力できた時' do
it '新規登録が成功する' do
visit root_path # 初めのホーム画面から
click_button 'Sing up' # Sing upを押す
visit new_user_path # Sing up画面へ遷移する
fill_in 'foo' # Name 入れて
fill_in 'example@example.com' # Email 入れて
fill_in 'password' # Password 入れて
fill_in 'password' # Comfirmation 入れて
click_button 'Create my account' # Create my account 押す
expect(page).to have_content '登録しました'
expect(current_path).to eq login_path
# 成功! → Loginページにいる、成功しましたってメッセージ出る
end
end
context 'フォームを正しく入力できなかった時' do
it '新規登録が失敗する' do
... # どこかの項目を空欄にするなどして記載する
expect(page).to have_content '登録できませんでした'
expect(current_path).to eq new_user_path
# 失敗したら? → Sing upページにいる、失敗しましたってメッセージ出る
end
end
良い感じにかけているのではないでしょうか?
慣れないうちはCapybaraの記述がパッと出てこないのでこちら伊藤淳一さんの
使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」
で探しながらコードに起こすといいかもしれません!
終わりに
- RSpecは、ひとつずつ分解して考えると難しくない! こわくない!
- 冗長になってしまっても、細かくわかりやすい方がいいとされているので、どんどん書いていきましょう!
- 他にも、
factory_bot
やlet
などのつまづきポイントがありますが、また別の機会に書いてみようと思います!
参考にした記事
https://www.wantedly.com/users/97689516/post_articles/293185
https://qiita.com/jnchito/items/42193d066bd61c740612
https://qiita.com/jnchito/items/607f956263c38a5fec24
https://qiita.com/shin1rok/items/a2c0dd6c136c1b9a8803
https://qiita.com/hawkcookie/items/d7965be4adbeb2490229