3

2 つの重複部分がある機能テストがあります。

require 'spec_helper'

describe "Messages manage" do
  let (:user) { create :user }
  let (:other_user) { create :use }
  before(:each) do
    login_as user
  end

  describe "[message create]" do

    it "messages created by self, should appear on the page", js: true do
      message_text = "Hello my friend"

      visit user_messages_path(user, {with:other_user.id} )
      fill_in :message_body, with: message_text
      click_button t("users.messages.index.send")
      sleep 1 # waiting for js

      page.should have_content(message_text)
      find_field(:message_body).value.should == ""
      page.should have_selector('#message_body', visible: false)
    end

    it "message errors should be displayed", js: true do
      message_text = "123"

      visit user_messages_path(user, {with:other_user.id} )
      fill_in :message_body, with: message_text
      click_button t("users.messages.index.send")
      sleep 1 # waiting for js

      page.should_not have_content("Message: #{message_text}")
      find_field(:message_body).value.should == message_text
      page.should have_selector('.message.error', visible: true)
    end

  end
end

この状況で、shared_examples などを使用する最善の方法は何ですか? 次のDRYへ。

4

2 に答える 2

3

コードのすぐ下に特定のメソッドを追加できます

require 'spec_helper'

describe "Messages manage" do
  # let (:user) { create :user } 
  # Instead expose it as instance variable
  @user = create(:user)
  # let (:other_user) { create :user }
  @other_user = create(:user)
  before(:each) do
    login_as user
  end

  describe "[message create]" do

    it "messages created by self, should appear on the page", js: true do

      # Use the custom method
      send_message "Hello my friend"

      page.should have_content(message_text)
      find_field(:message_body).value.should == ""
      page.should have_selector('#message_body', visible: false)
    end

    it "message errors should be displayed", js: true do

      # Use the custom method
      send_message "123"

      page.should_not have_content("Message: #{message_text}")
      find_field(:message_body).value.should == message_text
      page.should have_selector('.message.error', visible: true)
    end

  end


  def send_message(message_text)
        visit user_messages_path(@user, {with:@other_user.id} )
        fill_in :message_body, with: message_text
        click_button t("@users.messages.index.send")
        sleep 1 # waiting for js
  end

end

より一般的なコードについては、それらをモジュールの仕様/サポートに抽出できます。しかし、この場合は上記の方法で十分です。

于 2013-04-07T04:46:16.033 に答える
2

ブロックを必要とするのに十分な類似のコードがあるとは思わない(ただし、 spec/support/utilities.rbshared_examples_forのユーティリティ メソッドに対して引数を作成することはできます) ので、代わりに少し分割してみました。

@BillyChanの回答に関する議論によると、コーディングのスタイルに大きく依存するため、この質問に対する正しい答えを定量的に与えることは困難です。私のスタイルは、できるだけ簡潔でありながら読みやすいものにすることです乾燥しすぎていると考える人もいれば、十分に乾燥していないと考える人もいます。私はあなたのコードを持っていないので、これが実際に機能するかどうかはわかりませんが、あなたの考慮のために...

require 'spec_helper'

describe "Message management" do

  let(:user)       { create :user }
  let(:other_user) { create :user }

  before { login_as user }

  subject { page }

  describe "message creation" do
    let(:send_button) { t("users.messages.index.send") }

    before { visit user_messages_path(user, { with: other_user.id }) }

    context "by self", js: true do
      let(:message_text) { "Hello my friend" }

      before do
        fill_in :message_body, with: message_text
        click_button send_button
        sleep 1 # waiting for js
      end

      it { should have_content(message_text) }
      it { should have_selector('#message_body', visible: false) }
      specify { find_field(:message_body).value.should == "" }
    end

    describe "message errors", js: true do
      let(:message_text) { "123" }

      before do
        fill_in :message_body, with: message_text
        click_button send_button
        sleep 1 # waiting for js
      end

      it { should_not have_content("Message: #{message_text}") }
      it { should have_selector('.message.error', visible: true) }
      specify { find_field(:message_body).value.should == message_text }
    end
  end        
end

@ole の要求に応じて、詳細な説明を編集します。

specifyのエイリアスですit。ここで使用specifyするのは、このフレーズの方が読みやすいと思うからです ( の代わりに簡単に置き換えることができますit)。また、ブロック内の条件はofにit関連していますが、ブロック内のコンテンツは本質的に を直接参照しておらず、テストの「 を変更しています」。ブロックからのコードを読みやすいと思われるものに入れたい場合は、もう少し冗長なブロックですが、おそらく次のように変更します。subjectpagespecifypagesubjectspecifyit

describe "message errors", js: true do
  let(:message_text) { "123" }

  before do
    fill_in :message_body, with: message_text
    click_button send_button
    sleep 1 # waiting for js
  end

  it { should_not have_content("Message: #{message_text}") }
  it { should have_selector('.message.error', visible: true) }

  describe "message body value" do
    let(:message_body) { find_field(:message_body).value }
    subject { message_body }
    it { should == message_text }
  end
end

let必要に応じて、ステートメントを削除してブロックにfind_field(:message_body).value直接入れることもできます。subjectそれはすべて味とスタイルの問題です。この構文はこの例に適していますか? あなたが決める :-)

于 2013-04-07T05:59:30.577 に答える