🎃

RSpecの導入と使い方

2024/05/22に公開

はじめに

Ruby, RailsのテストツールのRspecの導入と簡単な使い方までの紹介です。

動作環境

Rails 7+MySQLのDocker環境構築Ridgepoleの導入と使い方で構築した環境を使います。
Ruby 3.2.2
Rails 7.0.8
MySQL 8.0

RSpec

RSpecとは、Ruby/Rails アプリケーションをテストするための一般的な動作駆動型開発 (BDD) フレームワークです。

Gemfileにrspec-railsを追加して bundle installをします。

api/Gemfile
group :development, :test do
+ gem "rspec-rails"
end
ターミナル
docker compose run --rm api bundle install
docker compose build api # イメージの再構築

設定ファイルの準備

ターミナル
docker compose run --rm api bundle exec rails g rspec:install
# 実行結果
  create  .rspec
  create  spec
  create  spec/spec_helper.rb
  create  spec/rails_helper.rb

spec_helperの下記部分のコメントアウトを外し、実行ファイルが一つの場合自動でdocumentationオプションが付与されるようにします。

api/spec/spec_helper.rb
  if config.files_to_run.one?
    # Use the documentation formatter for detailed output,
    # unless a formatter has already been configured
    # (e.g. via a command-line flag).
    config.default_formatter = "doc"
  end

factory_bot_rails

FactoryBotは、Ruby on Railsアプリケーションでテストデータを作成するためのライブラリであり、特にオブジェクト生成に関する煩雑さを軽減するために使用されます。factory_bot_railsは、FactoryBotをRailsプロジェクトに統合するためのgemです。

Gemfileにfactory_bot_railsを追加して bundle installをします。

api/Gemfile
group :development, :test do
  gem "rspec-rails"
+ gem "factory_bot_rails"
end
ターミナル
docker compose run --rm api bundle install
docker compose build api # イメージの再構築

テストコードで FactoryBot のメソッドを使う際、モジュール名 (FactoryBot)を省略できるようするため、rails_helper.rbに以下を追記します。

api/spec/rails_helper.rb
  RSpec.configure do |config|
+   config.include FactoryBot::Syntax::Methods
  end

使い方

Schemafileの変更

名前を姓と名を持つカラムに変更します。

api/db/schemas/users.schema.rb
create_table :users, force: :cascade, charset: 'utf8mb4', collation: 'utf8mb4_bin', options: 'ENGINE=InnoDB ROW_FORMAT=DYNAMIC' do |t|
-   t.string  :name, null: false, default: ''
+   t.string :first_name, null: false, default: ''
+   t.string :last_name, null: false, default: ''
    t.integer :age,  null: false, default: 20

    t.timestamps
-   t.index :name, name: 'index_users_on_name'
+   t.index :first_name, name: 'index_users_on_first_name'
+   t.index :last_name, name: 'index_users_on_last_name'
  en

データベースの準備

ターミナル
docker compose run --rm api bundle exec rails db:create RAILS_ENV=test
docker compose run --rm api bundle exec rails db_migration:apply RAILS_ENV=test

modelの準備

api/app/models/user.rb
class User < ApplicationRecord
  def full_name
    "#{first_name} #{last_name}"
  end
end

FactoryBotのファイル準備

ターミナル
docker compose run --rm api bundle exec rails g factory_bot:model user
# 実行結果
      create  spec/factories/users.rb
api/spec/factories/users.rb
FactoryBot.define do
  factory :user do
    first_name { 'Yamada' }
    last_name { 'Taro' }
    age { 10 }
  end
end

Specファイルの準備

ターミナル
docker compose run --rm api bundle exec rails g rspec:model user
# 実行結果
      create  spec/models/user_spec.rb
      invoke  factory_bot
   identical    spec/factories/users.rb
api/spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  let!(:user) { create(:user, first_name: "Suzuki", last_name: "Jiro") }
  describe "User#full_name" do
    it '"first_name last_name"が返ってくる' do
      expect(user.full_name).to eq "#{user.first_name} #{user.last_name}"
    end
  end
end

実行

ターミナル
docker compose run --rm api bundle exec rspec 
# 実行結果
User
  User#full_name
    "first_name last_name"が返ってくる

Finished in 0.10496 seconds (files took 0.97435 seconds to load)
1 example, 0 failures

Github ActionsでRSpecを実行する

.github/workflows/api_rspec.ymlを追加してGithub Actionsで実行するようにします。

ターミナル
mkdir -p .github/workflows
touch .github/workflows/api_rspec.yml
.github/workflows/api_rspec.yml
name: Run RSpec
on:
  push:
    paths:
      - 'api/**'
jobs:
  rspec:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    env:
      MYSQL_HOST: 127.0.0.1
    services:
      mysql:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ROOT_PASSWORD: "${{ secrets.MYSQL_PASSWORD }}"
        options: >-
          --health-cmd "mysqladmin ping"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
    - name: Set up Ruby
      uses: ruby/setup-ruby@v1
      with:
        working-directory: api
        ruby-version: '3.2.2'
        bundler-cache: true
    - name: Initialize Database
      working-directory: api
      run: |
        bundle exec rails db:create RAILS_ENV=test
        bundle exec rails db_migration:apply RAILS_ENV=test
    - name: Run RSpec
      working-directory: api
      run: bundle exec rspec

MySQLのroot passwordはsecretを使用します

Discussion