rspec рефакторинг? - PullRequest
       4

rspec рефакторинг?

3 голосов
/ 22 июля 2010

У меня следующий тест с двумя почти идентичными блоками.Сейчас я ищу способы реорганизовать это чисто.

Тест:

context "with the d1 configuration" do
  before (:each) do
    # send a message 
    @envelope = Factory(:envelope, :destination => '32495xxxxxx', :message => 'Message sent by d1')
    @distributor = Distributor.find_by_name(Distributor::D1)
    @result = @envelope.send_to(@distributor)
  end
  it "should created a new sms-message" do
    @envelope.sent_messages.size.should == 1
  end

  it "should have created one sms-message linked to the envelope and distributor" do
    sms = @envelope.sent_messages.find_by_distributor_id(@distributor.id)
    sms.should be_instance_of(SentMessage)
    sms.external_message_id.should_not == nil
    sms.sent_message_status_id.should == SentMessageStatus::IN_PROGRESS
  end

  it "should add a logline for the creation of the sms-message" do
    @envelope.log_lines.size.should == 2
    @envelope.log_lines.last.message.should =~ /^Sent message/
  end
end


context "with the correct d2 configuration" do
  before (:each) do
    # send a message 
    @envelope    = Factory(:envelope, :destination => '32495xxxxxx', :message => 'Message sent by d2')
    @distributor = Distributor.find_by_name(Distributor::D2)
    @result = @envelope.send_to(@distributor)
  end
  it "should created a new sms-message" do
    @envelope.sent_messages.size.should == 1
  end

  it "should have created one sms-message linked to the envelope and distributor" do
    sms = @envelope.sent_messages.find_by_distributor_id(@distributor.id)
    sms.should be_instance_of(SentMessage)
    sms.external_message_id.should_not == nil
    sms.sent_message_status_id.should == SentMessageStatus::IN_PROGRESS
  end

  it "should add a logline for the creation of the sms-message" do
    @envelope.log_lines.size.should == 2
    @envelope.log_lines.last.message.should =~ /^Sent message/
  end
end

Как вы можете сказать, два идентичных кодовых блока, каждый для другого дистрибьютора, D1 и D2 (вВ нашем проекте они имеют более значимые имена :)) - и теперь мне нужно добавить третьего дистрибьютора.Как мне это сделать?

Я могу зациклить массив, содержащий изменяющиеся части (в данном случае: имя-распространителя и содержимое сообщения).Но могу ли я также изменить название теста?

Каковы лучшие подходы здесь?Можно ли создать какой-нибудь тест-шаблон, в котором вы можете заполнить определенные значения и выполнить их?

Ответы [ 2 ]

4 голосов
/ 22 июля 2010

У меня была сессия парного программирования с более опытным моим коллегой, и вместе мы нашли следующее решение.

Сначала мы определили некоторое общее поведение:

subject {@envelope}
let(:the_sent_message){ @envelope.sent_messages.find_by_distributor_id(@distributor.id)}

shared_examples_for "a typical sent envelope" do
  it{should have(1).sent_messages }
  it{should have(2).log_lines     }
end

shared_examples_for "a successful delivery" do
  it("should have 1 IN_PROGRESS sms-message") { the_sent_message.should be_in_progress }

  it "should have 1 sms-message with external ref" do
    the_sent_message.external_message_id.should_not == nil
  end

  it "should log the delivery success" do
    @envelope.log_lines.last.message.should =~ /^Sent message/
  end
end

shared_examples_for "a failing delivery" do
  it("should have 1 FAILED sms-message") { the_sent_message.should be_failed }

  it "should have 1 sms-message and no external ref" do
    the_sent_message.external_message_id.should == nil
  end

  it "should log the delivery failure" do
    @envelope.log_lines.last.message.should =~ /^Failed to send/
  end
end

и тогда тесты станут более читабельными!

context "delivered by d1" do
  before do
    @distributor = Distributor.find_by_name(Distributor::D1)

    send_a_test_envelope_to(@distributor)
  end

  it_should_behave_like "a typical sent envelope"
  it_should_behave_like "a successful delivery"
end

context "delivered by d2" do
  before do
    @distributor = Distributor.find_by_name(Distributor::D2)

    send_a_test_envelope_to(@distributor)
  end

  it_should_behave_like "a typical sent envelope"
  it_should_behave_like "a successful delivery"
end

и мы также извлекли следующий метод

def send_a_test_envelope_to(distributor)
  @envelope = Factory(:envelope, :destination => '32495xxxxxx', :message => "Message sent by #{@distributor.name}")
  @envelope.send_to(distributor)
end

Теперь я все еще могу применить предложенный ответ, предложенный @Taryn, но я не совсем уверен, что он действительно нужен больше.

2 голосов
/ 22 июля 2010

Да, вы можете перебирать массив / хэш, полный примеров, и да, вы можете переименовывать контексты, основываясь на этом, но вы должны знать о проблемах области видимости - например, контекст - это область уровня класса, но тест это пример. Таким образом, вы должны настроить эти вещи в переменных экземпляра в разделе «настройка» контекста. Я в основном делал это с юнитом: test + shoulda (а не rspec), поэтому я мог несколько испортить правила видимости, но они должны быть похожими

Примечание. Я не тестировал приведенный ниже код, поэтому он может стать причиной подобных проблем ...

# name this better than I have    
CONFIGS = {'d1' => {:name => Distributor::D1
                    :destination => '32495xxxxxx',
                    :message => 'd1 message'}, 
           'd2' => {:name => Distributor::D2
                    :destination => '98765xxxxxx',
                    :message => 'd2 message'}
           } # etc

CONFIGS.each do |display_name, dist_hash|
  context "with the #{display_name} configuration" do
    before (:each) do
      # scope the value-hash here to make it available to test-cases 
      # (you don't have to if you're just using it in the setup section)
      @dist_hash = dist_hash
      # send a message 
      @envelope = Factory(:envelope, :destination => @dist_hash[:destination], :message => @dist_hash[:message])
      @distributor = Distributor.find_by_name(@dist_hash[:name])
      @result = @envelope.send_to(@distributor)
    end
    it "should created a new sms-message" do
      @envelope.sent_messages.size.should == 1
    end

    it "should have created one sms-message linked to the envelope and distributor" do
      sms = @envelope.sent_messages.find_by_distributor_id(@distributor.id)
      sms.should be_instance_of(SentMessage)
      sms.external_message_id.should_not == nil
      sms.sent_message_status_id.should == SentMessageStatus::IN_PROGRESS
    end

    it "should add a logline for the creation of the sms-message" do
      @envelope.log_lines.size.should == 2
      @envelope.log_lines.last.message.should =~ /^Sent message/
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...