[Tommas] 一種有效的測試策略(轉)

在最近的一個大型項目中,咱們在早期就定下了一個目標:不會在軟件中使用大量QA人員專一於手工 測試。經過手工測試發現bug極其耗時且成本高昂,這促使團隊嘗試儘量的將質量內嵌到產品內部。但這並不意味着手工測試毫無價值,由於人們總能在怎樣使用軟件上給你一些特別的驚喜。
  這是一個爲期18個月左右,週期很長的項目,而且後續也會持續更新。 在項目初期,團隊就意識到項目成功的重中之重在於一個優秀的 測試策略,尤爲是讓咱們的團隊可以作到:1)隨着項目時間的推移可以持續的提升團隊的 工做效率。2)無論面對的變動是大是小都可以具備足夠的信心。
  咱們花費了很長時間才肯定了一種有效的策略。這在很大程度上是由於咱們不得不 學習怎樣讓咱們的程序在全部層上都具備可測性。雖然全部的項目團隊成員都具備TDD(測試驅動開發)的經驗,但僅僅這樣並不足以創建有效的測試策略。
   測試分層
  給不一樣的測試分類是一件使人煩惱的事。有 功能測試,集成測試, 單元測試,驗收測試,slow tests,fast tests,UI測試...等等等等。而後咱們發現屬於咱們的測試主要有三種類型:
   系統測試
  皮下測試
  單元測試
  它們之間的區別主要在於被測試內容的範圍。系統測試指的是經過應用的外部接口進行運做,不管對象是一個瀏覽器,文件下拉菜單,隊列,window窗體應用或者其餘的什麼東西。
  皮下測試運行在外部用戶接口之下。若是測試的是Web應用,皮下測試在咱們理解就是指在真實的類
  以及環境部署到位的狀況下,經過命令處理器進行發送的表單對象。繞過UI層邏輯,直接到達domain層。發送表單對象,拋出」成功/失敗」的執行結果。
  對於最底層而言,咱們有單元測試。單元測試用於測試一個類,而且能夠是fast  test 或者 slow test中的一種。Fast Test 便是常規的TDD測試,用於增量的類設計。Test doubles曾被認爲是必要的,可是除非系統交互很是值得關注,不然嚴格的 基於交互的測試 並非那麼有價值。咱們一樣也有slow 單元測試,其一樣可被分類爲 交互測試。固然它們一樣可歸類爲 repository tests, persistence tests等。
  單元:皮下:系統 測試在咱們的測試工做中各自佔的比重差很少是 10:2:1。 爲了完成項目咱們作了大約 5000 個單元測試,1000個皮下測試,500個使用 WaitN 以及 Gallio驅動瀏覽器的系統測試。6000個單元/皮下測試的執行時間大概是10分鐘,而剩下的500個UI測試大概須要50分鐘完成。
   單元測試策略
  單元測試是在嚴密的TDD模式下開發的。咱們在功能實現以前編寫單元測試,並用這些測試驅動代碼設計。這些測試能夠幫助發現設計問題、封裝問題、代碼異味等。
  咱們努力避免編寫純粹用於提供測試的代碼。它們經常意味着咱們有設計問題、責任錯位或封裝已被破壞。
  隨着咱們愈來愈深刻項目管道,咱們對交互測試的重視愈來愈少。 若是你真的對交互感興趣,那麼經過mock進行的交互測試也僅僅是有趣而已。但更多的時候,咱們更感興趣的是附加做用,而交互只是一個實現細節。反之,咱們常常作的是模擬(mock)出過慢或不可測的代碼,好比存儲庫、基於外部服務的外觀、配置類等等。不然,咱們有限的模擬只是模擬了咱們感興趣的那些觀察點。
在大型項目中的某些時間點,爲了提取出能加快功能交付的理念,設計每每須要作大型的重構。在咱們上一個項目中,咱們發掘出了以下理念:
  AutoMapper
  將表單做爲單獨的命令消息處理
  Input builders
  有了以上這些,單元測試是重構時的保障。但只有咱們依賴這些測試來捕獲應用程序中全部有趣的行爲時,纔能有保障的做用。爲了容許有效的大中型重構,咱們須要增長額外的測試層級。
   皮下測試策略
  皮下測試,顧名思義,全部的測試都是在用戶界面之下進行的。在MVC應用程序中,皮下測試是測試控制器下面的全部內容。對於Web service,一切測試都在終端下進行。皮下測試的思想是,應用程序的最上層不執行任何實際的業務邏輯,而只是外部接口與底層服務之間的鏈接。
  皮下測試的重要性體如今咱們但願在拋開如用戶接口和外部服務這類外部鏈接點的狀況下,可以在整個系統運行的同時測試業務邏輯。相對於單元測試關注小模塊的設計,皮下測試關注的不涉及設計,而是測試整個系統的基本輸入和輸出。
  要創建有效的皮下測試,咱們能夠嘗試經過常見的邏輯流程創建uniform pinch points。例如,咱們能夠創建一個命令消息處理系統,或一個普通的查詢界面。在最近的一個處理批處理文件項目上,批處理文件中的每一行都被轉換爲一條消息。而後,咱們創造一條消息,發送給這個系統,而後驗證處理該消息的全部異常狀況。
  因爲皮下測試不是基於設計而是基於高級(業務)行爲,它們是理想的基於場景的測試策略,如BDD或Testcase Class per Fixture模式。若是咱們要進行大的重構,咱們須要這些高層次的測試,爲商業行爲創建全面的安全保障。因爲皮下測試更關注於端對端的邏輯,因此它也是標誌功能點完成的一個重要的目標點。
  雖然皮下測試使咱們可以安全地執行較大的重構,但它仍沒法保證咱們能夠放心地將系統升級到生產環境。
   全系統測試策略
  起初,咱們把全系統測試稱爲「UI 測試」,直到咱們的項目愈來愈多地牽涉到集成策略。這時輸入到咱們系統中的再也不是瀏覽器,取而代之的是消息,來自 REST 端點、FTP 或批處理文件。UI 測試只是全系統測試的一個子集。全系統測試背後的思想是,咱們想按照軟件在生產環境中的使用方式來測試它們。對於一個 MVC 應用程序來講,就是基於瀏覽器的測試。對於批處理文件來講,咱們會使用實際的文件。對於 REST 使用實際的 HTTP 請求。對於消息則使用實際的隊列和消息。
  若是咱們想知道,應用程序在部署到生產環境以前是否能按照預期工做,一個有效並且高效的方法是,建立一個自動化測試來測試整個系統。若是我可讓 UI 測試登陸到應用程序中、建立一個訂單,而後我能夠驗證是否產生了一個訂單請求,那麼我會感受很良好。
  關於全系統測試的一個常見誤區是認爲它就是黑盒測試。然而,全系統測試的特色在於,你必須對系統內部發生的事情瞭如指掌。實際上,全系統測試甚至還能夠利用域模型來生成數據,而不是一個純粹爲測試目的而構建的系統後門。不少團隊容易掉進去的一個大坑是,不按照與生產環境同樣的代碼路徑來測試,這將致使系統處於古怪的、無效的、很難處理的狀態。
  在咱們的項目中,全系統測試代碼是咱們在聲稱一個功能/故事作完以前的所寫的最後代碼。對於描述一個功能的「已完成」特性來講,手工測試的成本過高、並且不可靠。可是,若是我能像在生產環境同樣去測試,經過徹底同樣的外部界面來完成,那這樣的手工測試也算是成功的。
   全盤考慮
  在一個未經測試過的應用程序中,做爲提升覆蓋率的手段,咱們發現實際上最有價值的測試策略是從全系統測試開始,而後往下移,直至單元測試。咱們先作最寬鬆、最簡單的斷言,而後慢慢往下移,直至單元級別的邏輯。在全新開發的應用程序中,咱們傾向於不僅是特別關注某一個區域,由於對於一個須要長期維護的系統來講,全部的測試都很重要。
  這種測試策略確實須要必定的投資。咱們發現,當咱們知道這個應用程序對客戶的業務有決定性做用的時候,這樣的全盤考慮在特別有效。若是一個應用程序對業務有決定性做用,那它將不得不面臨變動。當變動來臨的時候,咱們最好能安全地實施變動而不影響客戶的業務。
相關文章
相關標籤/搜索