Raylarda Bir Endişe Nasıl Test Edilir


104

Bir var olduğu göz önüne alındığında Personable, benim Rails bir sahiptir 4 uygulamasını endişefull_name yöntemi bunu RSpec kullanarak test etmeye nasıl devam edebilirim?

endişeler / yakışıklı.rb

module Personable
  extend ActiveSupport::Concern

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

Hangi test çerçevesini kullanıyorsunuz? Ayrıca Personable'ın normal bir Ruby modülü olduğunu da unutmayın. Tıpkı başka bir mixin'i test ettiğiniz gibi test edin.
Lee Jarvis

Vermemiş ActiveSupport::ConcernRaylar çıkarıldı? Biraz önce gittiğini sanıyordum.
Russell

@LeeJarvis FactoryGirl ile birlikte Rspec kullanıyorum
Kyle Decot


4
@Russell Katılıyorum. Bununla birlikte, sadece Rails-y ile aynı fikirde olmadığım bir şeyi yapmak için bir yol izledikleri için sorularına yardım etmem. Her neyse, bu sorunun konusundan kaçmak gibi :-)
Lee Jarvis

Yanıtlar:


176

Bulduğunuz yöntem kesinlikle biraz işlevselliği test etmek için işe yarayacak, ancak oldukça kırılgan görünüyor - sahte sınıfınız (aslında yalnızca Structçözümünüzde bir) includesizin endişeniz olan gerçek bir sınıf gibi davranabilir veya olmayabilir . Ek olarak, modelle ilgili endişeleri test etmeye çalışıyorsanız, veritabanını uygun şekilde ayarlamadığınız sürece nesnelerin geçerliliğini test etmek veya ActiveRecord geri aramalarını başlatmak gibi şeyler yapamazsınız (çünkü kukla sınıfınız bir veritabanı tablo desteğine sahip olmayacaktır. o). Dahası, yalnızca endişeyi test etmekle kalmayıp aynı zamanda endişenin davranışını model özelliklerinizde test etmek isteyeceksiniz.

Öyleyse neden bir taşla iki kuş vurmuyorsunuz? RSpec'in paylaşılan örnek gruplarını kullanarak , endişelerinizi onları kullanan gerçek sınıflarla (örneğin modeller) karşılaştırarak test edebilirsiniz. ve onlar alıştığınız yerde bunları test etmek mümkün olacak. Ve testleri yalnızca bir kez yazmanız ve ardından endişenizi kullanan herhangi bir model spesifikasyonuna dahil etmeniz yeterlidir. Sizin durumunuzda bu şuna benzer bir şey olabilir:

# 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

Bu yaklaşımın avantajları, bir AR nesnesinden daha azının işe yaramayacağı AR geri aramalarını çağırmak gibi endişenizle ilgili şeyler yapmaya başladığınızda daha da belirgin hale gelir.


2
Bunun bir dezavantajı yavaşlamasıdır parallel_tests. Bunun yerine kullanmanın ayrı testler olması daha iyi olacağını düşünüyorum shared_examples_forve it_behaves_like.
Artem Kalinchuk

6
@ArtemKalinchuk Bunun doğru olduğundan emin değilim, github.com/grosser/parallel_tests/issues/168 parallel_tests başına dosya bazlıdır, bu yüzden paylaşılan örnekler bunu yavaşlatmamalıdır. Ayrıca, düzgün bir şekilde gruplandırılmış paylaşılan davranışların, test hızının önüne geçtiğini iddia ediyorum.
Aaron K


1
Bu bağlantıya endişeler dizini eklemekle ilgili hiçbir şey bulamadım. Bunun nasıl yapıldığını açıklar mısınız lütfen? Endişelerimden birinde modülü tanımak için RSpec testimi alamıyorum.
Jake Smith

4
_specShared_examples_for (bu durumda personable_spec.rb) içeren dosya adına eklemeyin , aksi takdirde yanıltıcı bir uyarı mesajı alırsınız - github.com/rspec/rspec-core/issues/828 .
Lalu

63

Aldığım yorumlara yanıt olarak, işte sonunda yaptım (herhangi bir iyileştirme varsa lütfen çekinmeyin) :

spec / endişeler / 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

1
Evet, denilen gerçek bir sınıfı test ederlerse bu diğer testleri bozacaktır Person. Düzeltmek için düzenleyeceğim.
Russell

Bu çalışmıyor. Bana şu hatayı veriyor:undefined method 'full_name' for #<struct first_name="Stewart", last_name="Home">
Kyle Decot

Genişletmek yerine Personable'ı eklemeyi deneyin. Cevabı güncelleyeceğim.
Russell

Şimdi harika çalışıyor. Beni doğru yönü gösterdiğiniz ve yeniden düzenleme yapmama yardımcı olduğunuz için teşekkürler @rusell
Kyle Decot

Harika çalışıyor ve güzel görünüyor
Edward

7

Başka bir düşünce, bunun gibi şeyleri test etmek için with_model gem'i kullanmaktır . Bir endişeyi kendim test etmek istiyordum ve pg_search geminin bunu yaptığını görmüştüm . Tek tek modeller üzerinde test etmekten çok daha iyi görünüyor, çünkü bunlar değişebilir ve ihtiyaç duyacağınız şeyleri spesifikasyonunuzda tanımlamak güzel.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.