Rails テスト

#前提
本日学んだことを書いていきます。

#本題

#単体テスト

RSpecをインストール

```
#省略

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

  gem 'rspec-rails', '~> 3.8' #追記
  gem 'factory_bot_rails', '~> 5.0' #追記

end

# 省略
```
```
$ bundle install
```
Rspec・FactoryBotがインストールされているか確認

```
$ bundle exec rspec --version
$ bundle exec gem list | grep factory_bot_rails
```

アプリのプロジェクトにRSpecを導入

```
$ rails g rspec:install
```
テスト用のDBを最新の構成にする

```
$ rails db:migrate:reset RAILS_ENV=test
```
テスト用のDBとは自動テストを実行するときに利用する専用のDB
例えば自動テストで「全データが消えること」を確認するとき、開発中に利用しているデータが消えてしまっては困る
開発中のデータと自動テスト用のデータを分離して考えることで、双方が干渉しないようになる

モデルのテストコードを追加

```
$ rails g rspec:model モデル名
```

テスト実行コマンド

```
$ bundle exec rspec
```


###RSpecでテストケースを識別するための3つのキーワード

・describe
正常系の機能
大分類のようなイメージで何についてテストをするかを記述する

・context
回答する
中分類のようなイメージで状況を記述する

・it
正しく登録できること
個々のテストケースを表し、期待する振る舞いを記述する


```
enquete = FoodEnquete.new(
          name: '田中 太郎',
          mail: 'taro.tanaka@example.com',
          age: 25,
          food_id: 2,
          score: 3,
          request: 'おいしかったです。',
          present_id: 1
        )

# バリデーションが通ること(バリデーションエラーが無いこと)を検証
expect(enquete).to be_valid

```

※Rails 5.2以降のRSpecではテストコードの実行が終了すると、DBの状態を元に戻してくれる


```
$ bundle exec rspec spec/models/〜.rb
.

Finished in 0.03355 seconds (files took 2.24 seconds to load)
1 example, 0 failures
```
実行結果の1行目に記号やアルファベットで結果が表示される

<code>.</code>成功 テストコードの想定通りに動作した
<code>F</code>失敗 テストコードの想定通りに操作しなかった

```
# true/falseのような真偽値を検証する時、be_truthy/be_falseyをマッチャーとする
expect(new_enquete.save).to be_falsey
```


```_enquetes.rb
FactoryBot.define do
  factory :food_enquete do

    name { '田中 太郎' }
    mail { 'taro.tanaka@example.com' }
    age { 25 }
    food_id { 2 }
    score { 3 }
    request { 'おいしかったです。' }
    present_id { 1 }

  end
end
```

```_enquete_spec.rb
# FactoryBot.build(クラス名)
enquete = FactoryBot.build(:food_enquete)
```

FactoryBot.create(クラス名)を呼出すと「田中 太郎」のテストデータが作成、さらにテストデータがDBへ保存される
つまり、.saveが不要になる

```
FactoryBot.create(:food_enquete)
```

FactoryBot.build(クラス名, 上書きしたい項目: XX)を呼出すと「田中 太郎」のテストデータが作成される
ここでは「お召し上がりになった料理」「満足度」「希望するプレゼント」「ご意見・ご要望」を上書きしている

```
re_enquete_tanaka = FactoryBot.build(:food_enquete, food_id: 0, score: 1, present_id: 0, request: "スープがぬるかった")
```

```_enquete_spec.rb
# このテストコードでは、各テストケースの前処理として「田中 太郎」のテストデータを作成する
before do
  FactoryBot.create(:food_enquete_tanaka)
end
```

```_enquete_spec.rb
# インスタンスを共通化してテストデータを作成
let(:new_enquete) { FoodEnquete.new }
```

共通メソッドのテストコードのファイルを認識させる
モデルのテストコードを書くためのファイルは<code>rails g rspec:model</code>で準備したが、共通メソッドは手動で用意する
RSpecが手動で作成するテストコードのファイルを認識するように設定を修正する
以下のテストコードのモデルのインスタンスを共通化
まずは修正前のテストコードを確認

```spec/rails_helper.rb
# 省略

# コメントアウトを解除する
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

# 省略
```

共通メソッドのテストコードのファイルを追加
<code>spec/support/concerns/common_modules.rb</code>にテストコードを追加

共通のテストコードを定義するときは<code>shared_examples</code>を利用し、その中にテストコードを書く


```_enquete_spec.rb
# 共通のテストコードを呼出すときはit_behaves_likeを利用
it_behaves_like '価格の表示'
```

#統合テスト

capybara
統合テスト（E2E）のフレームワーク
Rspecと連携してWEBブラウザの自動操作を支援する

selenium-webdriver
capybaraを通じてWEBブラウザを自動で操作する

webdrivers
GoogleChromeを操作するドライバ

```Gemfile.
group :test do
  gem 'capybara', '~> 3.28'
  gem 'selenium-webdriver', '~> 3.142'
  gem 'webdrivers', '~> 4.1'
end
```

```terminal.
$ bundle install
```

インストールされているか確認

```
$ bundle exec gem list | grep -e capybara -e selenium-webdriver  -e webdrivers
capybara (3.32.2)
selenium-webdriver (3.142.7)
webdrivers (4.3.0)
```

<code>spec_helper.rb</code>の修正

```spec_helper.rb
# 省略

require 'capybara/rspec' #追記

RSpec.configure do |config|

  # ブラウザにChromeを指定（以下追記）
  config.before(:each, type: :system) do
    driven_by :selenium, using: :chrome, screen_size: [1280, 960]
  end


  # 省略

end
```
※Chromeを1280px × 960pxのウィンドウサイズで開いて操作


追記
<code>--skip-test</code>
デフォルトのテストフレームワークを作成しない

<code>--skip-coffee</code>
CoffeeSprictを使用しない