1

競合状態のコードの一部をテストしようとしています。私が持っていた問題は、レール内の競合状態から安全ではないことが判明した一意性検証に関連していました。私は問題を解決することができると信じていますが、自分のソリューションをテストする方法がわかりません。競合状態のテストとその後のクリーニング

私は(に触発さ:http://blog.arkency.com/2015/09/testing-race-conditions/):次のようである来て最も近い

test "Can't create duplicate keys with same value and keyboard" do 
    assert_equal(5, ActiveRecord::Base.connection.pool.size) 
    begin 
    concurrency_level = 4 
    keyboard = create :keyboard 
    should_wait = true 

    statuses = {} 

    threads = Array.new(concurrency_level) do |i| 
     Thread.new do 
     true while should_wait 
     begin 
      # Unique validation for key values exists scoped to keyboard 
      key = keyboard.keys.new(value: 'a') 
      statuses[i] = key.save 
     rescue ActiveRecord::RecordNotUnique 
      statuses[i] = false 
     end 
     end 
    end 
    should_wait = false 
    threads.each(&:join) 

    assert_equal(1, keyboard.keys.count) 
    assert_equal(1, statuses.count { |_k, v| v }) 
    assert_equal(3, statuses.count { |_k, v| !v }) 
    ensure 
    ActiveRecord::Base.connection_pool.disconnect! 
    end 
end 

上記のコードは、まさに私のように構成されているが、モデルは、より一般的になるように変更しました。

テスト自体は問題なく動作しているようです。ただし、テストで作成されたキーはその後削除されません。私はDatabaseCleanerを使用しています。私はすべての異なる戦略を試しました。また、時には、定数キーの循環依存関係の問題が発生することがあります。理由は分かりませんが、私はルビのスレッドセーフではないことを要求しています。

私の問題には良い方法がありますか?上記で指定したように、私はこれにいくつかの異なる問題を抱えており、良いテスト標準が存在するはずの共通の問題であると感じています。

答えて

1

いくつかのこと:

1)おそらく自分の無知が、true while should_waitラインは、私には間違っているようです。 while should_wait doのようなものは、あなたが意図しているもののように思えます。あなたはpod.saveと呼んでも意味がないと思われるので、これはあなたが使っているコードとまったく同じではないと思います。

2) "切り捨て"戦略を使用すると、テストが実行されたときにすべてのテーブルを切り捨てると思うので、データベースクリーナーが機能すると思います。私の野生のお尻は、あなたが統合テストのためだけに実行するように設定したことです。これは単体テストなのです。そうでない場合は、テストの最後にDatabaseCleaner.truncate(または明示的に)を呼び出して、それが機能するかどうかを確認してください。

3)DB内のユニークなインデックスの問題を解決できますか?データベースを信頼するだけで、このテストの必要性はまったくなくなります。一意でない値を取得すると、コード内の非妥当性検査でその値を処理できます。あなたが保存するたびに余分なSQL呼び出しを行う必要がないので、非常に高速です。

4)なぜ循環依存関係の問題が発生しているのかを知ることは不可能です。私は以前にその問題を抱えており、ファイルの先頭にputs callerを入れて診断を試みました。

+0

1)ループは、すべてのスレッドが同時に起動することを確認するためにちょっと醜いハックです。あなたは "pod.save"に関して正しいと思っていました。私はそれを私の例に合うように編集しました。 2)私はそれを試してみる必要があります。私は各テストの後にそれをきれいにするように設定したと思ったが、あなたは正しいかもしれない。 3)ええ、それは私が使っている解決策です。そして、あなたは正しく、それを正しく処理するためにDBを信頼することができます。私はもう少し解決するのが難しいかもしれないいくつかのシナリオを持っているので、競合状態をテストするための一般的な方法はまだ素晴らしいでしょう。 –