【Ruby on Rails】RSpecでのviewのテスト

# 開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

# 前提
こちらが出来ている前提で進めます。
[【Ruby on Rails】RSpec導入まで](https://qiita.com/japwork/items/2a499c5f09cd53838d84)




モデルのテストはこちら
[【Ruby on Rails】RSpecでのモデルテスト](https://qiita.com/japwork/items/c6f58bae5e0b222e1eb0)

コントローラーのテストはこちら
[【Ruby on Rails】RSpecでのコントローラーテスト](https://qiita.com/japwork/items/8006b8631c03f3ca0052)

# viewのテスト準備

##・ファイルの作成
①
spec配下にsystemフォルダとfactoriesフォルダを作成。
systemフォルダには、テストしたいviewのファイルも作成し、
factoriesフォルダにはダミーデータのモデルを作成します。

今回はpostのviewをテストするため、
下記のようなファイル構成にします。

```
spec/system/post_spec.rb
　→テストしたい内容を記述します。

spec/factories/post.rb
spec/factories/user.rb
　→ダミーデータを作成します。
```

②
FactoryBotを使えるようにします。
使用するとuser = create(:user) のようにDB登録やモデルのビルドができるため便利です。
spec配下にsupportフォルダとfactory_bot.rbファイルを作成し、下記のように記述します。

```rb:spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
```
その後、下記を追加します。

```rb:spec/rails_helper.rb
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot' # ＜ーーー　追加

...

```
## spec_helper.rbの編集
下記内容をRSpec.configure do |config|内に追加します。

```rb:spec/spec_helper.rb
RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :rack_test
  end

...

end
```

# 実際のコード
まずはダミーデータを作成します。

```rb:spec/factories/user.rb
FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    phone_number { 12345678909 }
    password { 'password' }
    password_confirmation { 'password' }
  end
end
```
```rb:spec/factories/post.rb
FactoryBot.define do
  factory :post do
    body { Faker::Lorem.characters(number:20) }
    user
  end
end
```

次にテストコードを記述します。

```rb:spec/system/post_spec.rb
require 'rails_helper'

describe '投稿のテスト' do
  let(:user) { create(:user) }
  let(:user2) { create(:user) }
  let(:post) { create(:post, user: user) }
  let(:post2) { create(:post, user: user2) }
  before do
    visit new_user_session_path
    fill_in 'user[email]', with: user.email
    fill_in 'user[password]', with: user.password
    click_button 'ログイン'
    visit user_posts_path(user, post)
  end
  describe '表示のテスト' do
    context '新規投稿画面' do
      before do
        visit new_user_post_path(user, post)
      end
      it 'bodyフォームが表示される' do
        expect(page).to have_field 'post[body]'
      end
      it '新規投稿ボタンが表示される' do
        expect(page).to have_button '新規投稿'
      end
    end
  end
  describe '編集のテスト' do
    context '自分の投稿の編集画面への遷移' do
      it '遷移できる' do
        visit edit_user_post_path(user, post)
        expect(current_path).to eq('/users/' + user.id.to_s + '/posts/' + post.id.to_s + '/edit')
      end
    end
    context '他人の投稿の編集画面への遷移' do
      it '遷移できない' do
        visit edit_user_post_path(user, post2)
        expect(current_path).to eq('/users/' + user.id.to_s + '/posts')
      end
    end
  end
end
```

その後、ターミナルで下記を実行してください。

```:ターミナル
$ rspec spec/requests
```
エラーが出る場合はこちらも試してみてください

```:ターミナル
$ bundle exec rspec spec/system --format documentation
```

テストを通過すると

```
Finished in 3.64 seconds (files took 2.75 seconds to load)
4 examples, 0 failures
```

このように表示されるためテスト内容が正しいことを表しています。

## 参考（モデルのテストから抜粋）
[【Ruby on Rails】RSpecでのモデルテスト](https://qiita.com/japwork/items/c6f58bae5e0b222e1eb0)
逆にテストを通過しない場合、このような形でどこでエラーが起きているかわかるので、
テストコードが間違っているのか、バリデーションが間違っているかなどがわかるようになります。

```
Failures:

  1) Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x000000000619e938>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'

  2) Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと
     Failure/Error: let!(:post) { build(:post) }

     NoMethodError:
       undefined method `build' for #<RSpec::ExampleGroups::Post::Nested::Title:0x0000000007491518>
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.07992 seconds (files took 2.41 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./spec/models/post_spec.rb:11 # Postモデルのテスト バリデーションのテスト titleカラム 20文字以下であること
rspec ./spec/models/post_spec.rb:15 # Postモデルのテスト バリデーションのテスト titleカラム 空欄でないこと
```

また下部にあるrspec ./spec/models/post_spec.rb:11を使い、
下記のように個別にテスト内容を確認することも出来ます。

```:ターミナル
$ rspec spec/models/post_spec.rb:11
```

# まとめ
今回は
まずはダミーデータを作成し、
ログイン画面で実際にログインをした後、
１，ログインした状態で投稿画面にいき、表示が正しくされているか
２，他人の投稿画面に遷移できないか
この２点をテストしました。

javascriptのテストをする方法もあるため
興味のある方は調べてみてください。


またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら　https://twitter.com/japwork