Techioz Blog

専門家の仕様テストにおける Rubocop RSpec/MultipleMemoizedHelpers の問題

概要

Rails アプリでの認証には pundit を、テストには RSpec を使用します。このため、ポリシーの仕様を作成する必要がありました。

ただし、rubocop がエラー RSpec/MultipleMemoizedHelpers をスローするという問題が発生しています。 これは、let 呼び出しと subject 呼び出しが多すぎることを意味すると理解しています。私の問題は、コードを適切な呼び出し回数に従うように解決またはリファクタリングする方法がよくわからないことです。

もう 1 つ、スペック ファイルに対して RSpec/MultipleMemoizedHelpers を無効にしても問題ありませんか?

問題となるポリシー仕様ファイルのうち 3 つを次に示します。

require "rails_helper"

describe AnswerPolicy do
  subject { described_class }

  let(:user_admin) { build(:user, :admin) }
  let(:consultant) { build(:consultant) }
  let(:user_consultant) { build(:user, :consultant, consultant: consultant) }
  let(:client) { build(:client, consultant: consultant) }
  let(:user_client) { build(:user, :client, client: client) }
  let(:other_client) { build(:client, consultant: build(:consultant)) }
  let(:answer) { build(:answer, client: client) }
  let(:other_answer) { build(:answer, client: other_client) }

  permissions :update? do
    it "allows access to admin" do
      expect(described_class).to permit(user_admin)
    end

    it "prevents consultants to update other non-client answers" do
      expect(described_class).not_to permit(user_consultant, other_answer)
    end

    it "prevents clients to update their answers" do
      expect(described_class).not_to permit(user_client, answer)
    end

    it "allows consultants to update their client's answers" do
      expect(described_class).to permit(user_consultant, answer)
    end
  end
end
describe AssessmentStepPolicy do
  subject { described_class }

  let(:user_admin) { build(:user, :admin) }
  let(:consultant) { build(:consultant) }
  let(:user_consultant) { build(:user, :consultant, consultant: consultant) }
  let(:client) { build(:client, consultant: consultant) }
  let(:user_client) { build(:user, :client, client: client) }
  let(:other_client) { build(:client, consultant: build(:consultant)) }

  permissions :view? do
    it "allows access to admin" do
      expect(described_class).to permit(user_admin)
    end

    it "prevents consultants to view other non-client assessment details" do
      expect(described_class).not_to permit(user_consultant, other_client)
    end

    it "allows clients to view their assessment details" do
      expect(described_class).to permit(user_client, client)
    end

    it "prevents clients to view other client's assessment details" do
      expect(described_class).not_to permit(user_client, other_client)
    end

    it "allows consultants to view their client's answers" do
      expect(described_class).to permit(user_consultant, client)
    end
  end

  permissions :create? do
    it "allows access to any admin" do
      expect(described_class).to permit(user_admin)
    end

    it "prevents consultants to assess other clients" do
      expect(described_class).not_to permit(user_consultant, other_client)
    end

    it "prevents clients to assess themselves" do
      expect(described_class).not_to permit(user_client, client)
    end

    it "allows consultants to assess their clients" do
      expect(described_class).to permit(user_consultant, client)
    end
  end
end
require "rails_helper"

describe ReportPolicy do
  subject { described_class }

  let(:user_admin) { build(:user, :admin) }
  let(:consultant) { build(:consultant) }
  let(:user_consultant) { build(:user, :consultant, consultant: consultant) }
  let(:client) { build(:client, consultant: consultant) }
  let(:user_client) { build(:user, :client, client: client) }
  let(:other_consultant) { build(:consultant) }
  let(:other_client) { build(:client, consultant: other_consultant) }

  permissions :dashboard? do
    it "allows access to admin" do
      expect(described_class).to permit(user_admin)
    end

    it "prevents clients to view other client dashboards" do
      expect(described_class).not_to permit(user_client, other_client)
    end

    it "prevents consultants to view other non-client dashboards" do
      expect(described_class).not_to permit(user_consultant, other_client)
    end

    it "allows clients to view their dashboard" do
      expect(described_class).to permit(user_client, client)
    end

    it "allows consultants to view their client's dashboards" do
      expect(described_class).to permit(user_consultant, client)
    end
  end
end

解決策

この RSpec/MultipleMemoizedHelpers 警官は物議を醸しています。 letの数を任意の数に制限してほしい。

私はそれに対して懸命に戦った。私にとって、それは変数が多すぎるために警察が違反行為を起こすのと同じです。 rubocop とrubocop-ast ではこれが無効になっていますが、通常はデフォルトよりも多くのcopsを有効にしています。これらの let を def に変更すると、違反がなくなることに注意してください (ただし、何も変更していません。let は def の単なる構文シュガーです)。

工場を共有するのは良いアイデアのように思えますが、警官も無効にすることをお勧めします。