#はじめに
Railsチュートリアル第6版のテストをRSpecで書き直していく。
###目次
#Minitest
###Relationshipモデルのテスト
require 'test_helper'
class RelationshipTest < ActiveSupport::TestCase
def setup
@relationship = Relationship.new(follower_id: users(:michael).id,
followed_id: users(:archer).id)
end
test "should be valid" do
assert @relationship.valid?
end
test "should require a follower_id" do
@relationship.follower_id = nil
assert_not @relationship.valid?
end
test "should require a followed_id" do
@relationship.followed_id = nil
assert_not @relationship.valid?
end
end
###“following” 関連のメソッドのテスト
require 'test_helper'
class UserTest < ActiveSupport::TestCase
.
.
.
test "should follow and unfollow a user" do
michael = users(:michael)
archer = users(:archer)
assert_not michael.following?(archer)
michael.follow(archer)
assert michael.following?(archer)
assert archer.followers.include?(michael)
michael.unfollow(archer)
assert_not michael.following?(archer)
end
test "feed should have the right posts" do
michael = users(:michael)
archer = users(:archer)
lana = users(:lana)
# フォローしているユーザーの投稿を確認
lana.microposts.each do |post_following|
assert michael.feed.include?(post_following)
end
# 自分自身の投稿を確認
michael.microposts.each do |post_self|
assert michael.feed.include?(post_self)
end
# フォローしていないユーザーの投稿を確認
archer.microposts.each do |post_unfollowed|
assert_not michael.feed.include?(post_unfollowed)
end
end
end
###フォロー/フォロワーページの認可のテスト
require 'test_helper'
class UsersControllerTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
@other_user = users(:archer)
end
.
.
.
test "should redirect following when not logged in" do
get following_user_path(@user)
assert_redirected_to login_url
end
test "should redirect followers when not logged in" do
get followers_user_path(@user)
assert_redirected_to login_url
end
end
###following/followerをテストするためのリレーションシップ用fixture
one:
follower: michael
followed: lana
two:
follower: michael
followed: malory
three:
follower: lana
followed: michael
four:
follower: archer
followed: michael
###following/followerページのテスト
require 'test_helper'
class FollowingTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
@other = users(:archer)
log_in_as(@user)
end
test "following page" do
get following_user_path(@user)
assert_not @user.following.empty?
assert_match @user.following.count.to_s, response.body
@user.following.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
test "followers page" do
get followers_user_path(@user)
assert_not @user.followers.empty?
assert_match @user.followers.count.to_s, response.body
@user.followers.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
test "should follow a user the standard way" do
assert_difference '@user.following.count', 1 do
post relationships_path, params: { followed_id: @other.id }
end
end
test "should follow a user with Ajax" do
assert_difference '@user.following.count', 1 do
post relationships_path, xhr: true, params: { followed_id: @other.id }
end
end
test "should unfollow a user the standard way" do
@user.follow(@other)
relationship = @user.active_relationships.find_by(followed_id: @other.id)
assert_difference '@user.following.count', -1 do
delete relationship_path(relationship)
end
end
test "should unfollow a user with Ajax" do
@user.follow(@other)
relationship = @user.active_relationships.find_by(followed_id: @other.id)
assert_difference '@user.following.count', -1 do
delete relationship_path(relationship), xhr: true
end
end
end
###リレーションシップの基本的なアクセス制御に対するテスト
require 'test_helper'
class RelationshipsControllerTest < ActionDispatch::IntegrationTest
test "create should require logged-in user" do
assert_no_difference 'Relationship.count' do
post relationships_path
end
assert_redirected_to login_url
end
test "destroy should require logged-in user" do
assert_no_difference 'Relationship.count' do
delete relationship_path(relationships(:one))
end
assert_redirected_to login_url
end
end
#RSpec
###Relationshipモデルのテスト
require 'rails_helper'
RSpec.describe Relationship, type: :model do
let(:user) { FactoryBot.create(:user) }
let(:other) { FactoryBot.create(:user) }
let(:relationship) { Relationship.new(follower_id: user.id,followed_id: other.id) }
it "should be valid" do
expect(relationship).to be_valid
end
it "should require a follower_id" do
relationship.follower_id = nil
expect(relationship).to be_invalid
end
it "should require a followed_id" do
relationship.followed_id = nil
expect(relationship).to be_invalid
end
end
let
でrelationshipを作成しておく。
###“following” 関連のメソッドのテスト
require 'rails_helper'
RSpec.describe User, type: :model do
.
.
.
describe "relationships" do
let(:michael) { FactoryBot.create(:user) }
let(:archer) { FactoryBot.create(:user) }
let(:lana) { FactoryBot.create(:user) }
before do
michael.follow(lana)
end
it "should follow and unfollow a user" do
expect(michael.following?(archer)).to be_falsy
michael.follow(archer)
expect(michael.following?(archer)).to be_truthy
expect(archer.followers.include?(michael)).to be_truthy
michael.unfollow(archer)
expect(michael.following?(archer)).to be_falsy
end
it "feed should have the right posts" do
lana.microposts.each do |post_following|
expect(michael.feed.include?(post_following)).to be_truthy
end
michael.microposts.each do |post_self|
expect(michael.feed.include?(post_self)).to be_truthy
end
archer.microposts.each do |post_unfollowed|
expect(michael.feed.include?(post_unfollowed)).to be_falsy
end
end
end
end
relationshipのfixtureが無いので、before do
でfollowしておく。
###フォロー/フォロワーページの認可のテスト
require 'rails_helper'
RSpec.describe "Users", type: :request do
before do
@user = FactoryBot.create(:user)
@noadmin_user = FactoryBot.create(:user, :noadmin)
end
.
.
.
it "should redirect following when not logged in" do
get following_user_path(@user)
expect(response).to redirect_to login_url
end
it "should redirect followers when not logged in" do
get followers_user_path(@user)
expect(response).to redirect_to login_url
end
end
###following/followerページのテスト
require 'rails_helper'
RSpec.describe "Followings", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:other) { FactoryBot.create(:user) }
let(:other2) { FactoryBot.create(:user) }
let(:other3) { FactoryBot.create(:user) }
before do
log_in_as(user)
user.follow(other2)
user.follow(other3)
other2.follow(user)
other.follow(user)
end
it "following page" do
get following_user_path(user)
expect(user.following.empty?).to be_falsy
assert_match user.following.count.to_s, response.body
user.following.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
it "followers page" do
get followers_user_path(user)
expect(user.followers.empty?).to be_falsy
assert_match user.followers.count.to_s, response.body
user.followers.each do |user|
assert_select "a[href=?]", user_path(user)
end
end
it "should follow a user the standard way" do
expect{
post relationships_path, params: { followed_id: other.id }
}.to change(user.following, :count).by(1)
end
it "should follow a user with Ajax" do
expect{
post relationships_path, xhr: true, params: { followed_id: other.id }
}.to change(user.following, :count).by(1)
end
it "should unfollow a user the standard way" do
user.follow(other)
relationship = user.active_relationships.find_by(followed_id: other.id)
expect{
delete relationship_path(relationship)
}.to change(user.following, :count).by(-1)
end
it "should unfollow a user with Ajax" do
user.follow(other)
relationship = user.active_relationships.find_by(followed_id: other.id)
expect{
delete relationship_path(relationship), xhr: true
}.to change(user.following, :count).by(-1)
end
end
こちらもrelationship fixtureの代わりに、before do
でフォロー関係を作成しておく。
###リレーションシップの基本的なアクセス制御に対するテスト
require 'rails_helper'
RSpec.describe "Relationships", type: :request do
let(:user) { FactoryBot.create(:user) }
let(:other) { FactoryBot.create(:user) }
let!(:relationship) {Relationship.create(follower_id: user.id,followed_id: other.id)}
it "create should require logged-in user" do
expect{
post relationships_path
}.to_not change(Relationship, :count)
expect(response).to redirect_to login_path
end
it "destroy should require logged-in user" do
expect{
delete relationship_path(relationship)
}.to_not change(Relationship, :count)
expect(response).to redirect_to login_path
end
end
*"destroy should require logged-in user"*において使用する、userがotherをフォローしているというrelationshipをlet!
で作成しておく。この際、userのログインが求められないように、Relationship.create
を使用する。
#おわりに
今回テストを記述するにあたって、チュートリアルのテスト内容を忠実に再現することを意識していたため、RSpecの強みや良さを活かしきれていない部分が多々あると思う。
より良い書き方があれば是非コメントしていただきたい。
また、演習のテストは無視したので、気が向けば追加するつもりだ。