自宅のWindowsでRuby on Rails ~ RSpecで単体テスト

公開日: 2023/7/10 更新日: 2023/6/15

自宅のWindowsでRuby on Rails   ~ RSpecで単体テスト ~

1. 単体テストとは?


単体テストとは、ソフトウェア開発において、コードの最小単位である「ユニット(単位)」を対象に行うテストのことです。

ユニットとは、通常、関数やメソッドといった一つの機能を持った最小単位のコードのことを指します。


単体テストは、ユニットが正しく動作するかどうかを検証することで、ソフトウェアの品質を向上させるために行われます。

単体テストを行うことで、バグを早期に発見し、修正することができます。

また、単体テストは、開発の初期段階から行われることが多く、プログラマーが開発したコードの品質を保証する上でも重要な役割を果たします。


単体テストでは、ユニットが期待どおりの結果を返すかどうかを判断するために、テストデータを用いてテストを実行します。

ここで、テストデータを生成するために、FactoryBotやFakerといったGemがよく使われます。

また、テスト結果を判断するために、RSpecといったフレームワークを使用することが一般的です。

2. Railsにおける単体テスト


2-1. RSpe

RSpecは、Rubyで書かれたテストフレームワークの一つで、BDD(Behavior-Driven Development:振る舞い駆動開発)の手法を採用しています。

RSpecでは、RSpecのDSL(Domain Specific Language)を使ってテストコードを記述します。

2-2. FactoryBot

FactoryBotは、RSpecでテストデータを生成するためのGemの一つです。

FactoryBotを使うことで、テストデータを簡単に生成することができます。

また、FactoryBotを使うことで、テストデータの生成に必要なコードを一元化することができるため、テストコードの保守性が向上します。

以下がその例です。

#spec/factories/users.rb
FactoryBot.define do
  factory :user do
    email                 {Faker::Internet.free_email}
    password              {Faker::Internet.password(min_length: 6)}
    password_confirmation {password}
  end
end

#spec/factories/posts.rb
FactoryBot.define do
  factory :post do
    name {Faker::Name.name }
    content {Faker::Lorem.sentence(word_count: 10)}
    association :user
   end
end

2-3. Faker

Fakerは、テストデータの生成に必要なランダムな値を生成するためのGemの一つです。

Fakerを使うことで、テストデータを生成する際に、名前や住所、電話番号などのランダムな値を簡単に生成することができます。

2-4. モデルのテストコード例

具体的なテストコードの例として、以下のようなユーザーモデルの単体テストが考えられます。

require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'validations' do
    it 'is valid with valid attributes' do
      user = FactoryBot.build(:user)
      expect(user).to be_valid
    end

    it 'is invalid without an email' do
      user = FactoryBot.build(:user, email: nil)
      user.valid?
      expect(user.errors.full_messages).to include("Email can't be blank")
    end

    it 'is invalid with a duplicate email' do
      user1 = FactoryBot.create(:user)
      user2 = FactoryBot.build(:user, email: user1.email)
      user2.valid?
      expect(user2.errors.full_messages).to include('Email has already been taken')
    end

    it 'is invalid with a password shorter than 6 characters' do
      user = FactoryBot.build(:user, password: Faker::Internet.password(min_length: 1, max_length: 5))
      user.valid?
      expect(user.errors.full_messages).to include('Password is too short (minimum is 6 characters)')
    end
  end
end

このテストコードでは、Userモデルのバリデーションが正しく機能するかをテストしています。

各テストケースでは、FactoryBotを使ってテストデータを生成しています。また、パスワードの長さをランダムに生成するために、Fakerを使用しています。

テスト結果は、以下のようになります。


2-5. コントローラーのテストコード例

以下はコントローラーのテストコードの例です。

require 'rails_helper'

RSpec.describe "Posts", type: :request do
  before do
    @post = FactoryBot.create(:post)
    @user = FactoryBot.create(:user)
    @user.id = @post.user_id
    sign_in @user
  end

  describe 'GET #index' do
    it 'returns a success response' do
      get posts_path
      expect(response.status).to eq 200
    end
  end

  describe 'GET #show' do
    it 'returns a success response' do
      get post_path(@post)
      expect(response).to be_successful
    end
  end

  describe 'GET #edit' do
    it 'returns a success response' do
      get edit_post_path(@post)
      expect(response).to be_successful
    end
  end

  describe 'PATCH #update' do
    context 'with valid params' do
      let(:new_attributes) {
        { name: 'New Name' }
      }

      it 'updates the requested post' do
        patch post_path(@post), params: { post: new_attributes }
        @post.reload
        expect(@post.name).to eq('New Name')
      end

      it 'redirects to the post' do
        patch post_path(@post), params: { post: new_attributes }
        @post.reload
        expect(response).to redirect_to(post_path(@p

3. まとめ


近年のWebアプリケーション開発では、テスト駆動開発(TDD)やアジャイル開発の手法が注目されており、その中心にあるのが単体テストです。

単体テストは、1つの関数やクラス単位でテストを行うことで、アプリケーションのバグやエラーを事前に発見することができます。


その中でも、Rubyを使ったアプリケーション開発においてはRSpecといったテストフレームワークがよく利用されます。

RSpecは、テストの読みやすさや記述方法の柔軟性が高く、メンテナンス性も良いため、多くの開発者に愛用されています。


また、RSpecの便利な機能の1つにFactoryBotがあります。

FactoryBotは、テスト用のモデルオブジェクトを簡単に作成できるgemであり、データの生成やデフォルト値の設定などを行うことができます。

これにより、膨大なデータを用意する手間を省くことができます。


さらに、単体テストで必要となるランダムな値を生成するFakerというgemもあります。

Fakerは、名前やアドレスなど、多くの種類のデータをランダムに生成することができます。

これにより、テストの再現性を高めることができます。


モデルのテストコードでは、モデルの各メソッドが期待通りの動作をするかをテストします。

具体的には、データのバリデーション、関連するデータの取得、データの保存や削除などをテストします。

また、テストデータを生成する際に、FactoryBotやFakerを利用することで、再現性の高いテストを行うことができます。


コントローラーのテストコードでは、コントローラーの各アクションが期待通りの動作をするかをテストします。

具体的には、リクエストの送信、レスポンスの確認、テンプレートの表示、データの保存などをテストします。


テストデータを生成する際には、ロールバックという仕組みを利用することで、テストデータの保存とテストの実行が分離されるため、安全にテストを行うことができます。

このような自動化された単体テストは、アプリケーション開発において重要であり、浸透してきています。


今回は以上になります。

ありがとうございました。