Настройка теста в rspec с несколькими блоками "it" - PullRequest
1 голос
/ 03 сентября 2011

Скажем, у меня есть метод экземпляра, который делает много разных вещей, которые мне нужно проверить, что-то вроде store#process_order.Я хотел бы проверить, что он отправляет электронное письмо клиенту, добавляет запись в таблицу заказов, снимает средства с кредитной карты и т. Д. Какой лучший способ настроить это в rspec?В настоящее время я использую rspec и Factory Girl, я делаю что-то вроде этого:

describe Store do
  describe "#process_order" do
    before do
      @store = Factory(:store)
      @order = Factory(:order)
      # call the process method
      @store.process_order(@order)
    end

    it 'sends customer an email' do
      ...
    end
    it 'inserts order to db' do
      ...
    end
    it 'charges credit card' do
      ...
    end
  end
end

Но это действительно скучно.Действительно ли это правильный способ написать спецификацию для метода, который мне нужен, чтобы убедиться, что он выполняет несколько разных вещей?

Примечание: меня не интересуют ответы о том, является ли это хорошим дизайном.Это всего лишь пример, который я придумал, чтобы помочь с моим вопросом - как писать спецификации такого типа.

Ответы [ 3 ]

2 голосов
/ 03 сентября 2011

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

Этот метод также используется в книге RSpec. Я, безусловно, рекомендую прочитать его, если вы не уверены, что связано с RSpec.

1 голос
/ 05 сентября 2011

Если вы хотите протестировать весь процесс, то речь идет об интеграционном тесте, а не модульном тесте. Если вы хотите проверить #process_order method , который делает несколько вещей, то я ожидаю, что эти вещи означают вызов других методов. Итак, я бы добавил ожидания #should_receive и убедился, что все пути покрыты. Затем я бы специфицировал все эти методы по отдельности, поэтому у меня есть хороший набор спецификаций модулей для всего. В конце я определенно написал бы спецификацию интеграции / принятия, которая проверяет, работают ли все эти части вместе.

Кроме того, я бы использовал #let для настройки тестовых объектов, которая удаляет зависимости между примерами спецификаций (блокирует). В противном случае сбой в одном из примеров может вызвать сбой в другом примере, что приведет к неправильной обратной связи.

1 голос
/ 03 сентября 2011

Я думаю, что вы делаете хорошо, и я думаю, что rspec предназначен для использования.Каждое утверждение (спецификация) вашего приложения получает свой собственный блок.

Вы можете рассмотреть возможность использования before (:all) do, чтобы ордер обрабатывался только один раз, но это может привести к зависимости от порядка выполнения спецификаций.

Вы можете объединить весь код внутри describe "#process_order" в один большой блок it, если хотите, но тогда он будет менее читабельным, и rspec выдаст вам менее полезные сообщения об ошибках в случае сбоя спецификации.Идите в голову и добавьте raise к одному из ваших тестов и посмотрите, какое приятное сообщение об ошибке вы можете получить от rspec, если вы делаете это так, как вы это делаете в настоящее время.

...