2013-04-07 14 views
11

SCENARIUSZ ja wybiłem dotyczą nazywa Taggable. Jest to moduł, który pozwala każdemu modelowi obsługiwać tagowanie. Uwzględniłem ten problem/moduł w modelach takich jak User, Location, Places, Projects.Testowanie problemem/moduł, który używa ActiveRecord

Chcę napisać testy dla tego modułu, ale nie wiem od czego zacząć.

PYTANIE
1. Czy mogę zrobić test Izolacja na Taggable niepokoju?
W poniższym przykładzie test nie powiedzie się, ponieważ test szuka numeru dummy_class table. Zakładam, że robi to z powodu kodu has_many w Taggable, więc oczekuje, że 'DummyClass' będzie obiektem 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 

Część mnie myśli, jeśli tylko przetestować model, który ma tego modułu zawarte w jej wnętrzu jak User To wystarczy testu. Ale wciąż czytam, że należy testować moduły w izolacji.

Szukasz wskazówek/strategii dotyczących właściwego podejścia.

+0

Używasz '@ dummy_class', a następnie używasz' @ dummy'. Myślę, że to nieumyślne. – RubeOnRails

Odpowiedz

5

Proponuję o DummyClass być rodzajowe ActiveRecord::Base dziecko bardzo mało niestandardowego kodu oprócz tylko include Taggable, dzięki czemu można byłoby wyodrębnienie Twój moduł obawy jak to możliwe, ale jednocześnie jest klasa AR. Unikanie używania jednej z twoich "prawdziwych" klas, takich jak User, nadal izoluje cię od jakiegokolwiek innego kodu w tych klasach, co wydaje się cenne.

Więc coś takiego:

class DummyClass < ActiveRecord::Base; end 

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

Ponieważ Twój DummyClass konieczne może faktycznie interakcji z DB przetestować rzeczy takie jak stowarzyszenia, być może trzeba utworzyć tymczasowe tabele w DB podczas testów. Ruby gem temping może być w stanie pomóc, ponieważ jest przeznaczony do tworzenia tymczasowych modeli ActiveRecord i ich bazowych tabel bazy danych.

pracy tymczasowej pozwala na tworzenie dowolnych modeli ActiveRecord poparte tabeli tymczasowej SQL do wykorzystania w testach. Być może trzeba będzie zrobić coś takiego, jeśli testujesz moduł, który ma być mieszany w modele ActiveReord bez przekazywania na konkretnej klasie.

+1

Więc wcześniej próbowałem Twojego podejścia, ale kiedy przeprowadzam testy, ciągle myślę, że mam tabelę "dummy_classes". ActiveRecord :: StatementInvalid: Nie można znaleźć tabeli "dummy_classes" – alenm

+0

Może się okazać przydatny klej (temping) (https://github.com/jpignata/temping), zobacz moją zaktualizowaną odpowiedź powyżej –

+0

Dzięki za wskazówkę na temping gem . Ale zastanawiałem się, dlaczego przechodzę przez proces używania tego klejnotu, kiedy mogłem po prostu przetestować moduł w prawdziwej klasie ActiveRecord, takiej jak "Użytkownik". Może to właściwe podejście? Jeśli ten moduł wymaga ActiveRecord, przetestuj go. Świetny klejnot. – alenm

0

Jak sugeruje @ StuartM na answer, używając temping gem pracował dla mnie:

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

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

Uwaga, nie dostałem 'DummyClass.create' do pracy jeszcze z temping gem niestety – SuckerForMayhem

1

Oto moje rozwiązanie z podobnym problemem:

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

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

    describe "#tag" do 
    ... 
    end 
end 

W rzeczywistości mock_model('User') można drwić dowolny istniejący model w systemie.

To nie jest idealne rozwiązanie, ale przynajmniej jest jasne i drwi z wszystkiego.

Uwaga: mock_model (AR mocks) zostały wyodrębnione do rspec-activemodel-mocks w rspec 3.0.
Należy również użyć shoulda-matchers do dopasowywania skojarzeń.

2

Poszedłem z wykorzystaniem klejnotu ActiveRecord Tableless zamiast Temping, który wydaje się być trochę przestarzały w tej chwili.

Skonfigurowałem test dokładnie tak samo, jak Stuart M w jego answer, ale zawierał pomocnika i kolumny wymagane w mojej 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 

To działało na to, co potrzebne, aby sprawdzić, który był moduł rozszerzony ActiveRecord::Base z kilku dodatkowych metod, ale nie próbowałem go z wszelkimi has_many stowarzyszeń tak nadal nie może pomóc z tym, co chcieliśmy testować.

Powiązane problemy