你的應用就緒了嗎?
英文原文:Is Your Application Ready?
問題很簡單,卻很難回答。
我們通常會按時間交付軟件,在截止時間之前努力完成所有開發和測試工作。我們會優先完成那些自己覺得重要的部分,當應用達到確定的質量標準后, 就準備上線了。因為發布的內容可能不會盡善盡美,所以我們總是假設將來還有一些版本。甚至我們交付軟件時,都不能辨別應用的就緒狀態。我們總是依賴于測試 人員給我們答復,但為了產品的收益和質量,我們應該讓所有人都參到這個過程中。
在本文中,我們將會圍繞發布一個工作應用程序討論當前流行的幾種不同測試方法。然而,這些不是你“常規”的測試工作!我們強調質量不能變成最后打補丁。我們的目標是在整個編程過程中打造并保證質量。
測試簡史
現在我們的開發項目中有作為職能小組的測試人員,在那之前軟件的用法都很簡單,所以只讓開發人員確保軟件可以工作就夠了。但是隨著項目越來越 大,應用變得更加復雜,發布截止日期也更緊了。因為程序員永遠都不夠用,而且會越來越緊張,所以就要求他們在很短的時間內開發更多的特性。在巨大的“質量 洼地”里長滿了蟲子。我們急需殺蟲劑。
測試人員將成為那些殺蟲劑。隨著職責流轉,測試人員將成為守護者,捕捉從構建中遺留下來的蟲子。很不幸地是,這個主意沒有成功。應用太復雜了, 有太多場景需要測試人員充分覆蓋。即使引入了自動化,測試花費的時間也不可能低于原型開發的時間。而蟲子仍然在那兒,滿地都是。
在最近幾年里,特別是隨著敏捷方法的發展,測試已經在生態系統中有了徹底轉變,自始至終我們都不可能離開測試了。另外,從安裝版軟件,到客戶端/服務器端,再到云和移動應用的轉變,已經決定了應用是否“做好市場準備”會面臨更多的挑戰。
如今的測試非常復雜
通常,我們認為測試是達成可交付軟件的重要環節。但是你仔細想想看,在開發過程中測試無處不在,它肯定不是一個“周期”或者一項“任務”,而是散布在整個產品研發組的一套技能。
一個簡單的例子可以很好地解釋為什么測試不僅僅像最初定義的那樣只是檢查工件。假設你確定了如下需求:記錄應用中的 3 處錯誤將鎖定用戶。這看上去非常直白,但當你開始認真研究時,你會發現很多問題:什么是錯誤?鎖定后會觸發什么?這些“隱性”的需求可能并不明確,而需要 我們理解上下文中的要素。
我們來進一步說明:如果我們捕獲的所有需求都是一成不變的,那么我們如何完成所有測試?你不能在生產環境中測試,所以要在一些預生產環境的服務 器中做功能測試。你需要運行集成測試用例,運行場景腳本,驗證實際的運行情況,然后它自己再完成清理工作。我們也可以在單元測試層面測試這些用例,但需要 模擬數據庫和環境調用。
那只是一個簡單的需求,在測試人員實際操作之前就已經都完成了。
反饋回路
在敏捷時代V模型已經過時了,但即使在今天仍用它來表述一些基本的概念,說明過程中的每個步驟有哪些驗證操作的測試點。
如今我們叫它們“反饋回路”,可以用戴明的 PDCA 循環描述。
我們在敏捷開發中嘗試把這些循環周期變得盡可能簡潔。瀑布項目的問題是循環周期太長,反饋周期超過一周、一月甚至一年。然而,每個開發人員隔幾分鐘都要編譯自己的代碼,他們很清楚:循環周期越短越好。
在不同的情況下我們可以靈活使用這些循環。然而,當我們想要驗證一個工作特性時,就遇到了這樣的現實。
較短的反饋循環不會“恰好發生”。我們需要把它們應用到實踐中。這給時斷時續的“即時編譯”帶來了可能性,因為:
- 我們有促成這種可能性的工具。高效的編譯器大大加快了反饋速度。
- 我們清楚反饋工作的意義,為此創建了一個專門用于反饋的系統。我們的程序每隔幾分鐘就會自己去點擊“編譯”按鈕。甚至如果我們在適當的時間內沒獲得反饋都覺得不太正常了。 </ul>
- 可擴展性:某些框架的設計目的是擴展和自定義。我們通常為用戶提供一些 API,用戶可以用這些 API 擴展一些我們原來沒有想到的功能。當我們確認系統擴展性的時候,創建了用于擴展的模擬器(有時是真正的組件)去檢驗它的運行情況。
- 安全性:有時我們的應用有硬性的安全需求,但是大多數情況下安全性是后期添加的要求,它的難易程度完全取決于每個獨立的開發人員。我們可以使用靜 態代碼分析工具或請外界專家對應用做威脅評估。但很不幸地是,只有在與產品類似的環境下才能執行完整的安全掃描。除非那種像過渡場景下的環境,但這也意味 著還要針對現場服務器做最終的測試。
- 可擴展性和性能:特別是服務器端的應用,我們需要評估的應用的能力不僅是大量請求的響應,還包括未來請求增長時的執行情況。我們使用工具對系統做 壓力測試,根據工具的反饋結果了解系統的性能。此外,我們希望提前預知,為此我們會在一個孤立的系統中執行測試,而不是在會影響到實際用戶的服務器上。
- 可用性和可靠性:系統性能很重要,但可用性是龐大用戶的基礎。此外,我們還要評估應用經受宕機以及其恢復的能力。我們使用壓力工具在獨立的服務器上執行測試用例,應用針對這些用例反饋行為表現。
- 可移植性:在移動領域,我們習慣在多種設備上測試我們的應用。每種設備會有不同的操作系統、內存、資源和性能。隨著每種新設備的上市,在多種設備 上完成測試已經成了一種挑戰。我們為了在短時間內保持有效性一直都在不懈地努力,現在正致力于模擬器的方向。我們用軟件模擬器代替物理設備,確認應用能夠 在多種設備上正常運行。 </ul>
當代碼編譯的速度相當快的時候這是成立的。如果高效的、輕量級的編譯器需要幾個小時的編譯時間就太慢了。這樣我們就無法經常執行它,無法得到反饋,只好從頭再來。
通過隔離快速反饋
為了獲得較短的反饋回路,我們需要削減關注點。例如,為了避免過長的編譯周期,我們可以執行增量編譯。我們可以只編譯變更的部分,而不必等著完 整的編譯都結束。這其實是風險的權衡:我們為了反饋速度犧牲了反饋質量。雖然系統在完整編譯完之后可能會有不同的表現,但是我們假定這些差異并不大。我們 在這種假定的前提下去縮短反饋回路。
以隔離系統和過程的某些部分去獲得更快的反饋并不是新的觀點,在開發過程中出現了很多這樣的想法。即使我們可能不使用這些術語(比如在增量編譯這個案例中),但是會用于其他的場景下,比如需要快速驗證反饋的時候。
驗證和隔離
構建正確的應用:構建錯誤的產品是最大的浪費。我們要在產品開發初期識別正確的需求,甚至可以先做一個原型 系統。產品人員使用各種各樣的工具(包括實體模型、圖紙和原型)去收集需求和反饋意見,驗證還在正確的軌道上繼續開發,或者要做戰略調整(精益創業術 語),改變方向,再次收集反饋,最終回到正軌。
注意這種驗證與原先的V模型需求驗證的差異:我們驗證是否構建了客戶所需的,而不是驗證是否正確構建了規定的需求。在初期,我們不需要實際的應用。以后,我們要不停地收集數據。為了持續地開發和完善,我們需要在實際系統中不斷地收集應用數據。
功能性單元測試:這是非常典型的隔離性應用案例,因為如果不具備好的隔離性,很多功能都無法快速測試。不管你使用模擬框架、依賴注入容器還是簡單的 TDD 和抽象依賴,歸根到底都是把測試從環境中隔離出來。單元測試背后的思想是得到快速反饋,所以顯然要擁有可以達成這一目標的工具。
如果你考慮單元測試的流程和它所要達成的目標,你就會發現以隔離性為基礎構建軟件(例如,SOLID 原則)還有其他好處。我們通常把應用的易維護性看作開發團隊增加新特性、修復缺陷或修改設計的能力。如果流程中沒有快速的測試反饋機制,那么就會面臨風 險,白白浪費時間。
功能性集成測試:我們做單元測試的時候會導致與增量構建相似的后果:快速反饋的代價就是增加了系統內流程未充分測試的內在風險。集成測試更像完整的構建:我們在獲得高質量反饋的同時也要承受“慢”的代價。我們要花時間準備和執行測試,但它們卻能讓我們最終以更好的視角去了解系統的性能。
我們有時會試圖隔離系統的各個方面去縮減這些時間。所以我們可能要模擬瀏覽器操作,在 UI 層下運行包括數據庫代碼的流程。或者,我們可能要在圖形用戶界面(GUI)中執行不涉及數據庫的測試;這需要在反饋質量和速度之間作出取舍。
通訊測試:雖然它是一種特定的集成測試,但通訊測試需要特別拿出來討論,在此我分享一下我的個人經歷:十年 前,我們團隊正在開發一個用于大量硬件軟件接口。這個接口要實現基于 TCP 和 UDP 的通訊。但我們開發的時候硬件還沒有到位。當然,我們可以等,但是我們不想因此影響進度。我們確定了消息信息和結構、通訊連接和恢復以及錯誤處理機制,以 構建網絡模擬器。在那時它還不是自動化的,只是一個展示接收信息的應用,能夠針對請求向我們的軟件發送返回消息。后來我們增加了一些用于不同場景的自動化 處理,比如信號交換。
有了這個模擬器不僅加快了我們的開發和集成速度,它還向我們反饋了通訊組件的開發完成情況,記錄了出現的故障,還能當作參照工具來用。
非功能性需求:很久以前,我們只關心質量。然而今天,我們取得了長足的進步,現在需要關心更多東西,包括:
用戶體驗:最后這一點對于人類用戶來說是無可替代的。這需要測試人員的參與。測試人員站在用戶的角度發出用戶的聲音,回答像這樣的問題:這有益嗎?我能達成目標嗎?這就是我們測試的實際系統。
當剩下的測試都自動化了,那么手工探索性測試就是最后的難題了。測試人員批準之后它就可以上線了。
總結
產品研發復雜且具有風險。我們要確保構建了適當的特性、確保功能的正確性,并為災難和成功做好準備。理解早期反饋工作和越來越多可以做的測試,在交付之前回答我們的問題:是的,它已經就緒。
關于作者
Gil Zilberfeld 從小就從事軟件工作。他做過 20 年的商業軟件開發,具有豐富的軟件方法和實踐經驗。Gil 是 Typemock 的產品經理,在敏捷公司內從事敏捷團隊的部分工作,研發敏捷開發工具。他推動單元測試和其他設計實踐、可落地的敏捷方法,以及某些非常酷的工具。除了每月的在線網絡研討會,Gil 還在國際演討會上做單元測試、TDD、以及敏捷實踐和通訊的演講。他在業余時間里還打打僵尸,呵呵,開個玩笑。Gil 的博客包括不同的敏捷專題:流程、通訊和單元測試。