by Sampo Kuokkanen
        テストを書く
パート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の値の追加は何箇所かでやらないといけなかったですが。
 
次回は翻訳の追加ですね。