Comment puis-je tester: validation d'inclusion dans Rails en utilisant RSpec
J'ai la validation suivante dans mon ActiveRecord.
validates :active, :inclusion => {:in => ['Y', 'N']}
J'utilise ce qui suit pour tester mes validations de modèle.
should_not allow_value('A').for(:active)
should allow_value('Y').for(:active)
should allow_value('N').for(:active)
Y a-t-il un moyen plus propre et plus efficace de tester cela? J'utilise actuellement RSpec2 et shoulda matchers.
Modifier
Après avoir regardé autour de moi, j'ai seulement trouvé, c'est probablement une façon " ok " de tester cela, shoulda ne fournit rien pour cela et quiconque en a besoin peut écrire son propre matcher personnalisé pour cela.(Et sans doute y contribuer en retour au projet). Quelques liens vers des discussions qui pourraient être intéressantes:
3 réponses
Utiliser shoulda_matchers
Dans les versions récentes de shoulda-matchers
(au moins à partir de v2. 7. 0), Vous pouvez faire:
expect(subject).to validate_inclusion_of(:active).in_array(%w[Y N])
Cela teste que le tableau de valeurs acceptables dans la validation correspond exactement à cette spécification.
Dans les versions antérieures, > = v1. 4, shoulda_matchers
prend en charge cette syntaxe:
it {should ensure_inclusion_of(:active).in_array(%w[Y N]) }
Si vous avez plus d'éléments à tester qu'un y/n booléen, vous pouvez également essayer.
it "should allow valid values" do
%w(item1 item2 item3 item4).each do |v|
should allow_value(v).for(:field)
end
end
it { should_not allow_value("other").for(:role) }
Vous pouvez également remplacer le %w()
par une constante que vous avez définie dans votre modèle afin qu'il teste que seules les valeurs constantes sont autorisées.
CONSTANT = %w[item1 item2 item3 item4]
validates :field, :inclusion => CONSTANT
Puis le test:
it "should allow valid values" do
Model::CONSTANT.each do |v|
should allow_value(v).for(:field)
end
end
J'ai trouvé un shoulda matcher personnalisé (dans l'un des projets sur lesquels je travaillais) qui tente de se rapprocher de tester quelque chose comme ceci:
Exemples:
it { should validate_inclusion_check_constraint_on :status, :allowed_values => %w(Open Resolved Closed) }
it { should validate_inclusion_check_constraint_on :age, :allowed_values => 0..100 }
Le matcher essaie de s'assurer qu'il y a une contrainte DB qui explose quand il essaie de l'enregistrer.Je vais tenter de donner l'essence de l'idée. Les matchs? l'implémentation fait quelque chose comme:
begin
@allowed_values.each do |value|
@subject.send("#{@attribute}=", value)
@subject.save(:validate => false)
end
rescue ::ActiveRecord::StatementInvalid => e
# Returns false if the exception message contains a string matching the error throw by SQL db
end
Je suppose que si nous changeons légèrement ce qui précède pour dire @subject.save
et que la validation des Rails explose, nous pouvons revenir false lorsque la chaîne d'exception contient quelque chose qui se ferme correspond au message d'erreur d'exception réel.
Je sais que c'est loin d'être parfait pour contribuer au projet, mais je suppose que ce n'est pas une mauvaise idée à ajouter dans votre projet en tant que matcher personnalisé si vous voulez vraiment tester beaucoup de la validation :inclusion
.