我試圖測試競爭條件的代碼部分。我遇到的問題與唯一性驗證有關,事實證明,這種驗證在鐵軌中的競爭條件下是不安全的。我相信我可以解決這個問題,但我不知道如何測試我的解決方案。測試競爭條件的軌道,然後清理
我來最接近的是以下(靈感: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,並嘗試了所有不同的策略。另外,有時候我會得到一個關於常量鍵的循環依賴問題。不知道爲什麼,但我猜測它的原因要求不要在Ruby中保持線程安全?
有沒有更好的辦法來解決我的問題?正如我上面指出的那樣,我已經得到了一些不同的問題,我認爲應該存在一個普遍的問題,那就是良好的測試標準應該存在。
1)循環只是一個醜陋的黑客,以確保所有線程同時開始。你對「pod.save」是正確的,我編輯它以匹配我的例子。 2)我必須嘗試一下。我想我在每次測試後都將其配置爲清潔,但您很可能是正確的。 3)是的,這是我使用的解決方案。你是對的,我可以信任數據庫來正確處理它。我還有其他一些可能難以解決的情況,所以測試競態條件的一般方法仍然很棒。 –