2013-10-27 3 views
1

Стандарт кодирования, который я работаю, указывает, что группа спецификаций, проверяющих функцию, должна иметь объект, который является вызываемой функцией. Это выглядит следующим образом:Выполняет ли rspec блок `subject`?

define User do 
    context :foo do 
    let(:user) { FactoryGirl.create(:user) } 
    subject { user.foo } 
    it { ... } 
    end 
end 

Типичное использование subject блока для создания экземпляра класса, который вы проверяете:

define User do 
    subject { FactoryGirl.create(:user) } 
    it { ... } 
end 

планируемый эффект нашего руководства стиля является то, что у нас другая тема блок для каждого тестируемого метода. Это замедляет наши тесты? Если бы мы использовали subject в типичной манере, могли бы мы извлечь выгоду из встроенной мемуаризации или других ускорений только из одного предметного блока для каждого класса?

Asside:

Я столкнулся один случай, когда наш стиль не работает. При использовании any_instance.should_receive вы не можете следовать нашему руководству по стилю или спецификация всегда терпит неудачу. Вместо этого вам нужно использовать более традиционный подход, где subject - объект, который вы тестируете, и вы вызываете метод на нем в вашей спецификации.

# passing spec 
define Foo do 
    before { Bar.any_instance.stub(:baz) } 
    subject { FactoryGirl.create(:foo) } 
    it "bazzes Bars" do 
    Bar.any_instance.should_receive(:baz) 
    subject.baz_the_bars 
    end 
end 

# spec follows style guide but fails 
define Foo do 
    before { Bar.any_instance.stub(:baz) } 
    let(:foo) { FactoryGirl.create(:foo) } 
    subject { foo.baz_the_bars } 

    it "bazzes Bars" do 
    Bar.any_instance.should_receive(:baz) 
    subject 
    end 
end 

class Foo 
    has_many :bars 

    def baz_the_bars 
    bars.collect do |bar| 
     bar.baz 
    end.count(true) 
    end 
end 

Есть ли какой-либо другой вопрос, который я должен искать в этом стиле?

+0

Возможно, у меня что-то не хватает, почему ваш стук Бар вызывает проблемы? Субъект еще не вызывается, поэтому утверждение все равно должно быть установлено до запуска метода. – Shepmaster

+0

В блоке 'before' я не забиваю' Bar'. Я улаживаю метод 'baz()', в любом экземпляре 'Bar'. Мой первый проход был: 'before {Bar.stub (: baz)}', который также работал. Но это не прошло обзора кода, поэтому мне нужно было изменить блок 'before'. – user2574255

+0

Извините, я не был понятен - я имел в виду укусить 'baz' на всех« барах ». Тем не менее, я все еще не понимаю, почему ваш тест терпит неудачу. Не могли бы вы обновить свой пример для запуска? 'define' не является допустимым ключевым словом здесь, и я думаю, вы можете отказаться от ссылок на ActiveModel и FactoryGirl. Возможно, это поставит вопрос и на более ответственный вопрос. – Shepmaster

ответ

2

subject лениво создано, per-test, и областью до context/describe, как и let. Не должно быть никаких дополнительных накладных расходов.

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

describe "A thing" do 
    subject(:foo) { FactoryGirl.create(:foo) } 

    # A very complicated object from this method 
    describe "the result of calling frob" do 
    subject(:result) { foo.frob } 

    it { should be_active } 
    it { should be_alive } 
    end 
end 
+0

Извините, если мой вопрос был неясным. Я не спрашивал, есть ли дополнительные накладные расходы для использования 'subject'. Я спрашивал, есть ли дополнительные накладные расходы, чтобы не использовать один и тот же предмет во всем мире. В принципе, есть некоторые воспоминания, которые субъект делает, с которыми мы не пользуемся. Я отредактирую вопрос, чтобы попытаться уточнить. Спасибо за ответ. – user2574255

+0

Ну, я тоже непреднамеренно ответил на этот вопрос - 'subject' запоминается во время одного теста, но это * per-test *, поэтому он каждый раз перезагружается. Вы могли бы иметь тысячи блоков 'subject' (что было бы плохой идеей^_ ^), и единственным дополнительным временем было бы разбор файла. – Shepmaster

+0

Спасибо. Это хорошо знать. У нас есть тысячи блоков 'subject'. Никто никогда не спрашивал меня, если это плохая идея, но все как дела обстоят. Пока команда находится на одной странице, мне все равно, что мы делаем что-то по-другому, чем все. По крайней мере, это то, что я пытаюсь сказать себе :) – user2574255

Смежные вопросы