今回はRSpecでテストをpending(保留)する方法についてまとめたいと思います。プルリクエスト出したいけどこのテストは一旦保留にしたい、テストが未完成だけどとりあえずCircle Ciのチェックをパスしてプルリクエストを出したいといった状況などに使える方法です。
テストコード例
今回はUserモデルのnameとname_kanaのバリデーションチェックを行うシンプルなモデルテストを書いてみました。データ作成にはFactoryBotを使用しています。
class User < ApplicationRecord
validates :name, :name_kana, presence: true
end
FactoryBot.define do
factory :user do
name { "田中太朗" }
name_kana { "タナカタロウ" }
end
end
require 'rails_helper'
RSpec.describe User, type: :model do
it "nameとname_kanaが存在する" do
user = FactoryBot.build(:user)
expect(user).to be_valid
end
it "nameが空の場合" do
user = FactoryBot.build(:user, name: nil)
user.valid?
expect(user.errors[:name]).to include("can't be blank")
end
it "name_kanaが空の場合" do
user = FactoryBot.build(:user, name_kana: nil)
user.valid?
expect(user.errors[:name_kana]).to include("can't be blank")
end
end
上記のテストコードを実行すると3つのexamplesが成功するはずです。
% bundle exec rspec spec/models/user.rb
User
nameとname_kanaが存在する
nameが空の場合
name_kanaが空の場合
Finished in 0.09137 seconds (files took 1.56 seconds to load)
3 examples, 0 failures
【xdescribe】テスト全体をpending
テスト全体をpendingにするには、describeをxdescribeに編集することで可能になります。ここではUserモデルのテスト全体をpendingにしてみます。
require 'rails_helper'
RSpec.xdescribe User, type: :model do
it "nameとname_kanaが存在する" do
user = FactoryBot.build(:user)
expect(user).to be_valid
end
it "nameが空の場合" do
user = FactoryBot.build(:user, name: nil)
user.valid?
expect(user.errors[:name]).to include("can't be blank")
end
it "name_kanaが空の場合" do
user = FactoryBot.build(:user, name_kana: nil)
user.valid?
expect(user.errors[:name_kana]).to include("can't be blank")
end
end
% bundle exec rspec spec/models/user.rb
User
nameとname_kanaが存在する (PENDING: Temporarily skipped with xdescribe)
nameが空の場合 (PENDING: Temporarily skipped with xdescribe)
name_kanaが空の場合 (PENDING: Temporarily skipped with xdescribe)
Pending: (Failures listed here are expected and do not affect your suite's status)
1) User nameとname_kanaが存在する
# Temporarily skipped with xdescribe
# ./spec/models/user.rb:4
2) User nameが空の場合
# Temporarily skipped with xdescribe
# ./spec/models/user.rb:9
3) User name_kanaが空の場合
# Temporarily skipped with xdescribe
# ./spec/models/user.rb:15
Finished in 0.00657 seconds (files took 3.2 seconds to load)
3 examples, 0 failures, 3 pending
【xcontext】テストの一部をpending
全体ではなくテストの一部をpendingにしたい場合は、contextで括り、pendingにしたいcontextをxcontextに変更します。ここでは異常系のテストをpendingにしてみます。
require 'rails_helper'
RSpec.describe User, type: :model do
context "正常系" do
it "nameとname_kanaが存在する" do
user = FactoryBot.build(:user)
expect(user).to be_valid
end
end
xcontext "異常系" do
it "nameが空の場合" do
user = FactoryBot.build(:user, name: nil)
user.valid?
expect(user.errors[:name]).to include("can't be blank")
end
it "name_kanaが空の場合" do
user = FactoryBot.build(:user, name_kana: nil)
user.valid?
expect(user.errors[:name_kana]).to include("can't be blank")
end
end
end
% bundle exec rspec spec/models/user.rb
User
正常系
nameとname_kanaが存在する
異常系
nameが空の場合 (PENDING: Temporarily skipped with xcontext)
name_kanaが空の場合 (PENDING: Temporarily skipped with xcontext)
Pending: (Failures listed here are expected and do not affect your suite's status)
1) User 異常系 nameが空の場合
# Temporarily skipped with xcontext
# ./spec/models/user.rb:12
2) User 異常系 name_kanaが空の場合
# Temporarily skipped with xcontext
# ./spec/models/user.rb:18
Finished in 0.07004 seconds (files took 1.57 seconds to load)
3 examples, 0 failures, 2 pending
【xit】テストをskip
pendingとは意味が異なりますが、テストをskipにすることもできます。
pendingはテスト失敗時にのみ保留中にしてくれますが、skipはテスト成功失敗に関わらずテストを実行しないという違いがあります。
テストをskipしたい場合はitをxitに変更します。ここでは「nameとname_kanaが存在する」というテストをskipしてみます。
require 'rails_helper'
RSpec.describe User, type: :model do
it "nameとname_kanaが存在する" do
user = FactoryBot.build(:user)
expect(user).to be_valid
end
xit "nameが空の場合" do
user = FactoryBot.build(:user, name: nil)
user.valid?
expect(user.errors[:name]).to include("can't be blank")
end
it "name_kanaが空の場合" do
user = FactoryBot.build(:user, name_kana: nil)
user.valid?
expect(user.errors[:name_kana]).to include("can't be blank")
end
end
% bundle exec rspec spec/models/user.rb
User
nameとname_kanaが存在する
nameが空の場合 (PENDING: Temporarily skipped with xit)
name_kanaが空の場合
Pending: (Failures listed here are expected and do not affect your suite's status)
1) User nameが空の場合
# Temporarily skipped with xit
# ./spec/models/user.rb:9
Finished in 0.10042 seconds (files took 2.09 seconds to load)
3 examples, 0 failures, 1 pending
まとめ
- RSpecでテストをpendingにするには「x」を付与すればよい
- テスト全体をpendingしたい場合はdescribeをxdescribeにする
- テストの一部をpendingしたい場合はcontextをxcontextにする
- テストをskipしたい場合はitをxitにする
参考
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
今回はRSpecでテストをpending(保留)する方法について解説しました。テストが増えれば増えるほどpendingを使う機会が増えるため、覚えておいて損はないと思います。