[Rails] Rspec基礎 導入〜model spec

Rspecについて勉強したのでアウトプットも兼ねてメモがわりとしてまとめます。

# 導入

```ruby:Gemfile
group :development, :test do
  gem "rspec-rails"
  gem 'faker'
end
```
ダミーデータ用にfakerも導入しておきます。

```:ターミナル 
$ bundle install
$ rails g rspec:install
```

以下のファイルが作成されていれば導入完了！
spec/rails_helper.rb
spec/spec_helper.rb

# 実装
### テストするアプリの概要
テストの前にテストするサンプルアプリの概要を説明します。
今回テストするサンプルアプリは`User`が`title`と`content`カラムを持つ`Article`モデルを投稿できるシンプルなものです。
`title`と`content`には両方`presence true`のvalidation制約があることにします。

それではテストを書いていきます！

### データを保存できるか
まずはデータが保存できるかを確認します。

基本的なテストの流れは、
①確認したいことを決める
②ダミーデータを作成する
③ダミーデータで①の確認したいことが起こるかどうかを確認する
です。
それに沿ってやっていきます。


その前にテストを書くファイルを作ります。

```:ターミナル 
$ rails g rspec:model post
```
作成されたファイルにテストを書いていきます。
まずはテストの流れ①の確認したいことを決めます。
テストでは`it`というところに書いていきます。

```ruby
require 'rails_helper'

RSpec.describe Article, type: :model do
  it 'タイトルと内容が入力されていれば、保存できる' do
end
```

続いて流れ②のダミーデータを作成します。
作成するダミーデータは投稿者である`User`と`title`、`content`カラムを持った`Article`です。
投稿内容はfakerを使っています。

```ruby
require 'rails_helper'

RSpec.describe Article, type: :model do
  it 'タイトルと内容が入力されていれば、保存できる' do
    user = User.create!({
      email: 'test@example.com',
      password: 'password'
    })
    article = user.articles.build({
      title: Faker::Lorem.characters(number: 5),
      content: Faker::Lorem.characters(number: 10)
    })
  end
end

```
これでダミーデータの作成がでたので、
③のダミーデータで①の確認したいことが起こるかどうかを確認します。

```ruby
require 'rails_helper'

RSpec.describe Article, type: :model do
  it 'タイトルと内容が入力されていれば、記事を保存できる' do
    user = User.create!({
      email: 'test@example.com',
      password: 'password'
    })
    article = user.articles.build({
      title: Faker::Lorem.characters(number: 5),
      content: Faker::Lorem.characters(number: 10)
    })

    expect(article).to be_valid
  end
end
```

```
expect(article).to be_valid
```
`expext`と`be_valid`はRspecが用意したメソッドで、
`article`が正しく保存されることを期待するという意味です。

ターミナルでテストを実行します。

```:ターミナル 
$ bundle exec rspec spec/models/article_spec.rb
```
成功すると以下のように出力されます。

```:ターミナル 
.

Finished in 0.01966 seconds (files took 1.02 seconds to load)
1 example, 0 failures
```
これで正しく記事が保存されることをテストできました！

### contextとbefore
`context`と`before`を使うことで前提条件を作ることができます。
ダミーデータの部分を`context`と`before`の中にまとめることで見やすくなります。
`article`の部分はインスタンス変数にすることでアクセスできます。

```ruby
require 'rails_helper'

RSpec.describe Article, type: :model do
  context 'タイトルと内容が入力されている場合' do
    before do
      user = User.create!({
        email: 'test@example.com',
        password: 'password'
      })
      @article = user.articles.build({
        title: Faker::Lorem.characters(number: 5),
        content: Faker::Lorem.characters(number: 10)
      })
    end

    it '記事を保存できる' do
      expect(@article).to be_valid
    end
  end
end
```

### let 
`let`はRspec内で使える変数のこと。
`let`で`user`と`article`のダミーデータを変数として宣言できます。
`let`を使うと`before`は使えないらしい。

```ruby 
require 'rails_helper'

RSpec.describe Article, type: :model do
  context 'タイトルと内容が入力されている場合' do

    let!(:user) do
      User.create!({
        email: 'test@example.com',
        password: 'password'
      })
    end

    let!(:article) do
      user.articles.build({
        title: Faker::Lorem.characters(number: 5),
        content: Faker::Lorem.characters(number: 10)
      })
    end

    it '記事を保存できる' do
      expect(article).to be_valid
    end
  end
end

```

ざっとですがこんな感じです。
テストの基本の流れが掴めればあとは反復あるのみって感じですね！

テスト実行時にエラーが出た場合は以下の記事を参考にしてください。


https://qiita.com/aaaasahi_17/items/614e80af679ddf314426