自動テストコード実践編

#目次
1. はじめに
2. テストの種類
3. FactoryBot
4. 事前準備
5. テストコードの翻訳
6. createとbuild
7. テストが通る

#はじめに
私は、プログラミングをの勉強を初めてまだ2ヶ月の初心者であります。自分のアウトプットも兼ねてまだまだ技術は未熟ではありますが、私以外の初めて間もない方々の役に立つようなことができればと思いまして、投稿をさせていただきます。
今回は、テストコードを実際に書くことに関して、自分で勉強している中でわかりにくい部分が多く、まとめてみましたのでご覧になっていただければと思います。不備等ございましたら、恐れ入りますがコメントにてご指摘いただければ幸いでございます。

#テストの種類
主要なテストに関して説明致します。
###システムテスト
システムテストとは、実際の稼働環境を想定しユーザーの視点からアプリケーションの一通りの挙動をテストする手法です。
システム全体を実稼働時に近い状況で動かしつつテストする手法です。E2E(End to End)テストという言い方をすることもあるようです。

###結合テスト
結合テストとは、テスト環境においてアプリケーションの一通りの挙動をテストする手法です。この段階で、バグなどはすべて取り除かれている状態になることが求められます。

###機能テスト
機能テストとは、アプリケーションの各機能(例えば各コントローラ単位)に関してのテストのことです。
#FactoryBotとは
テストに使用するデータ作成をサポートするgemのことです。使用するデータの作り方を宣言します。
#事前準備
Gemfileに`rspec-rails`,`factory_bot_rails`のgemを追記し、bundle installをします。`rails g rspec:install`コマンドを実行し、必要なファイルを作っておきます。
#テストコードの翻訳
今回はuserモデルに関するテストを書いていきます。
先程作成したspecフォルダにfactoriesフォルダを作り、Factory_Botに関する記述をしていきます。
今回はuserのデータを作成します。

```ruby:spec/factories/users.rb
FactoryBot.define do          #FactoryBotにおいて定義します
  factory :user do            #factoryというメソッドを利用して:userという名前のUserクラスのファクトリを以下のように定義します
    nickname              {"abe"}
    password              {"00000000"}
    password_confirmation {"00000000"}
    email {"test1@example.com"}
  end
end
```

実際のテストの内容を書いていきます。
今回はツイートを投稿できるアプリケーションのテストでユーザーモデルのテストを想定して書いていきます。

```ruby:spec/models/user_spec.rb
require 'rails_helper'

describe 'ユーザー管理機能' do                  #仕様を記述するテスト対象
  context 'ユーザー作成' do                    #状況・状態の説明
    it "nicknameが空の場合登録できない" do       #期待する内容 以下に実際に期待する動作を書く
      user = FactoryBot.build(:user, nickname: nil)     #FactoryBotで作成したデータの定義、今回はnicknameを空にしたいので値を上書きする
      user.valid?                                       #バリデーションで保存ができない状態かどうかを確かめる
      expect(user.errors[:nickname]).to include("can't be blank")          #user.errorsのnicknameカラムにおいて、"can't be blank"が入ったエラー文であることを期待するというテストの成功条件に関する記述("can't be blank"は元々railsのgemで用意されているエラーメッセージ)
    end
  end
end
```
####expect(A).to eq B
エクスペクテーションの文法で、Aに入れた式がBの部分と値が等しければ、テストが成功します。
####describe
記述していく仕様が何に関してのものなのか(テストの対象)を記述します。
####content
仕様の中の状態、状況に関して記述します。これによってテストを仕様書のように見やすく整理することができます。
#createとbuild
FactoryBotのデータ作成の際のメソッドとして、createメソッドとbuildメソッドがあります。
###create
テスト用のDBに値が保存される処理が行われます。
つまり、DBにアクセスする処理(値の変更等)の際はcreateにする必要があります。注意すべき点として1回ずつテストが実行され、終了するたびに作成・変更されたDBの内容が消去されてしまいます。したがってテスト用のDBに保存された内容を確認するためには、binding.pry等でテストを一時停止させる必要があります。
###build
インスタンスを一時的に作成します。
DB上にデータを保存する処理は行いません。この部分がcreateメソッドとの大きな違いとなっています。
#テストが通る
テストをbundle exec rspecで実行してみます。
テストが無事通ればこのような記述となります。

````:terminal
ユーザー管理機能
  ユーザー作成機能
    nicknameが空の場合登録できない

Finished in 0.43078 seconds (files took 4.07 seconds to load)
1 example, 0 failures
````
１件のテストを実行して失敗が0件という意味になっています。

#参考にしたWebサイト、書籍
- 書籍
    - [現場で使える Ruby on Rails 5速習実践ガイド](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227)
- Webサイト
    - [FactoryBotにおけるcreateとbuildの違い](https://qiita.com/takutotacos/items/4a8bd25ccb42141bf67c)
    - [E2Eテストの導入から学んだこと](https://qiita.com/mt0m/items/7e18d8802843d9f60d28)
    - [機能テストについて](https://webrage.jp/techblog/functional_testing/)
    - [Markdown記法 サンプル集](https://qiita.com/tbpgr/items/989c6badefff69377da7)
    - [Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)