2013-04-07 14 views
11

SCENARIO ho estratto un preoccupazione chiamato Taggable. È un modulo che consente a qualsiasi modello di supportare il tagging. Ho incluso questo problema/modulo in modelli come User, Location, Places, Projects.sperimentazione di un modulo preoccupazione/che utilizza ActiveRecord

Voglio scrivere test per questo modulo, ma non so da dove iniziare.

DOMANDA
1. Posso fare dei test di isolamento sul Taggable preoccupazione?
Nell'esempio seguente il test non riesce perché il test sta cercando un dummy_class table. Presumo che stia facendo questo a causa del codice has_many in Taggable quindi, come risultato, si aspetta che 'DummyClass' sia un oggetto ActiveRecord.

# /app/models/concerns/taggable.rb 
module Taggable 
    extend ActiveSupport::Concern 

    included do 
    has_many :taggings, :as => :taggable, :dependent=> :destroy 
    has_many :tags, :through => :taggings 
    end 

    def tag(name) 
    name.strip! 
    tag = Tag.find_or_create_by_name(name) 
    self.taggings.find_or_create_by_tag_id(tag.id) 
    end 
end 


# /test/models/concerns/taggable_test.rb 
require 'test_helpers' 

class DummyClass 
end 

describe Taggable do 
    before do 
    @dummy = DummyClass.new 
    @dummy.extend(Taggable) 
    end 

    it "gets all tags" do 
    @dummy.tag("dummy tag") 
    @dummy.tags.must_be_instance_of Array 
    end 
end 

parte di me pensa se ho appena prova un modello che ha questo modulo incluso all'interno di esso come User che è abbastanza di un test. Ma continuo a leggere che dovresti testare i moduli in isolamento.

Alla ricerca di una guida/strategia su quale sia l'approccio giusto.

+0

Si utilizza '@ dummy_class', e quindi si usa' @ dummy'. Penso che non sia intenzionale. – RubeOnRails

risposta

5

Vorrei suggerire avendo DummyClass essere un generico ActiveRecord::Base bambino con pochissimo codice personalizzato oltre solo include Taggable, in modo che si sarebbe isolando il modulo preoccupazione per quanto possibile, ma ancora di essere una classe di AR. Evitare l'uso di una delle tue classi "reali" come User ti isola ancora da qualsiasi altro codice in quelle classi, il che sembra prezioso.

Quindi qualcosa di simile:

class DummyClass < ActiveRecord::Base; end 

describe Taggable do 
    before do 
    @dummy_class = DummyClass.new 
    end 
    ... 
end 

Dal momento che il DummyClass potrebbe essere necessario interagire realmente con il DB di testare le cose come le associazioni, potrebbe essere necessario creare le tabelle temporanee nel DB durante il test. La gemma temping Ruby potrebbe essere d'aiuto, poiché è stata progettata per creare modelli ActiveRecord temporanei e le relative tabelle di database sottostanti.

interinale consente di creare modelli ActiveRecord arbitrarie supportate da una tabella SQL temporanea per l'uso in test. Potrebbe essere necessario fare qualcosa di simile se si sta testando un modulo che deve essere mescolato nei modelli di ActiveReord senza inoltro su una classe concreta.

+1

Quindi ho provato il tuo approccio prima, ma quando corro i miei test continua a pensare di avere una tabella 'dummy_classes'. ActiveRecord :: StatementInvalid: Impossibile trovare la tabella 'dummy_classes' – alenm

+0

È possibile trovare utile la [temping] (https://github.com/jpignata/temping) gem, vedere la mia risposta aggiornata sopra –

+0

Grazie per il suggerimento sulla gemma temping . Ma stavo pensando perché passare attraverso il processo di utilizzo di questa gemma quando ho potuto testare il modulo in una vera classe ActiveRecord come "User". Forse è l'approccio giusto? Se questo modulo richiede ActiveRecord, prova con esso. Grande gioiello però. – alenm

0

Come suggerito in @ StuartM di answer, utilizzando la gemma temping ha funzionato per me:

# test.rb/spec.rb 
Temping.create :dummy_class do 
    include Taggable 
end 

describe Taggable do 
    before do 
    @dummy = DummyClass.new 
    end 
    ... 
end 
+0

Nota, non ho ottenuto 'DummyClass.create' per funzionare ancora con la gemma temping sfortunatamente – SuckerForMayhem

1

Ecco la mia soluzione del problema simile:

describe Taggable do 
    subject { mock_model('User').send(:extend, Taggable) } 

    it { should have_many(:tags) } 
    ... 

    describe "#tag" do 
    ... 
    end 
end 

Infatti mock_model('User') può deridere qualsiasi esistente modello nel sistema.

Questa non è una soluzione ideale ma almeno è chiara e prende in giro tutto.

Nota: mock_model (archi AR) sono stati estratti in rspec-activemodel-mocks in rspec 3.0.
Inoltre è necessario utilizzare shoulda-matchers per gli abbinamenti di associazioni.

2

Sono andato usando ActiveRecord Tableless piuttosto che Temping gem, che sembra essere un po 'antiquato al momento.

ho impostato la mia prova esattamente lo stesso di Stuart M ha nel suo answer ma incluso il metodo e le colonne has_no_table aiutante richiesto nella mia DummyClass.

class DummyClass < ActiveRecord::Base 
    # Use ActiveRecord tableless 
    has_no_table 
    # Add table columns 
    column :name, :string 
    # Add normal ActiveRecord validations etc 
    validates :name, :presence => true 
end 

questo ha lavorato per quello che mi serviva per testare, che era un modulo che si estendeva ActiveRecord::Base con alcuni metodi aggiuntivi, ma non ho provato con tutte le associazioni has_many quindi ancora non potrebbe aiutare con quello che volevi testare.

Problemi correlati