← All posts

by Sampo Kuokkanen

User avatar
Sampo Kuokkanen
Rails
2022-01-08
新しいRails 7アプリ作成したら、テストはRSpecでやる!

テストを書く

パート1はこちら 新しいRailsアプリを作ろう!オススメGem ー 合同会社Sampo Development

作成したばかりだと、テストフレームワークはMiniTestになっていて、 それをRSpecに置き換えることができます。ほとんどのプロジェクトだと RSpecを使っているかと思いますが、Rails自体はMiniTestでテストされていて、 Basecampなど有名なRailsを使っているところもMiniTestを使っています。

わかりやすでいうと、やはりRSpecはわかりやすいと思うので、今回もRSpecを使って テスト書きたいと思います。

echo 'gem "rspec-rails", group: [:development, :test]' >> Gemfile

というコマンドでRSpecをインストールします。(bundle実行は必要ですが)

# application.rb

config.generators do |g|
  g.test_framework  :rspec, fixture: false
end

application.rbでテストフレームワークをRSpecに指定します。

rails generate scaffold TimeEntry clocked_in:datetime clocked_out:datetime

今回は時間管理したいので、とりあえずTimeEntryを作成します。 これで打刻できるようにしたいです。

まだユーザーモデルなどもないので、簡単に行きましょう。 テストの設定があっているかどうかという確認にもなります。

invoke  active_record
      create    db/migrate/20220108013901_create_time_entries.rb
      create    app/models/time_entry.rb
      invoke    rspec
      create      spec/models/time_entry_spec.rb
      invoke  resource_route
       route    resources :time_entries
      invoke  scaffold_controller
      create    app/controllers/time_entries_controller.rb
      invoke    tailwindcss
      create      app/views/time_entries
      create      app/views/time_entries/index.html.erb
      create      app/views/time_entries/edit.html.erb
      create      app/views/time_entries/show.html.erb
      create      app/views/time_entries/new.html.erb
      create      app/views/time_entries/_form.html.erb
      create      app/views/time_entries/_time_entry.html.erb
      invoke    resource_route
      invoke    rspec
      create      spec/requests/time_entries_spec.rb
      create      spec/views/time_entries/edit.html.tailwindcss_spec.rb
      create      spec/views/time_entries/index.html.tailwindcss_spec.rb
      create      spec/views/time_entries/new.html.tailwindcss_spec.rb
      create      spec/views/time_entries/show.html.tailwindcss_spec.rb
      create      spec/routing/time_entries_routing_spec.rb
      invoke    helper
      create      app/helpers/time_entries_helper.rb
      invoke      rspec
      create        spec/helpers/time_entries_helper_spec.rb

といろんなファイルが作成されました。中身を確認すると、ちゃんとTailwindが使用されていて、 テストもSpecフォルダにはいって、ちゃんとRSpecで作成されています。

では、テストは少し作業が残っています。

  • あっている値
  • まちがっている値 をいれて、走らせられるようにしましょう!
# spec/models/time_entry_spec.rb
let(:valid_attributes) {
 {
 clocked_in: Time.now,
 }
}

let(:invalid_attributes) {
 {
  clocked_in: Time.now - 1.year,
 }
}

のように変更して、上は正しい値をいれて、下は間違っている値を入れます。 テストはRailsが作成してくれたままにしましょう。

bin/rails db:migrate RAILS_ENV=test でDBセットアップして、rspecコマンド実行します。

/time_entries POST /create with invalid parameters does not create a new TimeEntry

というエラーが出ましたね。 一年前の時間も打刻できてしまっています。 バリデーション追加しないといけないですね。

日付のバリデーションはこれからもいろいろやらないといけないので、 それをやりやすくするGemを導入します。

# Gemfile
gem 'validates_timeliness', '~> 6.0.0.beta2'
# インストーラー実行
rails generate validates_timeliness:install

このGemで以下のようにバリデーションを書きます。

# app/models/time_entry.rb
class TimeEntry < ApplicationRecord
  validates :clocked_in, comparison: { greater_than_or_equal_to: Proc.new { Time.zone.now - 5.minutes } }
end

Rails 7で新しく追加されたComparisonValidatorのPRを読むと、 追加の家庭もわかります。便利になりましたね。

次は翻訳も追加したいですね。。。 いわゆるI18nですね。英語で国際化の略です。

あと、エラーの場合はTurboの都合で422, unprocessable entityを返すように変わっているので、 それでテストが落ちる場合は以下のように書き換えます。

# spec/requests/time_entries_spec.rb # patch
expect(response.status).to eq(422)

これでテストが全部通るようになりました!

  • 地味にclocked_inの値の追加は何箇所かでやらないといけなかったですが。

次回は翻訳の追加ですね。

Ruby, Elixirの開発はご相談ください!

合同会社Sampo Development

sampo@sampo.ltd