LoginSignup
0
0

More than 5 years have passed since last update.

Railsチュートリアル テストをRSpecで実施 【フィーチャスペック編 microposts_spec 7/7】

Last updated at Posted at 2018-08-10

<!-- ## フィーチャースペック編 microposts_spec 7/7 -->

テスト対象

該当するコントローラ 該当するアクション
MicropostsController create, destroy

環境

Userモデル 単体テスト編 1/3 に記載

フォルダ、使用ファイル

種類 ファイル名
スペック spec/features/microposts_pages_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
ファクトリ(マイクロポスト) spec/support/factories/microposts.rb

アウトラインの作成

  • マイクロポストの作成/削除
  • 他人のマイクロポストは削除できない

  • ※ 未ログインの場合(ページ保護)のテストは authorization_spec.rb (別ファイル)にて作成
    フィーチャスペック編 authorization_spec

# spec/features/microposts_pages_spec.rb
RSpec.feature "MicropostsPages", type: :feature do

  # 未ログイン場合のスペックは、
  # authorization_spec.rb にて(別ファイル)作成

  # マイクロポストの作成(create)
  describe "create"
    # valid な情報の場合
    context "valid info"
      # 成功 (increment: 1)
      it_behaves_like "success create micropost"
      # 成功メッセージ
      scenario "have success messages"
    # invalid な情報の場合
    context "invalid info"
      it_behaves_like "fail create micropost"
      # 失敗メッセージ
      scenario "have error messages"
    # マイクロポストの削除(delete)
    describe "destroy"
      # 自分のマイクロポストの場合
      context "attempt to delete my microposts"
        # 成功 (decrement: -1)
        it_behaves_like "success delete micropost"
        # successメッセージが出力されること
        scenario "have success messages"
      # 他人のマイクロポストの場合
      context "attempt to delete other user's microposts"
        # 失敗 (decrement: 0)
        it_behaves_like "fail delete micropost"
end

スペック作成

# spec/features/microposts_pages_spec.rb
require 'rails_helper'

RSpec.feature "MicropostsPages", type: :feature do

  include SupportModule
  include_context "setup"

  subject { page }

  # マイクロポストの作成(create)
  describe "create" do
    before { login_as(user) }
    # valid な情報の場合
    context "valid info" do
      # 成功 (increment: 1)
      it_behaves_like "success create micropost"
    end
    # invalid な情報の場合
    context "invalid info" do
      it_behaves_like "fail create micropost"
    end
  end

  # マイクロポストの削除(delete)
  describe "destroy", type: :request do
    before { login_as(user) }
    # 自分のマイクロポストの場合
    context "attempt to delete my microposts" do
      it_behaves_like "success delete micropost"
    end
    # 他人のマイクロポストの場合
    context "attempt to delete other user's microposts" do
      it_behaves_like "fail delete micropost"
    end
  end
end

shared_examples の作成

  • it_behaves_like "success create micropost"
  • it_behaves_like "fail create micropost"
  • it_behaves_like "success delete micropost"
  • it_behaves_like "fail delete micropost"
  # spec/support/shared_examples.rb
                    # マイクロポストの作成/削除
    # microposts#create
    # 成功
    shared_examples_for "success create micropost" do
      scenario "micropost increment 1" do
        expect {
          visit root_path
          params = post_params
          fill_in "micropost_content", with: params[:content]
          click_button "Post"
        }.to change(Micropost, :count).by(1)
        # 成功メッセージ
        expect(page).to have_css("div.alert.alert-success", text: "Micropost created")
      end
    end
    # 失敗
    shared_examples_for "fail create micropost" do
      scenario "micropost increment 0" do
        expect {
          visit root_path
          fill_in "micropost_content", with: ""
          click_button "Post"
        }.to change(Micropost, :count).by(0)
        # 失敗メッセージ
        expect(page).to have_css("div.alert.alert-danger")
      end
    end

    # microposts#destroy
    # 成功
    shared_examples_for "success delete micropost" do
      before { my_posts }
      scenario "micropost descrement -1" do
        expect {
          visit root_path
          click_link "delete", match: :first
        }.to change(Micropost, :count).by(-1)
        # 成功メッセージ
        expect(page).to have_css("div.alert.alert-success", text: "Micropost deleted")
      end
    end
    # 失敗
    shared_examples_for "fail delete micropost" do
      before { other_posts }
      scenario "micropost descrement 0" do
        expect {
          # リンクが無いので、直接 HTTPリクエストを発行
          delete micropost_path(other_posts.first.id)
        }.to change(User, :count).by(0)
      end
    end

実行結果

$ bin/rspec spec/features/microposts_pages_spec.rb

MicropostPages
  create
    valid info
      behaves like success create micropost
        micropost increment 1
    invalid info
      behaves like fail create micropost
        micropost increment 0
  destroy
    attempt to delete my microposts
      behaves like success delete micropost
        micropost descrement -1
    attempt to delete other user's microposts
      behaves like fail delete micropost
        micropost descrement 0

Finished in 7.13 seconds (files took 2.15 seconds to load)
4 examples, 0 failures


未ログインの場合(ページ保護)のスペック

アウトラインの作成

# spec/features/authorization_spec.rb
RSpec.feature "Authorization", type: :feature do

  # ページ保護(アクセス権限)
  describe "in MicropostsController"
    # マイクロポスト 投稿(作成)/削除
    describe "authorization of create/destroy micropost"
      context "when non-login"
        describe "create"
        describe "destroy"
end

shared_examples の作成

  • ログインメッセージ出力・ログインページへリダイレクトは、一般化して使い回せるようにしてみる
  • spec側でブロックをオブジェクト化(Proc.new { })して subject { } に定義し、shared_examples側で、subject.call して呼び出す

# 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

スペック作成

# spec/features/authorization_spec.rb
require 'rails_helper'

RSpec.feature "Authorization", type: :feature do

  include SupportModule
  include_context "setup"

  # アクセス権限
  describe "in MicropostsController", type: :request do
    # マイクロポスト 投稿(作成)/削除
    describe "authorization of create/destroy micropost" do
      context "when non-login" do
        describe "create" do
          subject { Proc.new { post microposts_path, params: post_params } }
          it_behaves_like "error flash", "Please log in"
          it_behaves_like "redirect to path", "/login"
        end
        describe "destroy" do
          subject { Proc.new { delete micropost_path(my_post.id) } }
          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 "authorization of create/destroy micropost"

Authorization
  in MicropostsController
    authorization of create/destroy micropost
      when non-login
        create
          behaves like error flash
            should eq "Please log in"
          behaves like redirect to path
            should redirect to "/login"
        destroy
          behaves like error flash
            should eq "Please log in"
          behaves like redirect to path
            should redirect to "/login"

Finished in 4.68 seconds (files took 2.33 seconds to load)
4 examples, 0 failures


参考


以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0