我有一個Rails應用程序,我正在實施Twilio SMS API,並且我對如何測試驅動器的設計感到有些遺憾。使用第三方郵件的Rails TDD?
開始我剛做了一個模型,它是一個封裝了twilio API的SMS郵件程序,我希望能夠測試它並確保功能不會使用SMS信用或用測試文本消息轟擊某人。
我知道如何實現API並讓它在代碼中工作,但我需要幫助的是實際測試代碼以確保它能夠正常工作並防止將來發生破壞。有誰能提供一些建議嗎?
謝謝!
我有一個Rails應用程序,我正在實施Twilio SMS API,並且我對如何測試驅動器的設計感到有些遺憾。使用第三方郵件的Rails TDD?
開始我剛做了一個模型,它是一個封裝了twilio API的SMS郵件程序,我希望能夠測試它並確保功能不會使用SMS信用或用測試文本消息轟擊某人。
我知道如何實現API並讓它在代碼中工作,但我需要幫助的是實際測試代碼以確保它能夠正常工作並防止將來發生破壞。有誰能提供一些建議嗎?
謝謝!
我與測試經驗,並與測試Twilio的應用程序,是你測試,以消除風險您添加。您需要使用Twilio gem,而不是將自己的SMS代碼針對其REST端點進行滾動:這樣可以最大限度地降低風險。
將API儘可能簡化爲包含在業務邏輯類中,並主要測試業務邏輯。例如,在我的系統中,SMSes被髮送出Reminder類。該代碼看起來是這樣的:
class SomeWrapperClass
if (RAILS_ENV == "testing")
@@sent_smses = []
cattr_accessor :sent_smses
end
def send_a_message(to, from, message, callback_url = nil)
unless RAILS_ENV == "testing"
Twilio::SMS.message(to, from, message, callback_url)
else
@@sent_smses << {:to => to, :from => from, :message => message, :callback_url => callback_url}
end
end
end
這讓我寫測試專注於我的業務邏輯,這是我要搞砸了的東西。例如,如果我想要測試一些方法send_reminder(客戶端),它發送一個短信:
test "sends reminder to client" do
SomeWrapperClass.sent_smses = []
client = clients(:send_reminder_test_case)
Reminder.send_reminder(client)
sent_message = SomeWrapperClass.sent_smses.last
assert !sent_message.blank?, "Sending a reminder should fire an SMS to client."
assert sent_message.index(client.name) >= 0, "Sending a reminder should fire an SMS with the client's name in it.
...
end
現在我測試的實際風險,我補充說,這是我搞砸了提醒。 send_reminder。另一方面,包裝應該接近無風險。
顯然儘可能多地分離邏輯。通過這樣做,您可以儘可能多地測試其他所有內容,然後僅將呼叫留給需要測試的外部API。
使用外部API可能會非常棘手。一種選擇是嘲笑你知道會對你有用的事情或對你期待的迴應的反應,但這顯然可能有點脆弱。另一種選擇是看看VCR之類的東西。這將記錄對外部API的調用,並在您再次調用時再次播放。
你可以使用我已經測試過的gem Twilio.rb,然後在你的測試中嘲笑它,與摩卡
Twilio::SMS.expects(:create).with :to => '+19175551234', :from => '+12125551234', :body => 'this is easy!'
你的單元測試不應該打外部服務,他們應該總是被嘲笑。這從單元測試的一般原則可以看出,測試不應該擴展被測試對象的類邊界,並且合作者對象應該被模擬/存根。
希望這會有所幫助!
這傢伙似乎已經開始解決你的問題:https://github.com/arfrank/Fake-Twilio-Api
您可能不需要測試twiliolib的代碼,但是如果您不想存儲twiliolib的方法,那麼您可以使用FakeWeb gem來定義指定請求的響應。
史蒂夫·類似提到的,我剛剛踩滅了請求,在與摩卡:
# In Twilio initializer
TWILIO_ACCOUNT = Twilio::RestAccount.new(TWILIO_CONFIG[:sid], TWILIO_CONFIG[:token])
# In a test helper file somewhere
class ActiveSupport::TestCase
# Call this whenever you need to test twilio requests
def stub_twilio_requests
# Stub the actual request to Twilio
TWILIO_ACCOUNT.stubs(:request).returns(Net::HTTPSuccess.new(nil, nil, nil).tap { |n|
n.stubs(:body).returns("<?xml version=\"1.0\"?>\n<TwilioResponse></TwilioResponse>\n")
})
end
end
我認爲這是一個不好的模式把在執行相關測試代碼。 – 2011-02-02 18:23:20