一個完美的開發過程是這樣的:測試先行,開發人員會些設計一些邊界場景的測試用例,比如數據的取值范圍從極大到極小、循環語句超出限制范圍等等許多極端情況。這些測試代碼會作為產品代碼的一部分,以自檢代碼或者單元測試代碼的形式與功能代碼放在一起。這種類型的測試,開發人員是最適合、也是最有資格去做的人。
對于功能代碼而言,思維模式是建設,重點在考慮用戶、使用場景和數據流程上;對于測試代碼而言,思維模式是破壞,借用代碼擾亂用戶以及數據。在理想的開發過程里,我們可以把開發人員分為功能開發人員與測試開發人員。
我們還需要一個用戶開發人員,他們主要關心的問題是面向用戶的任務,包括用例、用戶故事、用戶場景、探索式測試等等。
上面的這種烏托邦式的理想開發過程,三種角色分工合作,真是完美啊 O(∩_∩)O~
可惜,這種公司在現階段好像還不存在過,Google 也只是接近這種模式。當前的軟件業的發布周期需要以年為單位的客戶端模式向每周、每天、甚至每小時都會發布的云端模式轉變。Google 的客戶端也按照 “云端模式” 來發布,他們的客戶端都有一個“自動更新”功能。
Google 的軟件測試開發工程師(SET)的職責如下:
在單元測試方面給予開發人員支持。
為開發人員提供測試框架,這樣會方便開發人員編寫一些中小型測試,以利于后期進行更多的與質量相關的測試。
1 開發和測試流程
公開的代碼庫(搜索非常便利)、和諧的工程工具、公司范圍內的資源共享,這些共享服務依賴于 Google 的基礎設施產品,它們會加速項目完成,并且減少了項目失敗的風險。
開發人員在維護這些代碼時,需要遵守這些規則:
所有的開發人員必須復用已經存在的公共庫,除非在需求方面有很好的說服理由。
對于公共的共享代碼,必須能夠很容易被找到,并且具有良好的可讀性,這些代碼必須存儲在代碼庫的共享區域,以便查找。
公共代碼必須盡可能地被復用而且相對獨立。因為與功能的復雜性和設計的巧妙性相比,可復用性帶來的價值更大。
所有依賴必須明確指出。
如果一個開發人員對共享代碼庫中的某段代碼有更好的方案,他可以去重構已有的代碼,并協助依賴在這個公共代碼庫之上的應用項目遷移到新的代碼庫上。Google 設立了一個“同事獎金”,任何人如果受到其他開發人員的正面影響,就可以送出獎金作為感謝。除此之外,經理們還有權使用其他獎勵手段。這么做的目的就是為了這種正向團隊合作形成一種良性的循環,并持續發展下去。
Google 非常重視代碼審核,特別是公共通用模塊的代碼必須經過審核。開發人員必須通過相關語言(C++、Java、Python、JavaScript)的可讀性審核,當開發人員按照約定的代碼風格寫出干凈、簡潔的代碼之后,委員會會授予這名開發人員一個“良好可讀性”的證書。
在共享代碼庫中的代碼,對測試有更高的要求。
最小化對平臺的依賴。所有開發人員的操作系統都盡可能地與 Google 生產環境的操作系統保持一致。對 Linux 發行版本也進行了管理。這樣如果一個 bug 在測試機器上出現時,那么在開發機器和生產機器上應該也能復現。
所有對平臺依賴的代碼,都強制要求使用公共的底層庫。Google 使用的每種編程語言,都要求使用統一的編譯器,這個編譯器針對不同的 Linux 發行版本都會進行持續的測試。限制運行環境可以避免許多與環境相關的那些難以調試的問題。保持簡單,也就相對安全。
使用統一的運行平臺和相同的代碼庫,進行持續集成測試、打包。
整體構建流程如下:
針對某個服務,保證所有相關代碼編譯通過。
設置這個服務的構建目標(Google 中是公共庫、二進制文件或者測試套件,我們假設是公共庫)
編寫一套單元測試用例,所有外部重要的依賴通過 mock 模擬實現。
為單元測試創建一個測試目標。
構建并運行測試目標,有問題就修改代碼,直到所有的測試都運行成功。
運行靜態代碼分析工具,確保遵守統一的代碼風格,且通過一系列常見問題的靜態掃描檢測。
提交代碼,申請代碼審核,根據反饋再做修改,然后運行所有的單元測試并保證順利通過。
這里面包含兩個目標:
庫構建目標:需要新發布的公共庫。
測試構建目標:驗證新發布的公共庫是否滿足需求。
一個 Google 產品由三部分組成:
經過良好測試的獨立庫。
可讀性和可復用性好的公共服務庫。
覆蓋所有重要構建目標的單元測試套件。
為了保證單獨的服務可以并行地開發,服務之間的接口需要在項目的早期確定下來,這樣開發人員就可以依賴于協商好的接口上。為了保證服務級別之間的早期測試,這些接口一般只做了虛假實現。
在構建目標增長到一定規模時,針對功能集成的小型測試會成為回歸測試的一部分。
在以上的活動中,SET 始終是核心參與者。SET 還會同時編寫許多的 mock 工具。
2 SET 角色
SET 也是軟件工程師,是一個 100% 的編碼角色,他會作為測試人員盡可能早地參與到設計和代碼開發流程中去。
SET 是和功能開發人員坐在一起的,這樣更容易融入進去。
在面試 SET 的時候,在代碼要求上與軟件開發工程師(SWE)是一樣的,同時還要求 SET 明白如何去測試 SWE 編寫的代碼。也就是 SET 的要求更高,需要同時了解代碼以及測試的問題。
3 項目的早期階段
許多創新產品(比如 Gmail 和 Chrome OS)都來源于團隊 20% 的業余時間。只有在軟件產品變得重要的時候,質量才顯得重要。
如果一個產品在概念上還沒有完全成型就去關心質量,這是優先級混亂的表現。因此在項目早期就強調測試,是一件非常愚蠢的事情。
Chrome OS 剛開始只有幾個開發人員做了原型,且多數都是腳本和虛假實現,他們拿著只是原型的瀏覽器應用模型做演示,并通過了正式的立項批準。一旦得到正式批準立項,項目的開發總監就會找測試團隊,尋求測試資源。
4 團隊結構
SWE 一般僅在自己的模塊領域內提供最優的解決方案,但從整個產品的角度來看,視野略窄,而一個 SET 不僅要具有更廣的產品視野,而且在產品的整個生命周期中對產品和功能特性都要做充分的理解。
早期的計劃做多少和怎樣做比較合適,由創建項目的負責人來做最終的決定。
Google 的技術負責人一般由工程師擔任,負責設定技術方向、開展合作、充當與其他團隊溝通的項目接口人。
5 設計文檔
在初期,團隊成員一起協同完成設計文檔的不同部分,這些文檔需要技術負責人的審核。SET 在團隊中的優勢就是他們擁有產品方面最廣闊的視野。
為什么要讓 SET 參與審核設計文檔:
SET 熟悉系統設計(通過閱讀所有設計文檔)。
SET 早期提出的建議會反饋在文檔和代碼里。
作為第一個審閱所有設計文檔的人,SET 對整個項目的了解程度超過了技術負責人。
SET 在項目初期就與開飯人員建立了良好的工作關系。
審核設計文檔時,需要帶著一定的目的性:
完整性:找出一些特殊背景知識的地方,鼓勵作者在這方面添加更多的細節,或者增加一些外部文檔的鏈接,作為補充。
正確性:是否有語法、錯字、標點符號等方面的錯誤。
一致性:確保配圖和文字描述保持一致,確保文檔沒有出現與其他文檔在觀點上截然相反。
設計:設計經過深思熟慮。
接口和協議:清晰的定義,完整地描述。
測試:保證系統的可測試性,而且易于測試。
6 接口和協議
Google 采用的是 protocol buffer 語言,它與編程語言和平臺無關,對結構化數據具有可擴展性,但相比 XML 更小、更快、也更簡單。開發人員使用 protocol buffer 的描述語言定義數據結構,然后自動生成源代碼。
7 自動化計劃
SET 要盡早提供一個可供實施的自動化測試計劃。計劃必須合情合理而且有影響力。因為投入的越多,維護的成本也會越大,所以需要保證計劃規模小而且目的性要強。
SET 會先把容易出錯的接口進行隔離,并針對它們創建 mock,這樣就可以控制它們之間的交互,從而確保良好的測試覆蓋率。
SET 會構建一個輕量級的自動化框架,并使用報表和儀表盤來展示收集到的測試結果以及測試進度,整個過程公開透明,這樣獲得的代碼的質量會大大提高。
8 可測試性
SET 要保證系統的可測試性。他是一個質量顧問的角色,為開發人員提供程序結構和代碼風格方面的建議,這樣開發人員才能更好地做單元測試。SET 還提供測試框架方面的建議,使開發人員能夠在測試框架的基礎上寫測試。
開發人員必須有能力進行代碼審查,代碼審查有來自工具和公司文化方面的支持。只有被證明是值的信賴的開發者,才能往代碼庫中提交代碼。
Google 把代碼審查作為開發流程的中心,因此相對于編寫代碼而言,代碼審查更值的炫耀。
代碼已一個“變更列表”(change list,下文會簡稱為 CL)的單元被編寫和封裝起來。CL 會被提交審查,Google 使用代碼審查工具 Mondrian 發送給具有審核資格的 SWE 或 SET進行審查。
如果 CL 很大,那么審查者會要求把數量較大的 CL 分解為數量較小的幾個 CL。有經驗和值的信賴的開發人員會得到“可讀性”的資格,大家同心協力確保整個代碼庫看起來像是由一個人編寫的一樣。
9 測試大小的定義
9.1 小型測試
小型測試就是單元測試。它一般集中精力在函數級別的獨立操作與調用上,這樣的限定可以提供更加全面的底層代碼的覆蓋率:
范圍的隔離而且沒有外部依賴,所以小型測試可以在很短的時間內運行結束。這樣它們就可以執行的比較頻繁,也可以很快發現問題。
9.2 中型測試
中型測試的主要目標是驗證指定模塊之間的交互,也就是集成測試。鼓勵使用模擬技術(mock)來解決外部服務的依賴問題。有的情況下 mock 不能用,那就用輕量級的虛假實現(fake),比如使用常駐內存的數據庫。
9.3 大型測試
大型測試就是系統測試,或者端到端測試。它會依賴外部資源,比如數據庫、文件系統、網絡服務等等。
10 測試平臺
Google 的測試平臺的需要滿足的功能是:
開發人員編譯和運行小型測試,希望立即能夠知道運行結果。
開發人員系統運行一個項目中的所有小型測試,并能夠快速知道運行結果。
只有在代碼變更后,才希望去編譯運行所有相關的測試,并能夠立即知道運行結果。
看到一個項目的測試覆蓋率并查看結果。
對項目的每次代碼變更,都能夠運行這個項目的小型測試,并將運行結果發送給團隊成員以輔助進行代碼審查。
在代碼變更提高到版本控制系統后,自動運行項目的所有測試。
每周都能得到代碼覆蓋率,并實時跟蹤覆蓋率的變化。
當每一個測試都被標注為相應的規模后,調度器可以優化任務隊列,達到合理利用的目的。
Google 的測試系統會監測某個測試任務是否超時,或者消耗的資源超過了這個測試規模所應使用的資源時,會取消它并報告錯誤。
11 測試規模的益處
11.1 小型測試的優缺點
優點:
因為可以很快運行完畢,所以在有代碼變更時就可以立即運行,這樣可以較早地發現缺陷并及時反饋。
可以很容易做邊界場景與錯誤條件的測試。
可以很容易地隔離錯誤。
缺點:
代碼應清晰干凈、規模較小且重點集中。
為了便于模擬,系統之間的接口要有良好的定義。
有時候對依賴資源的模擬是有難度的。
11.2 中型測試的優缺點
優點:
是小型測試到大型測試的過渡。
因為運行速度較快,所以也可以頻繁地運行它們。
缺點:
依賴外部資源,所以本身就具有不確定性。
運行速度沒有小型測試來得快。
11.3 大型測試的優缺點
優點:
是最根本,也是最重要的,因為它們反應了系統是如何工作的。
缺點:
依賴外部資源,所以本身就具有不確定性。
因為測試范疇很寬,所以如果測試運行失敗,要精確定位到失敗的根源比較困難。
準備測試數據很耗時。
大型測試不能像小型測試那樣可以走特定的代碼路徑,所以只能進行功能的常規測試。
小型測試帶來優秀的代碼質量、良好的異常處理以及優雅的錯誤報告。中大型測試帶來整體產品質量和數據驗證。
代碼覆蓋率的結果會存儲在云端,任何開發人員都可以通過內網的網絡,使用瀏覽器來查看這些報告。
總體上的經驗法則是:70% 是小型測試,20% 是中型測試,10% 是大型測試。如果項目是面向用戶的,擁有較高的集成度,或者用戶接口比較復雜,就應該使用更多的中大型測試;如果是基礎平臺或者面向數據的項目,最好有大量的小型測試。
12 測試運行的要求
每個測試與其他測試都是獨立的,它們能夠以任意順序運行。
不做持久化方面的工作。當測試用例測試后,要保證測試環境的狀態與測試用例開始執行之前的狀態是一致的。
-
Google
+關注
關注
5文章
1762瀏覽量
57509 -
工程師
+關注
關注
59文章
1569瀏覽量
68510
發布評論請先 登錄
相關推薦
評論