2017-11-16 6 views
2

私はマルチテナントのSaaSアプリケーションを持っています。すべてのテナントモデルでテナントセキュリティテストを実行します。Rspec:ホワイトリストに登録されていない限り、すべてのモデルで特定の単体テストを実行してください

describe 'tenant security' do 
    it "has only the current company's data" do 
    set_tenant_company 
    other_companys_data = create :model 

    set_tenant_company 
    this_companys_data = create :model 

    expect(Model.all).to include this_companys_data 
    expect(Model.all).not_to include other_companys_data 
    end 
end 

これをすべてのモデルで実行する方法はありますか。 [単体テストに何かを明示的にコーディングすることなく]もしそうなら、テナント以外のモデルをホワイトリストにする方法はありますか?

テナントのセキュリティは非常に重要です。私はそれを間違って見落としたくはありません。

+0

ホワイトリストに登録しないと自動的に行う方法はわかりませんが、すべてのテナントモデルで1つの実装と数行しか必要としないので、 'behaves_like'を使うことができます。これを見てください:https://relishapp.com/rspec/rspec-core/v/3-7/docs/example-groups/shared-examples –

+0

ありがとう! Shared_examplesは私のしていることよりも優れているようです。モデル仕様ファイルごとに自動的にshared_exampleを1回実行する方法はありますか?特定のファイル(ホワイトリスト)をスキップするように指示する方法はありますか? –

答えて

0

ペドロのコメントのベース、およびRSpecのコアチームに投稿された彼の質問:

あなたは暗黙的に、各モデルに含めるテストとの共有の例を作成します。 :この条件を含まないホワイトリストモデルのための条件である。

RSpec.shared_examples 'a tenant model' do 
    it "has only the current company's data",unless: metadata[:not_a_tenant_model] == true do 
    set_tenant_company 
    other_companys_data = create subject.class.name.underscore.to_sym 

    set_tenant_company 
    this_companys_data = create subject.class.name.underscore.to_sym 

    expect(subject.class.all).to include this_companys_data 
    expect(subject.class.all).not_to include other_companys_data 
    end 
end 

置きますRSpec.configuration

RSpec.configure do |config| 
    config.include_context 'a tenant model', type: :model 
end 

これで次の行は、すべてのモデルで次のように配置する効果があります。

Rspec.describe TenantModel do 
    it_behaves_like 'a tenant model' 
end 

だけで適切なタグを追加し、非テナントモデルをホワイトリストに:

RSpec.decribe NonTenantModel, :not_a_tenant_model do 
    # shared example will not be included 
end 

ビッグはあなたに感謝!ペドロとRSpecコアチームに

+0

いくつかの調査とテストの後、実行時にサンプルを生成できないため、これは不可能だと私は信じています。 RSpecではこれを許可していません。とにかく、私はコア・チームにこれを行う方法があるかどうかを尋ねました:https://github.com/rspec/rspec-core/issues/2480方法がある場合は、配列を作成し、そこに記述されたクラスの存在。 –

+0

ありがとう!私は[メタデータ](https://relishapp.com/rspec/rspec-core/docs/metadata)、[フィルタリング](https://relishapp.com/rspec/rspec-core/docs/filtering) 、[after(:context)フック](https://relishapp.com/rspec/rspec-core/docs/hooks/before-and-after-hooks)を参照してください。 shared_examplesを条件付きで実行するための実用的なソリューションにはまだ着いていません。 –

0

現在採用されているソリューションでは、すべての非テナントモデルに特定のタグを付ける必要があります。このソリューションでは、設定でこれを行います。

さて、この問題を開くに感謝:https://github.com/rspec/rspec-core/issues/2480、これはあなたのケースのために非常に最善の解決策のようだ:

non_tenant_models = %w(NonTenantModelOne NonTenantModelTwo).map(&:constantize) 

RSpec.configure do |c| 
    c.define_derived_metadata(type: :model) do |meta| 
    meta[:tenant_model] = true unless meta[:described_class].presence_in non_tenant_models 
    end 

    c.include_context "shared", tenant_model: true 
end 

これは、すべての非をモデルがテナントであれば言って、あなたに明確なメタデータを与え、ホワイトリストモデル内の何かをコーディングする必要はなく、実行中の共有サンプルで指定されたテナントモデル。

+0

設定に「ホワイトリスト」タグの非常に素晴らしい抽象化。私の特定のケースでは、ホワイトリストに載っているタグを明示的にホワイトリストに載せておくことを好みます。私はこのテストがすべてのモデルに含まれていることを確認したいが、テストを可能な限り明示的に保つことが望ましい。すべてのあなたのご意見ありがとうございます。私はあなたの助けなしに解決策を実装していない。 –

+0

Youre welcome :) –

関連する問題