web-dev-qa-db-ja.com

Rspecはスコープを許可します

Rspecletとスコープに問題があると思います。 let inの例(「it」ブロック)で定義されたメソッドを使用できますが、外部(letを実行したdescribeブロック)では使用できません。

5   describe Connection do
8     let(:connection) { described_class.new(connection_settings) }
9 
10    it_behaves_like "any connection", connection
24  end

この仕様を実行しようとすると、次のエラーが発生します。

connection_spec.rb:10:クラス:0xae8e5b8の未定義のローカル変数またはメソッド `connection '(NameError)

接続パラメータをit_behaves_likeに渡すにはどうすればよいですか?

34
Costi

私は自分に合ったものを見つけました:

   describe Connection do
     it_behaves_like "any connection", new.connection
     # new.connection: because we're in the class context 
     # and let creates method in the instance context, 
     # instantiate a instance of whatever we're in
   end
3
Costi

let()は、サンプルブロックにスコープされ、他の場所では使用できないことになっています。実際には、let()をパラメーターとして使用しません。パラメータとしてit_behaves_likeで機能しない理由は、let()の定義方法に関係しています。 Rspecの各サンプルグループはカスタムクラスを定義します。 let()は、そのクラスのインスタンスメソッドを定義します。ただし、そのカスタムクラスでit_behaves_likeを呼び出すと、インスタンス内からではなく、クラスレベルで呼び出されます。

私は次のようにlet()を使用しました:

shared_examples_for 'any connection' do
  it 'should have valid connection' do
    connection.valid?
  end
end

describe Connection do
  let(:connection) { Connection.new(settings) }
  let(:settings) { { :blah => :foo } }
  it_behaves_like 'any connection'
end

Shared_examplesを使用することはめったにありませんが、bcobbの回答と同様のことを行いました。

module SpecHelpers
  module Connection
    extend ActiveSupport::Concern

    included do
      let(:connection) { raise "You must override 'connection'" }
    end

    module ClassMethods
      def expects_valid_connection
        it "should be a valid connection" do
          connection.should be_valid
        end
      end
    end
  end
end

describe Connection do
  include SpecHelpers::Connection

  let(:connection) { Connection.new }

  expects_valid_connection
end

これらの共有例の定義は、共有例を使用するよりも冗長です。 「it_behave_like」はRspecを直接拡張するよりも厄介だと思います。

明らかに、.expects_valid_connectionsに引数を追加できます

私は友人のrspecクラスを助けるためにこれを書きました: http://Ruby-lambda.blogspot.com/2011/02/agile-rspec-with-let.html .. ..

27
Ho-Sheng Hsiao

編集済み-私の最初の解決策を完全に説明しました。Ho-ShengHsiaoが理由について素晴らしい説明をしました。

it_behaves_likeに次のようなブロックを与えることができます。

describe Connection do
  it_behaves_like "any connection" do
    let(:connection) { described_class.new(connection_settings) }
  end
end
20
bcobb

letで宣言されたパラメーターを明示的に渡さない場合、共有の例で使用できることを発見しました。

そう:

describe Connection do
  let(:connection) { described_class.new(connection_settings) }

  it_behaves_like "any connection"
end

接続は、共有のサンプル仕様で利用可能になります

6
David Mendiola

これは私のために働きます:

  describe "numbers" do

    shared_examples "a number" do |a_number|
      let(:another_number) {
        10
      }

      it "can be added to" do
        (a_number + another_number).should be > a_number
      end

      it "can be subtracted from" do
        (a_number - another_number).should be < a_number
      end
    end

    describe "77" do
      it_should_behave_like "a number", 77
    end

    describe "2" do
      it_should_behave_like "a number", 2
    end
  end
1
z5h