初投稿です!
どうか優しい目で見てあげて下さい。お願いします!
さてさて、今回はテストコードの初歩的な事について備忘録的に書き残していこうかと思います。
フリマアプリを開発上で、商品(product)の出品時の
「必須項目が全て入力してある際は登録できる」
といったテストコードを書こうと思います!
今回登録する中身はこちら↓
###productsテーブル
カラム名 | 型 | オプション |
---|---|---|
name | string | null: false |
price | integer | null: false |
description(商品説明) | string | null: false |
status(商品の状態) | string | null: false |
size | string | null: false |
judgment | integer | |
days(発送までの日にち) | string | null: false |
cost(配送料負担者) | string | null: false |
prefecture_id | integer | null: false |
category_id | integer | null: false, foreign_key: true |
brand_id | integer | foreign_key: true |
user_id | integer | null: false, foreign_key: true |
テーブルから
name,
price,
description,
status,
size,
days,
cost,
prefecture_id,
category_id,
user_id
のカラムの値があれば登録できそう( ^ω^ )
というわけで、今回はFactoryBotを用いて、下記の様にテストコードを書きました!!
FactoryBot.define do
factory :product do #値は適当です
name {"tomato"}
price {111}
description {"aaa"}
status {"aaa"}
size {"aaa"}
days {"aaa"}
cost {"aaa"}
prefecture_id {1}
category_id {1}
user_id {1}
end
end
require 'rails_helper'
describe Product do
describe '#create' do
it "is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id" do
product = FactoryBot.build(:product)
expect(product).to be_valid
end
end
end
さてこれで、【bundle exec rspec】っと( ^ω^ )
### 結果
Product
#create
is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id (FAILED - 1)
Failures:
1) Product#create is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id
Failure/Error: expect(product).to be_valid
expected #<Product id: nil, name: "abe", price: 111, description: "aaa", status: "aaa", size: "aaa", judgment: nil, days: "aaa", cost: "aaa", prefecture_id: 1, category_id: 1, brand_id: nil, user_id: 1, created_at: nil, updated_at: nil> to be valid, but got errors: Userを入力してください, Categoryを入力してください
# ./spec/models/product_spec.rb:7:in `block (3 levels) in <top (required)>'
Finished in 0.18668 seconds (files took 3.15 seconds to load)
1 example, 1 failure
失敗( ´ ▽ ` )
エラー分を見てみると、
「UserとCategoryってどこのどいつ誰だよ!そんなのどこにもいねぇぞ!」
と怒られてます。
それもそのはず…
user_idとcategory_idを外部キーで指定しているのにその先が居ないからね…。( ˊ̱˂˃ˋ̱ )
そこで、
FactoryBotにUserとCategoryも追記します!!
まずここでUserとCategoryのテーブルを確認↓
###Usersテーブル
カラム名 | 型 | オプション |
---|---|---|
nickname | string | null: false |
string | null: false | |
encrypted_password | string | null: false |
user_image (プロフィール画像) | string | |
introduction (自己紹介) | text | |
family_name (姓) | string | null: false |
first_name (名) | string | null: false |
family_name_kana (セイ) | string | null: false |
first_name_kana (メイ) | string | null: false |
birth_day (生年月日) | date | null: false |
###Categoriesテーブル
カラム名 | 型 | オプション |
---|---|---|
name | string | null: false |
ancestry | string |
なので、FactoryBotに以下の様に追記!
# ----------追記部分ここから--------------
FactoryBot.define do
factory :user do #値は適当です
nickname {"sasa"}
email {"kkk@gmail.com"}
password {"00000000"} #登録の際に必要なので追記!
encrypted_password{"00000000"}
family_name {"sasaki"}
first_name {"goro"}
family_name_kana {"sasaki"}
first_name_kana {"goro"}
birth_day {"1990-08-24"}
end
factory :category do #値は適当です
name {"aaa"}
end
# ----------追記部分ここまで--------------
factory :product do #値は適当です
name {"tomato"}
price {111}
description {"aaa"}
status {"aaa"}
size {"aaa"}
days {"aaa"}
cost {"aaa"}
prefecture_id {1}
category_id {1}
user_id {1}
end
end
そしてuserとcategoryはこのテスト内で一旦保存されないと、
また「UserとCategoryってどこのどいつ誰だよ!そんなのどこにもいねぇぞ!」
と怒られてしまうので、
buildではなくcreateを使って行きます!!
require 'rails_helper'
describe Product do
describe '#create' do
it "is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id" do
user = create(:user)
category = create(:category)
product = FactoryBot.build(:product)
expect(product).to be_valid
end
end
end
これでいける!!
【bundle exec rspec】っと( ^ω^ )
### 結果
Product
#create
is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id (FAILED - 1)
Failures:
1) Product#create is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id
Failure/Error: expect(product).to be_valid
expected #<Product id: nil, name: "abe", price: 111, description: "aaa", status: "aaa", size: "aaa", judgment: nil, days: "aaa", cost: "aaa", prefecture_id: 1, category_id: 1, brand_id: nil, user_id: 1, created_at: nil, updated_at: nil> to be valid, but got errors: Userを入力してください, Categoryを入力してください
# ./spec/models/product_spec.rb:8:in `block (3 levels) in <top (required)>'
Finished in 0.17322 seconds (files took 2.77 seconds to load)
1 example, 1 failure
…えっ?_:(´ཀ`」 ∠):
同じエラーでとる…何故…??
もしかして、userもcategoryもcreateできてない?
と思い、【binding.pry】を【category = create(:category)】の直下に記入し、
確かめてみると、、、
Product
#create
From: /Users/hoge/Desktop/GitHub/hogehoge/spec/models/product_spec.rb @ line 7 :
2: describe Product do
3: describe '#create' do
4: it "is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id" do
5: user = create(:user)
6: category = create(:category)
=> 7: binding.pry
8: product = build(:product)
9: expect(product).to be_valid
10: end
11:
12: # it "is invalid without a name" do
[1] pry(#<RSpec::ExampleGroups::Product::Create>)> user
=> #<User id: 15, nickname: "sato", email: "kkk@gmail.com", user_image: nil, introduction: nil, family_name: "sato", first_name: "kenta", family_name_kana: "sato", first_name_kana: "kenta", birth_day: "1990-08-24", created_at: "2020-03-21 05:17:39", updated_at: "2020-03-21 05:17:39">
[2] pry(#<RSpec::ExampleGroups::Product::Create>)> category
=> #<Category:0x00007fe4caab5138 id: 7, name: "aaa", ancestry: nil, created_at: Sat, 21 Mar 2020 05:17:39 UTC +00:00, updated_at: Sat, 21 Mar 2020 05:17:39 UTC +00:00>
[3] pry(#<RSpec::ExampleGroups::Product::Create>)>
なんてことない、userとcategoryのidが違っていただけでした。( ´ ▽ ` )
そりゃ常にidが1な訳ないよね。。。
と言うことでさらにテストコードを下記の様に修正!!
require 'rails_helper'
describe Product do
describe '#create' do
it "is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id" do
user = create(:user)
category = create(:category)
#修正点!! user_id: user[:id], category_id: category[:id]を追記、これでテスト時に保存されたuserとcategoryのidが呼び出され、上書きされる
product = FactoryBot.build(:product, user_id: user[:id], category_id: category[:id])
expect(product).to be_valid
end
end
end
これでどうかな?
( ^ω^ )つ【bundle exec rspec】
### 結果
Product
#create
is valid with a name, price, description, status, size, days, cost, prefecture_id, category_id, user_id
Finished in 0.07648 seconds (files took 2.63 seconds to load)
1 example, 0 failures
無事テスト成功!!
やったぜ!✌︎('ω'✌︎ )( ✌︎'ω')✌︎
まとめ
テスト内容は単純でも、
アプリごとにテーブルなどの制約(NotNullや、外部キーなど)も異なるので、
そこに気をつけてテストコードを書いていかないと、
私の様に、テストコードの沼にハマる事になります。
この記事が少しでも初学者の役に立ちます様に。
ここまで読んでくれて
ありがとう。
また次の記事でお会いしましょう!!♪( ´θ`)ノそれでは