テストコードについて(Ruby on Rails)

今回は、Ruby on Railsのテストコードについての記事を書きたいと思います。

## バージョン
・Ruby 2.6.5
・Rails 6.0.0

## テストコードとは?

・テストコードとは?
テストコードとは、アプリケーションの動作確認をする際にかくコードです。
アプリケーションを作成したら、新規登録やログインができるか手動で確認する
と思います。
これを、コードを書いて自動で実行できるのがテストコードです。

■なぜ、テストコードは必要?
①クオリティの担保ができる
もし、手動で挙動を確認するとデメリットが多い。
・人為的ミスが起きる
・仕様が変わった時に、もう一度やらなくてはいけない
・記録が残らない
こういったデメリットを回避できてクオリティを担保できる。

②仕様を見極めることができる
テストコードをかける人は、そのアプリケーションの仕様を理解している。

テストコードで大事なのは「何を確認したいのか意識する」

## テストコードのパターンと種類
■パターン
・正常系
「ユーザーが開発者の意図する挙動を行った時の挙動」を確認するテストコード。
つまりは、「ログインできる時」など上手くいった時の確認。

・異常系
「ユーザーが開発者の意図しない操作を行った時の挙動」を確認するテストコード。
例えば、新規登録の際に「フォーム空欄だと登録できない」などを確認する。

※その他にも準正常系など様々な分類があります。

■種類
・単体テストコード
モデルやコントローラーなど機能ごとに問題がないかを確かめる。
モデルの場合バリデーションの確認などを行う。
例えば、「パスワードを英数混合」のバリデーションを設定していたらその挙動を
確認する。

## Gemの導入
railsでテストコードを行うには、RspecのGemの導入が必要。

Gemfile

```ruby
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', '~> 4.0.0'
end
```

Gemfileのgroup :development, :test doの中に記述を行う。

```
% bundle install
```

```
 % rails g rspec:install
```
Gemのインストールを行った後に、rails gでrspecをインストールを行う。

```
create  .rspec
create  spec
create  spec/spec_helper.rb
create  spec/rails_helper.rb
```
すると上記のファイルが作成される。

.rspec

```
--format documentation
```
作成され.rspecファイルに上記を記述する。
これは、テストコードの結果をターミナル上に可視化するための記述。

これで、rspecの導入は完了したので、あとはファイルを作成してコードを書くだけです。

ちなみにテストファイルの生成の仕方は、

```
% rails g rspec:model user
```
ターミナルより上記のコマンドを実行するとファイルが生成でsきます。
これは、userモデルの単体テストコードのファイルを作成したものです。

ちなみにこれは、単体テストコードの場合で、次に結合テストの場合について。

##  結合テストの場合についての準備
結合テストの場合は、System Specという技術を使用します。
これは、CapybaraというGemを用い流のですが、このGemはデフォルトで
導入されています。

Gemfile

```ruby
group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of web drivers to run system tests with browsers
  gem 'webdrivers'
end
```
Gemfileを見ると導入されていることが確認できます。

```
% rails g rspec:system users
```
ターミナルよりファイルを作成。
これは、userの結合テストコードのファイルです。
つまり、「新規登録」や「ログイン」機能のテストを行うものです。

ここまでが、テストコードの説明と導入手順の流れです。

## 効率よくテストコードを書くために

テストコードを効率よく書くために、導入するGemが
FactoryBotとFakerです。

・FactoryBot
インスタンスをまとめることができるGemです。他のファイルであらかじめ各クラスのインスタンスに定める値を設定しておき、各テストコードで使用します。

```ruby
RSpec.describe User, type: :model do
  describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
      user = User.new(nickname: '', email: 'test@example', password: '000000', password_confirmation: '000000')
      user.valid?
      expect(user.errors.full_messages).to include("Nickname can't be blank")
    end
  end
end
```
これが、FactoryBotを使わずに書いたテストコードです。
テストを行うたびにインスタンスを生成しなくてはいけません。
別のファイルにあらかじめインスタンスを作成し、再度利用するのがFactoryBotの役目です。

Gemfile

```ruby
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', '~> 4.0.0'
  gem 'factory_bot_rails'
  gem 'faker'
end
```
Gemfileのgroup :development, :test doの中に記述します(Fakerも記述しています。)
記述を行ったら、

```
% bundle install
```
これで、導入完了です。
「factories」というフォルダができるので、その中にファイルを作成します。
factoriesというフォルダができていない場合は手動で作成してください。

spec/factories/users.rb

```ruby
 FactoryBot.define do
  factory :user do
      nickname               {"test"}
      email                  {"test@test"}
      password               {'test1234'}
      password_confirmation  {password}
      profile                {"よろしくお願いします"}
  
```
このようにそれぞれのインスタンスをあらかじめ作成しておきます。

```ruby
RSpec.describe User, type: :model do
  before do
    @user = FactoryBot.build(:user)
  end

  describe "新規登録" do
    context "登録できる時" do
      it "プロフィール写真以外の情報が入力されていれば登録できる" do
        expect(@user).to be_valid
      end

      it "プロフィール写真がなくても登録できる" do
        @user.image = nil
        expect(@user).to be_valid
      end
    end
    context "登録できない時" do
      it "emailがないと登録できない" do
        @user.email = nil
        @user.valid?
        expect(@user.errors.full_messages).to include("Email can't be blank")
      end
```
このように、beforeであらかじめセットアップしておくと、各項目で使えるようになります。
例えば、"登録できるとき"の"プロフィール写真以外の情報が入力されていれば登録できる"
はあらかじめ、@userの中にFactoryBotの情報が入っているため、これだけの記述で済みます。

・Faker
ランダムな値を生成するGemです。メールアドレス、人名、パスワードなど、さまざまな意図に応じたランダムな値を生成してくれます。

Fakerを使用すると、名前やemailなどをランダムに生成してくれます。
同じ情報が登録できないようなバリデーションを組んでいる時なんかに使います。
導入の仕方は、先ほどと同じで導入が済んだら、

spec/factories/users.rb

```ruby
FactoryBot.define do
  factory :user do
      nickname               {Faker::Name}
      email                  {Faker::Internet.free_email}
      password               {'test1234'}
      password_confirmation  {password}
      profile                {"よろしくお願いします"}
 
  end
end
```
FactoryBotのファイルにFakerを使用したい部分に記述します。
今回だと、emailとnicknameを自動生成しました。

他にもいろんなものが生成できるので、興味ある方はこちらを参考してください。
[Fakerの公式GitHub](https://github.com/faker-ruby/faker)

ここまでが、テストコードに関しての説明です。
オリジナルアプリに、テストコードを書くことでより理解が深まりました。

初心者のため、記事に不備があるかもしれません。
その際は、コメントしていただければ幸いです。