テストコードについて学んだので、まとめ。
今回はRspecを導入した時のコードの作り方について。
Gemfileの準備
group :development, :test do
gem 'rspec-rails'
gem 'rails-controller-testing'
gem 'factory_bot_rails'
end
group :test do
gem 'faker'
end
rspec-rails
テストコードを書くためのGem
rails-controller-testing
コントローラーをテストするためのGem
factory_bot_rails
テストコードを書く際に、インスタンス変数を別ファイルにまとめておくためのGem。
テストコードが長くなるほど、繰り返しパラメーターを書かなければならないので、便利。
faker
インスタンス変数をランダムで作成してくれるgem。デフォルトでは一意性は保証されていないので、設定が必要。
名前やアドレスだけでなく、住所や大学などさまざまな値をランダムで作成可能。
以上のGemを記述したら、bundle installし、RSpecの設定ファイルを作成するためにrails g rspec:installを実行。
$ bundle install
$rails g rspec:install
RSpecのセットアップ
.rspecファイルに以下の記述をすると、テスト結果が読みやすくなります
--format documantation
$ bundle exec rspec spec/controllers/tweets_controller_spec.rb
# --format documatationありの場合
TweetsController
GET #new
renders the :new template
GET #edit
assigns the requested contact to @user
renders the :edit template (FAILED - 1)
GET #index
populates an array of tweets ordered by created_at DESC
renders the :index template
# 〜省略〜
# --format documatation無しの場合
..F..
# 「.」はテストをパスして、「F」はテストに失敗していることを示している
# 〜省略〜
〜省略〜部分は共通で、テスト結果を羅列する時に簡略化しているところを、きちんと文章で教えてくれます。が、テストの数が多くなると、ターミナルを結果が埋め尽くしてしまうので、好みで使い分けてください。筆者はつけなくてもいいかなと思います。
Fakerを使ったテスト用アカウント・ツイートの作成
Fakerを使うと様々なデータに対して、ランダムにデータ生成してくれます。例えば、今回はテスト環境にFakerを導入したので、テスト環境を立ち上げて、Faker::使いたいデータ.オプション(詳しくはhttps://github.com/stympy/faker)を使ってみると。
$ rails c -e test
[1] pry(main)> Faker::Name.name
=> "Roma Halvorson"
[2] pry(main)> Faker::Name.name
=> "Ms. Nicolle Kling"
[3] pry(main)> Faker::Name.name
=> "Janae Considine Sr."
このようにランダムで名前が生成されました。これを利用して、userとtweetをランダムで作成してもらいます。
specディレクトリ以下に、factoriesのフォルダを作成し、その中にusers.rbとtweets.rbを作成して、以下の内容を記載します。
せっかくなので、いろいろランダムで作ってもらいましょう。(きっとFakerの作者はハリー・ポッターが好きなのでしょう。)
FactoryBot.define do
factory :user do
name {Faker::Movies::HarryPotter.character}
password {"00000000"}
password_confirmation {"00000000"}
sequence(:email) {Faker::Internet.unique.email}
end
end
# Faker::Movies::HarryPotter.character ハリーポッターのキャラをランダムで生成してくれるメソッド
# Faker::Internet.email emailアドレスをランダムで生成してくれるメソッド。観察した範囲では○○○@○○.○○という形式で作成してくれる
# メソッドの前にuniqueを入れると、一意性が保たれるので、uniqueness: trueのテストができるようになります。
これで、仮想のデータは作成できました。最後にrails_helper.rbに記述省略を指定しましょう
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
# 上の設定をしておくとテストコードの中で
user = FactoryBot.create(:user)
# この記述を
user = build(:user)
# このようにスッキリかける
テストコードの作成
大前提として、userモデルの設定は以下のようにしておきます。
class User < ApplicationRecord
validates :name, presence: true
validates :email, uniqueness: true
end
その上で、テストコードを描きましょう。
require 'rails_helper'
# rails_helperを呼び出し
# describe User do~endの間にコントローラーごとのテストを記述
describe モデル名 do
describe '#コントローラー名' do
it "テストしたい内容と結果がどうなるかを記述。日本語OK" do
#メソッドを記述して、結果がどうなるかを記述する
end
#例
it "is invalid when same email exists 重複したemailを登録しようとすると無効になる" do
user1 = create(:user, email: "example@example.com") #(create(:user)でユーザーをデータベースに仮保存して、emailを指定)
user2 = build(:user, name: "sato", email: "example@example.com") #(buildで同じemailのユーザーを作るが、まだデータベースに保存してない)
user2.valid? #(user2が有効であるかを判定する)
expect(user2.errors[:email]).to include("has already been taken")
end
end
end
$ bundle exec rspec spec/controllers/テスト名.rb
これで簡単にですが、テストができました。