單元測試很棒。在假定一些數據的環境下,能順利通過測試的系統就可算是一個好系統。
不過,現在可以直連外部資源的集成測試才讓程序更有價值。誰知道那些內容商(供應商,vendor)會做出什么傻事來!
很多人一直嘗試著讓測試達到100%的代碼覆蓋率,這是很棒的想法,但我倒覺得它有些基本概念上的問題。LosTechies, Ryan Svihla 提出了"反模式(anti-pattern", 有個有趣的觀點: “多數應用都需要與外部資源交互”。他們有許多不錯的論點,比如:
大多數的單元測試都需一個運行著的數據庫、網頁或應用服務器。
確實如此。
全是同數據和外部系統相關的
我下面將要證明多數Bug并不來源于程序本身,而是由從外部輸入的數據所引起的。
為什么? 因為通常Bug出現在實際的工作環 境中,我們的程序總會處理不好那些外部系統輸入的原始數據,或者程序輸出到外部系統中的數據。而"單元測試"或TDD中所強調的是提供一組假定的數據,檢 驗程序是否能夠按照預期的方式運行。也就說整個測試是在一個假定環境下進行的。這就是為什么接口總是如此輕易就成功運行了。在這之上還可以達到自動化,預 測試性,以及可重復的測試。但是仍有很多系統無法解決現實的問題。
因為這樣的測試方式所能解決的僅是軟件開發要面對的問題中的一部分。如何才能發現真正的問題?最終還是要讓你的軟件與它的外部資源連接起來運行才能發現。
舉個略為抽象的例子:
1) 一些來自外部系統的數據.
2) 應用程序開始處理這些數據.
3) 應用程序將處理后的數據發送到外部資源中 (一般是與第1步不同的數據)
4) 外部數據拿到第3步的數據,在處理后再發送到應用程序.
5) 再次接收到數據,并加以處理.
如此反復。
我們常用mocks/stubs或者類似的程序來產生第1步的數據來進行第2步的測試,而測試第5步時所使用的數據也是使用類似的方式產生的。其中第1步和第4步是不可靠,也是不可預計的,因為你根本不知道外部系統會給你什么數據。
第1步和第4步是程序在上線環境下要面對的,所以它們才是最需要關注的。
外部系統都很挑剔(External systems are finicky mean things)
對于一些e-Commerce系統,或者財務系統,各式的接口,各式的數據在各個系統間流轉。
我們來談一些高層次的問題:
1)理想情況下,當外部系統更改了要發送的數據,無論是是格式(format)或模式(schema),你希望會提前知道。這有些一廂情愿了。最近我曾 與一個電子商務系統,外部數據系統的稅務信息增加了一欄,同時需要應用程序調整內部邏輯。就是外部數據系統已經開始發送數據了,我們才知道的。
2)理想情況下,當外部系統聲稱支持新的API,你應該改變應用程序的內部邏輯,并且發送新數據。最后,你會發現,他們支持新的API,要么在他們的UAT(User Acceptance Test)環境而不在上線(PRODUCTION)的環境,或者只在上線環境中而不在UAT環境中。
3)你的程序已使用關于國內資產的采購信息很順暢了,外部系統和程序的配合也很好。然后開始加入一些國際資產信息時,你可能并不能及時地發現數據已完全變了。
這些都是我曾遇到的場景。我要說就是你在單元測試中根據無法了解到未來面對的環境,只有實際運行時才有辦法。更悲哀的是那些在凌晨3點把你叫起來的問題通常都這樣產生的。
如何完善測試規格(How to setup your Specs)
我做設計也是從規格文檔開始的。規格(specification)其實就是另一種測試(well-crafted tests)。我會區分規格中的單元和集成,并寫不同的代碼。
所謂“單元”的測試規格是測試內部的業務邏輯,看看有沒有把東西都串起來了。就是在測試時提供一些場景,確保程序執行正確的邏輯,輸出期望的結果。
而集成(Integration)的測試規格則和外部資源有關。直接提供一組外部資源數據,以及要返回的數據。這些是集成測試中實際關心的東西。和外部資源的交互才能真正確定程序是否可以正常工作。
[只譯出主要概念,詳細內容請閱讀原文!]
原文地址:More Reasons Why Integration Tests Can Be More Important Than Unit Tests
本文轉載自:http://blog.csdn.net/horkychen/article/details/8685473