Как в интеграционных тестах rspec/capybara можно реализовать N (последовательных) шагов в качестве N примеров 'itdo'?

Для приложения для обмена сообщениями у нас есть довольно длинные интеграционные тесты. Прямо сейчас, чтобы выполнить заданный сценарий, необходимо выполнить около 20 или 30 шагов в определенной последовательности, потому что шаг N отвечает на данные, созданные на шаге N-1.

Таким образом, в настоящее время они организованы в рамках одного примера «это ... делать»:

describe WidgetController do
  describe "long opt-in opt-out scenario" do
    it "can complete the full sequence" do
      # create an account factory with trait account_type
      # create manager factory for the account
      # 5 people factories opt-in to that account
      # 1 person then opts out
      # a manager creates and sends a broadcast
      # the one opt-out does not get the message
      # the four opt-ins get the message
      # verify the format of the message

Каждый шаг имеет одно или два утверждения для проверки правильности выполнения шага. Итак, в настоящее время у нас есть более 40 утверждений в одном примере it...do, который полностью скрывает то, что на самом деле тестируется.

Мы могли вставлять оператор puts на каждый шаг, чтобы передать описание на выходе, но, безусловно, было бы лучше, если бы наши N шагов можно было обрабатывать как N примеров rspec.

Есть ли способ организовать N последовательных шагов интеграционного теста в виде N отдельных it...do примеров, чтобы (а) они выполнялись последовательно, и (б) состояние сохранялось между шагами, и (в) (в идеале) мы могли продолжать использовать случайное заполнение порядок других тестов, которые мы проводим?


person jpw    schedule 07.10.2012    source источник
comment
задавался тем же вопросом. вы случайно не нашли ответ на этот вопрос?   -  person gingerlime    schedule 13.09.2013


Ответы (2)


Я бы отделил тестирование от подготовки теста, чтобы сделать его чище. Это означает, что в вашем примере для этого одного длинного теста:

  # create an account factory with trait account_type
  # create manager factory for the account
  # 5 people factories opt-in to that account
  # 1 person then opts out
  # a manager creates and sends a broadcast
  --> no asserts until now, because that is test preparation

Вы можете поместить это в before(:all), а затем сделать отдельные тесты:

 before(:all) do
     # no asserts here, just the steps to do it
     # create an account factory with trait account_type
     # create manager factory for the account
     # 5 people factories opt-in to that account
     # 1 person then opts out
     # a manager creates and sends a broadcast

     # so in the end you got:
     @people = ...
     @manager = ...
     @opt-ins = ...
     @opt-out = ...
     @broadcast = ...
 end

 it "should not send the message to the opt-out" do
     # the one opt-out does not get the message
 end

 it "should send the message to the four opt-ins" do
     # the four opt-ins get the message
 end

 it "should have the right message format" do
     # verify the format of the message
 end

Кроме того, вы также должны протестировать шаги before(:all) в отдельных тестах:

it "should be able to create an account with account_type" do
     # create an account factory with trait account_type
     # assert it worked
end

it "should be able to create a manager for an account" do
     # create an account factory with trait account_type
     # no assertion that it worked (that is tested before)

     # create manager factory for the account
     # assert manager got correctly created
end

it "should be able to opt-in to accounts" do
     # create an account factory with trait account_type
     # no assertion that it worked (that is tested before)

     # 5 people factories opt-in to that account
     # assert that it worked
end

it "should be able to opt-in to accounts" do
     # create an account factory with trait account_type
     # 5 people factories opt-in to that account

     # 1 person then opts out
     # assert that it worked
end

Есть небольшое дублирование кода, но это делает тесты простыми и понятными для чтения, поэтому я бы пошел на это.

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

# spec/contexts/big_message_broadcast.rb
shared_context "big message broadcast" do
    before(:all) do
         # no asserts here, just the steps to do it
         # create an account factory with trait account_type
         # create manager factory for the account
         # 5 people factories opt-in to that account
         # 1 person then opts out
         # a manager creates and sends a broadcast

         # so in the end you got:
         @people = ...
         @manager = ...
         @opt-ins = ...
         @opt-out = ...
         @broadcast = ...
     end
end

# spec/.../some_spec.rb
describe "long opt-in opt-out scenario" do
     include_context 'big message broadcast'
     it "should not send the message to the opt-out" do
         ...
     end
     ...
end

Таким образом, вы можете просто использовать include_context 'big message broadcast', чтобы приготовить его где угодно.

person Markus    schedule 27.12.2014

Вы можете попробовать использовать библиотеку Capybara Test Helpers. для инкапсуляции и модульности интеграционных тестов.

Инкапсулируя различные шаги в отдельные вспомогательные методы теста и давая им описательные имена, тест должен стать легче читать.

Еще одно преимущество заключается в том, что после того, как вы разделите поток на разные методы, вы можете получать дополнительные выходные данные, просто включение.

output

person Maximo Mussini    schedule 30.11.2020