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の値の追加は何箇所かでやらないといけなかったですが。
次回は翻訳の追加ですね。