J'ai la validation suivante dans mon ActiveRecord.
validates :active, :inclusion => {:in => ['Y', 'N']}
J'utilise les éléments suivants 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)
Existe-t-il un moyen plus propre et plus efficace de tester cela? J'utilise actuellement RSpec2 et des matchers shoulda.
[~ # ~] modifier [~ # ~]
Après quelques recherches, je n'ai trouvé, c'est probablement une façon `` ok '' de tester cela, shoulda ne fournit rien pour cela et toute personne qui en a besoin peut écrire son propre matcher personnalisé (et probablement le contribuer de nouveau au projet) . Quelques liens vers des discussions qui pourraient être intéressantes:
Dans les versions récentes de shoulda-matchers
(au moins à partir de la 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 booléen O/N, 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 la %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 adaptateur de shoulda personnalisé (dans l'un des projets sur lesquels je travaillais) qui tente de s'approcher pour 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 de base de données qui explose quand il essaie de l'enregistrer. J'essaierai de donner l'essence de l'idée. Les matchs? la mise en œuvre 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 modifions légèrement ce qui précède pour dire @subject.save
et laissez Rails explose, nous pouvons retourner false lorsque la chaîne d'exception contient quelque chose qui 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 ne serait pas une mauvaise idée d'ajouter à votre projet en tant que matcher personnalisé si vous voulez vraiment tester beaucoup de :inclusion
validation.