テスト対象
該当するコントローラ | 該当するアクション |
---|---|
UsersController | following, followers |
環境
フォルダ、使用ファイル
種類 | ファイル名 |
---|---|
スペック | spec/features/users_follow_spec.rb |
スペック | spec/features/authorization_spec.rb |
サポートモジュール | spec/support/support_module.rb |
shared_context | spec/support/shared_context.rb |
shared_examples | spec/support/shared_examples.rb |
ファクトリ(ユーザ) | spec/support/factories/users.rb |
アウトライン作成 1/2
フォロー/フォロワー のユーザ情報の表示
※ 未ログインの場合(ページ保護)/ユーザ削除権限(admin権限)のテストは
authorization_spec.rb
(別ファイル)にて作成
フィーチャスペック編 authorization_spec
users_following_spec.rb
# spec/features/users_following_spec.rb
RSpec.feature "UsersFollowing", type: :feature do
# 未ログイン場合のスペックは、
# authorization_spec.rb にて(別ファイル)作成
# フォロー/フォロワー
describe "following/followers method"
# 自分がフォロー中のユーザのページ
describe "following page"
# ユーザ情報の表示が正しいこと
it_behaves_like "have user infomation"
# 自分をフォローしているユーザのページ
describe "followers page"
# ユーザ情報の表示が正しいこと
it_behaves_like "have user infomation"
end
shared_examples の作成
- ##### it_behaves_like "have user infomation"
shared_examples.rb
# spec/support/shared_examples.rb
# ユーザ情報
# top#home, users#following, users#followers
shared_examples_for "have user infomation" do
it { expect(page).to have_css('img.gravatar') }
it { expect(page).to have_css('h1', text: user.name) }
it { expect(page).to have_text("Microposts") }
it { expect(page).to have_link("view my profile", href: user_path(user)) }
end
スペック作成 1/2
users_following_spec.rb
# spec/features/users_follow_spec.rb
require 'rails_helper'
RSpec.feature "UsersFollow", type: :feature do
include SupportModule
include_context "setup"
subject { page }
# 未ログインの場合のテストは、
# authorization_spec.rb にて(別ファイル)実施
describe "following/followers method" do
describe "following page" do
before do
login_as(user)
click_link "following"
end
it_behaves_like "have user infomation"
end
describe "followers page" do
before do
login_as(user)
click_link "following"
end
it_behaves_like "have user infomation"
end
end
end
実行結果 1/2
$ bin/rspec spec/features/users_follow_spec.rb -e "following page" -e "followers page"
UsersFollow
following/followers method
following page
behaves like have user infomation
should have visible css "img.gravatar"
should have visible css "h1" with text "Example user"
should text "Microposts"
should have visible link "view my profile" with href "/users/5"
followers page
behaves like have user infomation
should have visible css "img.gravatar"
should have visible css "h1" with text "Example user"
should text "Microposts"
should have visible link "view my profile" with href "/users/5"
Finished in 5.6 seconds (files took 2.16 seconds to load)
8 examples, 0 failures
アウトライン作成 2/2
users_following_spec.rb
# spec/features/users_follow_spec.rb
RSpec.feature "UsersFollowing", type: :feature do
# フォロー/フォロワー
describe "following/followers method"
# (省略)
# ページネーション
describe "pagination"
# ユーザ情報が表示されている
scenario "list each following"
# ユーザ情報が表示されている
scenario "list each followers"
end
サンプルデータのセットアップ
users_following_spec.rb
# spec/features/users_follow_spec.rb
describe "following/followers method" do
# セットアップ
before do
users # => shared_context 内で定義 create_list(:other_user, 30)
users.each do |u|
user.follow(u) # => 自分が 30人をフォローする
u.follow(user) # => 他人の 30人にフォローされる
end
user.follow(other_user) # => 自分が他人(1人)をフォロー
other_user.follow(user) # => 他人が自分(1人)をフォロー
end
# (セットアップの確認:31人をフォローしている)
it { expect(user.following.count).to eq 31 }
# (セットアップの確認:31人にフォローされている)
it { expect(other_user.following.count).to eq 1 }
it { expect(user.followers.count).to eq 31 }
end
コンソールで確認
$rails console test --sandbox
(抜粋)
$ rails c test -s
[1] pry(main)>
[2] pry(main)> users = FactoryBot.create_list(:other_user, 3)
id: 5,
name: "Jess Witting",
email: "everettkunze@wintheiser.com",
id: 6,
name: "Tula Reilly",
email: "sashagleason@leuschke.co",
id: 7,
name: "Cori Emard",
email: "rustywill@mayert.com",
[3] pry(main)>
[4] pry(main)>
[5] pry(main)> me = FactoryBot.create(:user)
id: 8,
name: "Example user",
email: "user@example.com",
[8] pry(main)>
[9] pry(main)> users.each do |u|
[9] pry(main)* me.follow(u)
[9] pry(main)* u.follow(me)
[9] pry(main)* end
(抜粋)自分が フォロー中のユーザ
[["follower_id", 8], ["followed_id", 5], ["created_at", "2018-08-07 02:07:11.485562"], ["updated_at", "2018-08-07 02:07:11.485562"]]
[["follower_id", 8], ["followed_id", 6], ["created_at", "2018-08-07 02:07:11.512676"], ["updated_at", "2018-08-07 02:07:11.512676"]]
[["follower_id", 8], ["followed_id", 7], ["created_at", "2018-08-07 02:07:11.536817"], ["updated_at", "2018-08-07 02:07:11.536817"]]
(抜粋)自分を フォローしているのユーザ
[["follower_id", 5], ["followed_id", 8], ["created_at", "2018-08-07 02:07:11.499536"], ["updated_at", "2018-08-07 02:07:11.499536"]]
[["follower_id", 6], ["followed_id", 8], ["created_at", "2018-08-07 02:07:11.527219"], ["updated_at", "2018-08-07 02:07:11.527219"]]
[["follower_id", 7], ["followed_id", 8], ["created_at", "2018-08-07 02:07:11.546484"], ["updated_at", "2018-08-07 02:07:11.546484"]]
実行結果
- サンプルデータのセットアップ
$ bin/rspec spec/features/users_follow_spec.rb
UsersFollow
following/followers method
should eq 31
should eq 1
should eq 31
Finished in 3.87 seconds (files took 2.08 seconds to load)
3 examples, 0 failures
スペック作成 2/2
users_following_spec.rb
# spec/features/users_following_spec.rb
require 'rails_helper'
RSpec.feature "UsersFollow", type: :feature do
include SupportModule
include_context "setup"
subject { page }
# 未ログインの場合のテストは、
# authorization_spec.rb にて(別ファイル)実施
describe "following/followers method" do
before do
users # => shared_context 内で定義 create_list(:other_user, 30)
users.each do |u|
user.follow(u) # => 自分が 30人をフォローする
u.follow(user) # => 他人の 30人にフォローされる
end
user.follow(other_user) # => 自分が他人(1人)をフォロー
other_user.follow(user) # => 他人が自分(1人)をフォロー
end
# (セットアップの確認:31人をフォローしている)
it { expect(user.following.count).to eq 31 }
# (セットアップの確認:31人にフォローされている)
it { expect(other_user.following.count).to eq 1 }
it { expect(user.followers.count).to eq 31 }
# (省略)
describe "pagination" do
before { login_as(user) }
scenario "list each following" do
# login_as(user)
click_link "following"
user.following.paginate(page: 1).each do |u|
expect(page).to have_css("li", text: u.name)
expect(page).to have_link(u.name, href: user_path(u))
end
end
scenario "list each followers" do
# login_as(user)
click_link "followers"
user.followers.paginate(page: 1).each do |u|
expect(page).to have_css("li", text: u.name)
expect(page).to have_link(u.name, href: user_path(u))
end
end
end
end
end
実行結果 2/2
$ bin/rspec spec/features/users_follow_spec.rb -e "pagination"
UsersFollow
following/followers method
pagination
list each following
list each followers
Finished in 6.39 seconds (files took 1.98 seconds to load)
2 examples, 0 failures
未ログインの場合(ページ保護)のスペック
- #### authorization_spec.rb (別ファイル)にて作成
アウトラインの作成
authorization_spec.rb
# spec/features/authorization_spec.rb
RSpec.feature "Authorization", type: :feature do
# ページ保護(アクセス権限)
describe "in UsersController"
describe "login is necessary"
# 未ログインの場合
context "when non-login"
describe "edit"
# ログインメッセージが出力されること
it "should have error_messages 'Please log in'"
# ログインページへリダイレクトされること
it "should have redirect to '/login'"
describe "update"
it "should have error_messages 'Please log in'"
it "should have redirect to '/login'"
end
shared_examples の作成
-
ログインメッセージ出力・ログインページへリダイレクトは、一般化して使い回せるようにしてみる
spec側でブロックをオブジェクト化(
Proc.new { }
)してsubject { }
に定義し、shared_examples側で、subject.call
して呼び出す
shared_examples.rb
# spec/support/shared_examples.rb
# 成功メッセージ
# flash[:success]
shared_examples_for "success message" do |msg|
it { subject.call; expect(flash[:success]).to eq msg }
end
# 失敗メッセージ
# flash[:danger]
shared_examples_for "error message" do |msg|
it { subject.call; expect(flash[:danger]).to eq msg }
end
# リダイレクト
# redirect to path
shared_examples_for "redirect to path" do |path|
it { subject.call; expect(response).to redirect_to path }
end
スペック作成
authorization_spec.rb
# spec/features/authorization_spec.rb
RSpec.feature "Authorization", type: :feature do
include SupportModule
include_context "setup"
# アクセス権限
describe "in UsersController", type: :request do
# 未ログインの場合 (before_action のテスト)
describe "login is necessary" do
context "when non-login" do
describe "following" do
subject { Proc.new { get following_user_path(user) } }
it_behaves_like "error flash", "Please log in"
it_behaves_like "redirect to path", "/login"
end
describe "followers" do
subject { Proc.new { get followers_user_path(user) } }
it_behaves_like "error flash", "Please log in"
it_behaves_like "redirect to path", "/login"
end
end
end
end
end
実行結果
$ bin/rspec spec/features/authorization_spec.rb -e "following" -e "followers"
Authorization
in UsersController
login is necessary
when non-login
following
behaves like error flash
should eq "Please log in"
behaves like redirect to path
should redirect to "/login"
followers
behaves like error flash
should eq "Please log in"
behaves like redirect to path
should redirect to "/login"
Finished in 1.86 seconds (files took 1.95 seconds to load)
4 examples, 0 failures