2

database_cleaner はほとんどの場合機能しますが、各テストの後に user_id のようなものがクリアされることを期待している場合には機能しません。そのため、user_id はクリアされるのではなく全体を通して増加し、ユーザー ID は 1、2、3、またはテスト用に作成された数として予測できます。期待される結果をハードコーディングする代わりに id を呼び出すことができますが、後でより複雑な例でその内容をクリアする必要があります。これが最も簡単に表示できます。どんな助けでも大歓迎です。

SPEC_HELPER.RB から:

RSpec.configure do |config|

  config.mock_with :rspec
  config.include FactoryGirl::Syntax::Methods

  config.include(Capybara, :type => :integration)
  config.include Devise::TestHelpers, :type => :controller
  config.use_transactional_fixtures = false

  config.before(:each) do
    I18n.default_locale = :en
    I18n.locale = :en
    DatabaseCleaner.start
    ResqueSpec.reset!
    ActionMailer::Base.deliveries.clear
  end 

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.after(:all) do
    TestCleaner.clean
  end

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :transaction
    Role.reset_cache!
  end

  config.after(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

私のテストから:

      it "should return one provider" do
        get :index

        response.body.gsub(/\s+/, "").should == {
            :experts => [{
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 1,
                             :photo => @provider.details.photo.url
                         }] }.to_json
      end

      it "should show return two providers"  do
        @provider2 = create(:provider)
        get :index

        response.body.gsub(/\s+/, "").should == {
            :experts => [{
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 1,
                             :photo => @provider.details.photo.url
                         },
                         {
                             :availability => false,
                             :name => "#{@provider.user.first_name}#{@provider.user.last_name}",
                             :expert_id => 2,
                             :photo => @provider.details.photo.url
                         }
            ] }.to_json
      end
4

3 に答える 3

3

データベース クリーナーは、各仕様をトランザクションにラップし、仕様の最後でそのトランザクションをロールバックして、データベースの変更を削除します。ただし、トランザクションをロールバックしても、主キーの自動割り当てに使用される自動インクリメントまたはシーケンス値はリセットされません。

ID をハードコーディングしないことを強くお勧めします。あなたの例はより複雑になると述べています。その場合、ランダムな整数をコードに散りばめることは、より単純な例よりも保守性がさらに低下します。mysql を使用していると仮定すると、切り捨て戦略を使用すると自動インクリメント値がリセットされますが、速度も大幅に低下します。

于 2012-08-19T15:21:38.480 に答える
1

テストを始めたとき、私はこれにたくさん遭遇しました。最終的に、これはデータベースクリーナーの問題によるものではなく(私も推測したように)、テストを実行するコードの構造によるものであることがわかりました。

before(:each)私が試して説明できる最善の方法は、基本的に、セットアップブロックと実際のit外で何かを行うとshould、実際のテストの「外」になり、これらの問題が発生するということです。

具体的には、ここで問題が発生する可能性があると思います。

  it "should show return two providers"  do
    @provider2 = create(:provider)
    get :index

    response.body.gsub(/\s+/, "").should == {

私はこれをもっと次のようなものに変更したいと思います:

  it "should show return two providers"  do
    before(:each) do { 
      @provider2 = create(:provider)
      get :index
    }

    response.body.gsub(/\s+/, "").should == {
于 2012-08-19T12:17:32.733 に答える
1

データベースが適切にクリーニングされていないのは、リクエスト/統合仕様ですか? もしそうなら、切り捨て戦略ではなくトランザクション戦略でクリーニングしている可能性があります。

これを追加してみてください。これにより、統合仕様のみの切り捨てに戦略が変更されます。

config.before type: :integration do
  DatabaseCleaner.strategy = :truncation
end

Capybara は別のデータベース接続を使用して別のスレッドで実行されるため、統合仕様にトランザクション戦略を使用することはできません。

この記事は、rspec/capybara 用に DB をセットアップするのに大いに役立ちました:クリーンでわずかに高速な spec のための正気の Rspec config

于 2012-08-19T12:03:41.627 に答える