FactoryGirlを追加した
いつもの、ごみシリーズです。
今週土日は、自分の所属しているバドミントンクラブのHPの作成で終わってしまいました。 デザイン難しい。
さて、今回は前回 RspecでHTTPのリクエスト・レスポンスのテストを行った - takapi86のブログ で追加したテストに、テストデータを追加していきます。
こちらを参考に導入を行いました。
File: GETTING_STARTED — Documentation for factory_girl (4.8.0)
導入
Gemfile
にfactory_girl_rails
を追加して、bundle install
します。
group :test do gem 'factory_girl_rails' end
- factory_girlのテストデータを作成するコードを保管する場所として、
spec/factories/
を作成しておきます。
ファイルを作成する
区モデル(ward)、町モデル(town)のFactoryGirlファイルを作成します。 ※ward、townは1:nの関係です。
詳しくは、
- spec/factories/wards.rbを作成
FactoryGirl.define do factory :ward do # モデル名を指定 sequence(:id) ward_code 16 name '港北区' end end
- spec/factories/towns.rbを作成
FactoryGirl.define do factory :town do # モデル名を指定 sequence(:id) ward_code 16 initial_code 3 town_code 1073 name '篠原町' end end
試してみる
- test環境にコンソールで入ります。
RAILS_ENV=test bundle exec rails c
wardのデータを作ってみる
[1] pry(main)> ward = FactoryGirl.create(:ward) (0.1ms) begin transaction SQL (0.4ms) INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["id", 1], ["ward_code", 16], ["name", "港北区"], ["created_at", 2017-03-26 14:57:30 UTC], ["updated_at", 2017-03-26 14:57:30 UTC]] (145.8ms) commit transaction => #<Ward:0x00559a99c3ccb8 id: 1, ward_code: 16, name: "港北区", created_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:57:30 UTC +00:00>
townのデータを作ってみる
[2] pry(main)> FactoryGirl.create(:town, ward: ward) (0.1ms) begin transaction SQL (0.3ms) INSERT INTO "towns" ("id", "ward_code", "initial_code", "town_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["id", 1], ["ward_code", 2], ["initial_code", 3], ["town_code", 1073], ["name", "篠原町"], ["created_at", 2017-03-26 14:59:00 UTC], ["updated_at", 2017-03-26 14:59:00 UTC]] (60.9ms) commit transaction => #<Town:0x00559a9daa47f8 id: 1, ward_code: 2, initial_code: 3, town_code: 1073, name: "篠原町", created_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00, updated_at: Sun, 26 Mar 2017 14:59:00 UTC +00:00>
うまくいったっぽいです。 念の為、testのDBはクリアしておきます。
RAILS_ENV=test bundle exec rake db:migrate:reset
前回のテストに追加
require 'rails_helper' RSpec.describe TownsController, type: :request, json: true do let(:town) { FactoryGirl.create(:town, ward: create(:ward)) } describe 'GET /towns/:name.json' do before do get URI.escape("/towns/#{town.name}.json") end it '200 OK を返す' do expect(response.status).to eq(200) end end end
こちらもうまくいったようです。
ちなみに、ここではFactoryGirl.create
と記載していますが、クラス名は、
spec_helper.rbの Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
のコメントを外し、以下のようにファイルを追加するか、そのままconfig.include FactoryGirl::Syntax::Methods
と追記することで、省略できます。
# spec/support/factory_girl.rb RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods end
ただ、このままでは2回目実行すると、以下のようなエラーが発生してしまうようです。
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: wards.id: INSERT INTO "wards" ("id", "ward_code", "name", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>' # ./spec/requests/towns_spec.rb:7:in `block (3 levels) in <top (required)>' # ------------------ # --- Caused by: --- # SQLite3::ConstraintException: # UNIQUE constraint failed: wards.id # ./spec/requests/towns_spec.rb:2:in `block (2 levels) in <top (required)>'
どうやら、続けてテストする場合は、テスト後にテストしたデータを削除する処理を入れる必要があるようです。 こちらは、次回対応していきたいと思います。