web-dev-qa-db-fra.com

Comment tester un problème dans Rails

Étant donné que j'ai un problème Personable dans mon application Rails 4 qui a un full_name méthode, comment pourrais-je tester cela avec RSpec?

soucis/personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end
95
Kyle Decot

La méthode que vous avez trouvée fonctionnera certainement pour tester un peu de fonctionnalité mais semble assez fragile - votre classe fictive (en réalité juste un Struct dans votre solution) peut ou non se comporter comme une vraie classe qui include s votre préoccupation. De plus, si vous essayez de tester les problèmes de modèle, vous ne pourrez pas effectuer de tâches telles que tester la validité des objets ou appeler des rappels ActiveRecord, sauf si vous configurez la base de données en conséquence (car votre classe factice n'aura pas de sauvegarde de table de base de données). il). En outre, vous souhaiterez non seulement tester le problème, mais également son comportement dans les spécifications de votre modèle.

Alors, pourquoi ne pas faire d'une pierre deux coups? En utilisant les exemples de groupes partagés de RSpec, vous pouvez tester vos préoccupations par rapport aux classes qui les utilisent (par exemple, les modèles) et vous pourrez les tester partout où ils sont utilisés. Et il vous suffit d'écrire les tests une fois, puis de les inclure dans toute spécification de modèle qui utilise votre préoccupation. Dans votre cas, cela pourrait ressembler à ceci:

# app/models/concerns/personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb

require 'spec_helper'

shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb

require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb

require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

Les avantages de cette approche deviennent encore plus évidents lorsque vous commencez à faire des choses dans votre préoccupation, comme invoquer des rappels AR, où rien de moins qu'un objet AR ne suffira.

159
Josh Leitzel

En réponse aux commentaires que j'ai reçus, voici ce que j'ai fini par faire (si quelqu'un a des améliorations, n'hésitez pas à les poster) :

spec/concerne/personable_spec.rb

require 'spec_helper'

describe Personable do
  let(:test_class) { Struct.new(:first_name, :last_name) { include Personable } }
  let(:personable) { test_class.new("Stewart", "Home") }

  it "has a full_name" do
    expect(personable.full_name).to eq("#{personable.first_name} #{personable.last_name}")
  end
end
55
Kyle Decot

Une autre pensée consiste à utiliser le with_model gem pour tester de telles choses. Je cherchais à tester moi-même un problème et j'avais vu le pg_search gem le faisant . Cela semble beaucoup mieux que de tester sur des modèles individuels, car ceux-ci pourraient changer, et il est agréable de définir les éléments dont vous aurez besoin dans vos spécifications.

5
lobati