Rspecでテストコード を書く② 〜テストの準備とProjectモデル編〜
TECH::CAMP卒業まであと20日となりました。
今日は、前回書いたテストコード についての記事の続きを書こうと思います。
前回テストを通したuserモデルとアソシエーションを組んでいる、projectモデルというものをテストしようと思います。
作業の前に
- gemのインストール
group :test do gem 'rspec-rails' gem 'factory_bot_rails' gem 'faker', "~> 2.8" gem 'rails-controller-testing' #コントローラーのテストをする場合 end
- specディレクトリの作成(コマンド)
$ rails g spec:install
- .rspec ファイルへの追記
--format documentation
- rails.helper.rb ファイルへの追記
RSpec.configure do |config| config.include FactoryBot::Syntax::Methods #ここを追記 #省略 end
DB design
DB設計は下記の通り。アソシエーションも記載しています。
- users table
Column | Type | Options |
username | string | null: false |
string | null: false, unique: true | |
password_digest | string | null: false |
- Association
- has many projects
- projects table
Column | Type | Options |
name | string | null: false |
user_id | integer | null: false, foreign_ley: true |
- Association
- belongs_to user
- belongs_to user
FactoryBotの準備
アソシエーションからわかることとして、
projectはuserに依存している = userの情報がないと、projectが作られないのです。
これはテストの世界でも一緒です。
なので、「projectを保存できる」という条件でテストを通すためには、
事前にFactoryBotで、userの情報と、userの情報を入れたprojectの情報を作ってやる必要があります。
- spec/factories/user.rb
FactoryBot.define do factory :user do password = Faker::Internet.password(min_length:8) username {"username"} email {Faker::Internet.email} password {password} password_confirmation {password} end end
- spec/factories/project.rb
FactoryBot.define do factory :project do name {"project"} user end end
projectモデルのFactoryBotに上記のように「user」と記載することで、
FactoryBotで作ったuserの情報が入るようになっています。
ただ、ユーザーの情報が入るカラムが2つあったりする場合は、この方法だとうまくいきませんでした。
その場合はprojectsモデルのFactoryBotにはuserとは書かず、
rspecで
user = create(:user) project = build(:project, user_id: user.id)
という風に、userを生成のうえ、そのユーザーはprojectsテーブルのどのカラムに入るのかを指定してやるとうまくいきました。
rspecを書く
では、rspecのテストコードを書いていきましょう!require 'rails_helper' describe Project do describe '#create' do it "nameがないと登録できないこと" do project = build(:project, name: nil) project.valid? expect(project.errors[:name]).to include("can't be blank") end it "nameが31文字以上だと登録できないこと" do project = build(:project, name: "abcdefghijklmnopqrstuvwxyzabcde") project.valid? expect(project.errors[:name]).to include("is too long (maximum is 30 characters)") end it "user_idがないと登録できないこと" do project = build(:project, user_id: nil) project.valid? expect(project.errors[:user]).to include("must exist") end it "name,user_id があれば登録できること" do expect(build(:project)).to be_valid end it "nameが30文字以内であれば登録できること" do expect(build(:project, name: "abcdefghijklmnopqrstuvwxyzabcd")).to be_valid end end end
上記テストですが、userがないとエラーになってしまいます。
実際の環境でもuserがないとprojectsが保存できないのですから、
テストでしっかり反映されているということですね。
まとめ
前回userモデルのテストを行いましたが、今回アソシエーションを組んでいるモデルのテストを書いたことで、
rspecの理解が深まりました!
わかってくるとテスト楽しい!
rspecに関する書籍がってあまり見つからない(電子書籍はありました!)ため、
学んだことはしっかりと書き留めて忘れた時に見直せるようにしておきたいです。