テストコードの作成について

テストコードについて学んだので、まとめ。
今回はRspecを導入した時のコードの作り方について。

#Gemfileの準備

```ruby:Gemfile.rb
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を実行。

```terminal
$ bundle install
$rails g rspec:install
```

#RSpecのセットアップ
.rspecファイルに以下の記述をすると、テスト結果が読みやすくなります

```ruby:rspec
--format documantation
```

```terminal
$ 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)を使ってみると。

```terminal
$ 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の作者はハリー・ポッターが好きなのでしょう。）

```ruyby:spec/factories/users.rb
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に記述省略を指定しましょう

```ruby:rails_helper.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
```

```ruby:user_spec.rb
#上の設定をしておくとテストコードの中で
user = FactoryBot.create(:user)
#この記述を
user = build(:user)
#このようにスッキリかける
```

##テストコードの作成
大前提として、userモデルの設定は以下のようにしておきます。

```ruby:user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, uniqueness: true
end
```

その上で、テストコードを描きましょう。

```ruby:テスト名.rb
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
```

```terminal
$ bundle exec rspec spec/controllers/テスト名.rb
```

これで簡単にですが、テストができました。