10

外部データソースに基づいて一連の仕様を動的に生成したいと思います。具体的には、ダウンロードしたGoogleスプレッドシートがあり、スプレッドシートの各行を独自のテストケースに使用する必要があります。

describe "Cases" do
  before(:all) do
    # Download spreadsheet and
    # populate cases in DB
  end

  Cases.each do |case|
    it "Case #{case.num}" do
      # spec
    end
  end
end

これは機能しません。RSpecを使用する初心者の場合、(私が理解しているように)コンパイル時に仕様を参照しないため、before(:all)実行されることはありません。空のitブロックを配置before(:all)すると、が実行されますが、他の何よりも先に評価される問題が発生します。これは、ブロックCases.eachによってまだ入力されていないため、空です。before(:all)

要するに、私は混乱していて、RSpecについての私の理解は非常に限られているように見えます。データを取得し、そのデータを使用して一連の仕様を設定してから、それらをRSpecで実行したいと思います。これは、Casesが事前に(describeブロックの外で)設定された配列である場合は機能しますが、実行時に設定する必要があります。RSpecで何ができるのですか?

4

2 に答える 2

3

ブロックを削除しbeforeます。

describerspec が読み込まれると、a のコードが実行されます。これらの仕様が実行されない場合でも、シートをダウンロードしてスキャンするという欠点があります。

次に対処しなければならない問題は、すべての仕様の後にデータベースが空になることです。そのため、以下で作成された各スペックの before ブロックにデータベースを再設定する必要があります。

私はこれをお勧めしないことを強調しておきます。テスト ケースを動的にプルすることについて深く考えます。コードが外部データなしで機能することを証明する一般的なテストを検討してください。または、スプレッドシートのコピーを取得し、保存してspec/assetsロードし、その特定の例のより簡単なテストを行います。

describe "Cases" do
  # Download spreadsheet and
  # populate cases in DB
  before(:each) do
    # repopulate the DB
  end

  Cases.each do |case|
    it "Case #{case.num}" do
      # spec
    end
  end

  # clean out the db so that the first executed test is not polluted
end
于 2013-01-25T18:03:40.907 に答える
3

これは機能しません... RSpec は ... コンパイル時にスペックを「見る」ことはありません ...

なぜだろうと思い、調べてみました。次のコードと出力を調べると、いくつかの結論を導き出すことができます。

  • Rubyにはコンパイル時間がありません
  • クラス/モジュールの本体はすぐに評価され、実行されます
  • describe方法もそうです
  • ブロックの本体はdescribeRSpec によって即座に処理されます
  • RSpecは後で実行するためにbeforeブロックとブロックを保存しますit
  • ファイルの解析が終了すると、RSpec は describe文字列の報告と保存されたbefore/itサンプル ブロックの実行を開始します。

次のコードはこれを示しています。

module SO
    puts '>>>>> Ruby sees module SO and executes/evaluates its body'
    cases = [1,2,3]

    describe "SO Cases" do
        puts "in module SO, RSpec sees describe Cases self=#{self}"
        before(:each) do
            puts '  in before(:all)'
        end

        cases.each do |case_|
            puts "    in each loop with case_=#{case_}"
            it "Case #{case_}" do
                puts "        check spec for case #{case_}"
            end
        end
    end
end

module M # to avoid "warning: class variable access from toplevel"
    puts '>>>>> Ruby sees module M and executes/evaluates its body'
    describe "M Cases" do
        puts "in module M, RSpec sees describe Cases self=#{self}, ancestors :"
        ancestors.each {|a| puts "    #{a}"}
        print 'self.methods.grep(/^it/) : '; p self.methods.grep(/^it/).sort
        before(:all) do
            puts "  in before(:all) self=#{self}"
            @@cases = [1,2,3]
            puts "  ... now cases=#{@@cases}"
            File.open('generated_cases.rb', 'w') do |fgen|
                fgen.puts 'puts "\n*** inside generated_cases.rb ***"'
                fgen.puts 'module GenSpecs'
                fgen.puts "puts '>>>>> Ruby sees module GenSpecs and executes/evaluates its body'"
                fgen.puts '    describe "GenSpecs Cases" do'
                fgen.puts '        puts "in module GenSpecs, RSpec sees describe Cases"'
                @@cases.each do |case_|
                    puts "    in each loop with case_=#{case_}"
                    fgen.puts <<-IT_SPECS
        it "Case #{case_}" do
            puts "    some spec for case_=#{case_}"
        end
        IT_SPECS
                end
                fgen.puts '    end'
                fgen.puts 'end # module GenSpecs'
                fgen.puts "puts '>>>>> end of ruby file generated_cases.rb <<<<<'"
            end
            puts 'file generated_cases.rb has been closed'
            require_relative 'generated_cases'
        end

        it 'has loaded Cases' do
            @@cases.should_not be_empty
        end
    end
end
puts '>>>>> end of ruby file t2_spec.rb <<<<<'

実行:

$ ruby -v
ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-darwin12.2.0]
$ rspec --version
2.12.2
$ rspec --format nested t2_spec.rb 
>>>>> Ruby sees module SO and executes/evaluates its body
in module SO, RSpec sees describe Cases self=#<Class:0x007fcaf49a6e80>
    in each loop with case_=1
    in each loop with case_=2
    in each loop with case_=3
>>>>> Ruby sees module M and executes/evaluates its body
in module M, RSpec sees describe Cases self=#<Class:0x007fcaf2852e28>, ancestors :
    #<Class:0x007fcaf2852e28>
    RSpec::Core::ExampleGroup
    ...
self.methods.grep(/^it/) : [:it, :it_behaves_like, :it_should_behave_like, :its]
>>>>> end of ruby file t2_spec.rb <<<<<

SO Cases
  in before(:all)
        check spec for case 1
  Case 1
  in before(:all)
        check spec for case 2
  Case 2
  in before(:all)
        check spec for case 3
  Case 3

M Cases
  in before(:all) self=#<RSpec::Core::ExampleGroup::Nested_2:0x007fcaf2836ca0>
  ... now cases=[1, 2, 3]
    in each loop with case_=1
    in each loop with case_=2
    in each loop with case_=3
file generated_cases.rb has been closed

*** inside generated_cases.rb ***
>>>>> Ruby sees module GenSpecs and executes/evaluates its body
in module GenSpecs, RSpec sees describe Cases
>>>>> end of ruby file generated_cases.rb <<<<<
  has loaded Cases

GenSpecs Cases
    some spec for case_=1
  Case 1
    some spec for case_=2
  Case 2
    some spec for case_=3
  Case 3

Finished in 0.01699 seconds
7 examples, 0 failures

ファイルを作成してこのように要求するのはデモンストレーション用であり、あなたのケースではうまくいかないかもしれません。2 つの段階で行うことをお勧めします。最初に、スプレッドシートを読み、describeいくつかのit例を含む file.rb を作成します。2 番目のフェーズでは、Ruby を起動して、生成されたファイルを処理します。

于 2013-01-26T10:28:12.810 に答える