J'essaie de tester des parties de mon code pour des conditions de course. Le problème que j'avais était lié à des validations d'unicité, qui, comme il s'avère, n'est pas à l'abri des conditions de course dans les rails. Je crois que je serai en mesure de résoudre le problème, mais je ne suis pas sûr de savoir comment tester ma solution.Test des rails pour les conditions de course, et nettoyage après
Le plus proche que je suis venu est le suivant (inspiré par: 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
Le code ci-dessus est structuré exactement comme le mien, mais les modèles ont changé pour être plus général.
Le test lui-même semble fonctionner correctement. Cependant, les clés créées dans les tests ne sont pas supprimées par la suite. J'utilise DatabaseCleaner et j'ai essayé toutes les différentes stratégies. En outre, parfois, je reçois un problème de dépendance circulaire pour la clé constante. Je ne sais pas pourquoi, mais je suppose que c'est dû à ne pas être thread safe dans ruby?
Y a-t-il un meilleur moyen de résoudre mon problème? Comme je l'ai indiqué ci-dessus, j'ai eu quelques problèmes différents avec ceci, et je pense que cela devrait être un problème suffisamment commun pour que de bonnes normes de test existent.
1) La boucle est juste un bidouillage pour s'assurer que tous les threads démarrent en même temps. Vous aviez raison concernant "pod.save", je l'ai édité pour correspondre à mon exemple. 2) Je vais devoir essayer ça. Je pensais que je l'ai configuré pour nettoyer après chaque test, mais vous pourriez très bien avoir raison. 3) Oui, c'est la solution que j'utilise. Et vous avez raison de dire que je peux probablement faire confiance à la DB pour le gérer correctement. J'ai quelques autres scénarios qui pourraient être un peu plus difficiles à résoudre, donc une façon générale de tester les conditions de course serait encore bonne. –