2013-05-13 1 views
69

Учитывая, что у меня есть проблема с Personable в моем приложении Rails 4, которое имеет метод full_name, как бы я попытался проверить это с помощью RSpec?Как протестировать проблему в рельсах

проблемы/personable.rb

module Personable 
    extend ActiveSupport::Concern 

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

Какие рамки тестирования вы используете? Также помните, что Personable является обычным модулем Ruby. Протестируйте его так же, как вы проверите любой другой микс. –

+0

Не удалось ли «ActiveSupport :: Concern» удалить Rails? Я думал, что прошло немного раньше. – Russell

+0

@LeeJarvis Я использую Rspec вдоль w/FactoryGirl –

ответ

118

Метод, который вы нашли, наверняка будет работать, чтобы протестировать немного функциональности, но выглядит довольно хрупким - ваш фиктивный класс (фактически только Struct в вашем решении) может или не может вести себя как настоящий класс, который вас беспокоит. Кроме того, если вы пытаетесь проверить проблемы модели, вы не сможете делать такие вещи, как проверка достоверности объектов или вызов обратных вызовов ActiveRecord, если вы не настроите базу данных соответственно (поскольку ваш фиктивный класс не будет иметь поддержку таблицы базы данных Это). Более того, вы захотите не только протестировать концерн, но и проверить поведение концерна внутри своих моделей.

Так почему бы не убить двух зайцев одним выстрелом? Используя RSpec shared example groups, вы можете проверить свои проблемы против фактических классов, которые ими пользуются (например, модели) и, вы сможете протестировать их везде, где они используются. И вам нужно только написать тесты один раз, а затем просто включить их в любую модель спецификации, которая использует вашу озабоченность. В вашем случае, это может выглядеть примерно так:

# 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 = FactoryGirl.create(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 

Преимущество такого подход становится еще более очевидным, когда вы начинаете делать вещи в вашей заботе, как применение AR обратных вызовов, где все меньше объекта AR только что выиграли» т. е. делать.

+1

Одним из недостатков является то, что он будет замедлять 'parallel_tests'. Я думаю, будет лучше иметь отдельные тесты вместо использования 'shared_examples_for' и' it_behaves_like'. –

+4

@ArtemKalinchuk Я не уверен, что это правда, за https://github.com/grosser/parallel_tests/issues/168 'parallel_tests' основаны на файл, поэтому общие примеры не должны замедлить его. Я бы также утверждал, что правильно сгруппированные общие поведения, козырей скорости тестирования. –

+8

Убедитесь включить 'concerns' каталог в' spec_helper.rb' https://github.com/rspec/rspec-core/issues/407#issuecomment-1409871 – Ziggy

37

В ответ на замечания, которые я получил, вот что я в конечном итоге делает (если кто-то улучшения, пожалуйста, не стесняйтесь отправлять их) :

спецификации/проблемы/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 
    personable.full_name.should == "#{personable.first_name} #{personable.last_name}" 
    end 

end 
+1

Да, это нарушит другие тесты, если они будут проверять реальный класс под названием «Человек». Я отредактирую исправление. – Russell

+0

Это не работает. Это дает мне ошибку: 'undefined method 'full_name' для # ' –

+0

Попробуйте включить Личность, а не расширять ее. Я обновлю ответ. – Russell

3

Другая мысль заключается в использовании with_model gem для проверки таких вещей. Я хотел проверить свою заботу и увидел pg_search gem doing this. Это кажется намного лучше, чем тестирование на отдельных моделях, так как это может измениться, и неплохо определить, что вам понадобится в вашей спецификации.

+0

Спасибо. Не видел «with_model» – Subimage

+0

Да, это здорово. Спасибо :) –

+0

Мне кажется, что с_модель - это то, что Райан Бэйтс указал бы, если он все еще делает railscasts. Я скучаю по этому парню. – IAmNaN