字數總計:0 個 | 閱讀時長:0 分鐘 |閱讀次數:

前言

想發揮持續整合的真正作用,一個至關重要的部分就是自動化測試策略。

本章主要討論軟體進入生產環境之前的 「自動化測試管理」 ,包含:

  1. 自動化測試的定位:
    • 包含哪些測試,怎麼分類?
    • 哪些可以被自動化?
    • 本章節主要探討哪些測試?
  2. 傳統自動化測試的困境:
    • 過去常見的一種自動化測試策略模式,它哪些問題?
    • 作為良好自動化測試的一個反例
  3. 如何實踐良好的自動化測試
    • 自動化測試的分層
    • 測試案例的管理、從何開始做自動化測試…

10.1 自動化測試的自身定位

測試領域的4類活動

  1. 「問題認知」:對業務問題本身的理解與認識 (了解測試的目標是什麼)
  2. 「分析」:分析、設計測試流程或實作測試程式碼 (以最低的測試成本,達到驗證的目標)
  3. 「執行」:執行測試,得到測試結果數據
  4. 「決策」:根據測試結果進行下一步行動判斷
  • 其中的「執行」存在大量重複性勞動,自動化測試能夠降低此成本
  • 回歸測試:重複執行以前的全部或部分相同的測試工作
    • 確保過去開發的功能服務都有正常運作
    • 產品生命週期越長,回歸測試案例庫就越大,回歸測試的工作負擔越重

Brian Marick 測試4象限

有很多不同的測試,如何分類?哪些測試可以被自動化?

測試四象限

  • 四個面向
    • 面向業務專家:能與業務專家無障礙溝通 (ex: PM、使用者)
    • 面向技術人員:易與技術人員達成共識 (ex: 開發工程師)
    • 支持編程:目標是為了幫助研發團隊檢查功能需求是否開發完成 (ex: 功能性和UI是否一致)
    • 評判項目:目標是為了找出產品是否有缺限 (ex: 產品是否滿足客戶的實際需求)
  • 四個象限
    • 第一象限:(手動) 用戶演示demo、可用性測試、探索性測試
    • 第二象限:(自動化) 功能驗收測試 => 以用戶的角度
    • 第三象限:(自動化) 系統集成測試、組件測試、單元測試 => 系統角度,技術實現的驗證
    • 第四象限:(自動化/手動) 非功能驗收測試(性能測試、容量測試、可靠性測試…)
  • 本章主要討論第二、第三象限的自動化測試

10.1.1 自動化測試的優勢

相較於手動測試,自動化測試有哪些優勢
(機械自動化 v.s. 人的手動執行)

「減少失誤率,提高準確性」:

  • 機械不受情緒、經驗的影響,每次執行都重覆相同的動作並紀錄詳細的結果

「節省時間和執行成本」

  • 在長生命週期、發佈頻率高的產品中,時間成本的節省相當明顯

「提升測試覆蓋度」:

  • 自動化測試可以增加測試的深度和範圍,以提高軟件質量
  • ex: 內存使用、內部程序狀態…

「做手動無法完成的測試」:

  • 手動測試難做到如摸擬成千上萬個虛擬用戶同時間與軟體進行互動 (mock)

「為開發人員提高質量反饋速度」:

  • 讓開發人員可以方便的執行,快速發現問題

「提高團隊士氣」:

  • 讓團隊可以將時間花在更具挑戰性和更有價值的活動中
  • ex: 探索性測試

10.1.2 自動化測試所需的投入

事物都具有兩面性,自動化測試帶來收益的同時,也會產生成本
成本說明
工具投入成本測試工具、測試框架的研究與培訓
測試案例維護成本功能調整的同時,需維護相對應的測試案例
專業技能人員的成本測試編程、設計規劃的經驗、培訓
設備資源的投入自動化測試無法完全替代手動測試
保留手動測試所需的測試環境,也要為自動化測試的執行準備相應的測試環境

手動測試與自動化測試的不同

自動化測試有很多優勢,但手動測試依舊不可完全被取代
為什麼?兩者的本質上有哪些不同?
  • 自動化測試
    • 無主觀意識,它只做腳本要求它做的事
    • 比較沒有無主動觀察、主動認知和分析的能力,沒有創造力
    • 擅長回答:系統是否照我們「預先設計」的方式正確運行?
    • ex: 用戶功能驗收測試
  • 手動測試
    • 有人為主觀意識的介入
    • 具主動觀察、學習、分析、創造力
    • 擅長回答:我們是否正在開發一個正確的,滿足用戶期望的軟體系統?
    • ex: 探索性測試

自動化測試與手動測試的成本收益對比示意圖

自動化測試與手工測試的成本收益對比示意圖

10.2 突破傳統自動化測試的困境

  • 自動化測試常作為提測前的檢驗標準 (提交給手動測試之前,先運行自動化測試案例)

傳統自動化測試的創建流程

10-3-傳統自動化測試流程

  1. 測試分析者 => 分析測試案例,並文檔化(撰寫測試流程的文檔)
  2. 測試執行者 => 照測試流程文件執行手動測試,發現BUG向開發人員報告
  3. 開發人員 => 修復bug
  4. 測試執行者 => 再次執行測試,直至驗證通過
  5. 測試分析者 => 從測試案例文檔中選出一些重要且變動可能性較小的測試案例
  6. 自動化測試開發者 => 對挑選出來的測試案例編寫自動化腳本,並歸入自動化回歸測試庫

10.2.1 傳統自動化測試的特點

1. 測試案例執行成本過高

  • 處理流程較長、要準備的測試案例較多,需花費較多時間、精力
  • 多為黑盒自動化測試案例,摸擬真實用戶的介面操作來驅動的系統集成測試

2. 自動化測試執行頻率低

  • 通常是在軟件開發完後(提測階段)、或系統回歸測試(重覆以前全部或部份的測試工作)用

3. 質量反饋滯後

  • 大部份的測試案例是回歸測試案例,無法對當前正在開發的新功能進行測試
  • 為了能安全執行,經常會通過 sleep 指令讓流程暫停,再繼續下一流程,因此很耗時

4. 測試環境準備成本高

  • 完善的測試數據集
  • 整套的運行環境
  • 測試環境的搭建手動操作較多,甚至需要多人的參與

5. 測試結果可性度低

  • 受機械硬體配置、網路狀況、案例處理時間長度等影響,可能會產生隨機失敗
  • 若界面需求的改動沒有即時通知測試團隊對測試進行修改,也會造成測試失敗
  • 這些失敗都會造成團隊可能會更傾向於忽略這些自動化測試案例的存在

6. 人員依賴性強

  • 編寫自動化測試案例很大程度依賴少數測試開發專職人員

適合傳統自動化測試的團隊

  • 適合用于發佈版本週期較長,使用傳統瀑布開發方法的團隊
  • 現代軟件版本迭代速度越來越快,這種自動化測試案例的投資回報率越來越低

名詞解釋:

  • 黑箱測試(ex: 功能驗收測試)
    • 把測試軟件當成黑箱,不在乎內部的實作,只在乎輸入輸出結果是否正確
    • 根據用戶說明書、需求文檔,去進行操作、輸入測試
    • 優點:站在用戶的立場進行測試
    • 缺點:無法對程序內部特定的內容進行測試
  • 白箱測試(ex: 單元測試)
    • 把軟體當成透明的盒子,在乎程式內部的運行邏輯,對其結構進行測試
    • 優點:對程式內部的問題進行覆蓋(盡量作到能夠覆蓋到每一行原碼中)
    • 缺點:無法檢驗程式外部的特徵,也無法站在用戶的角度進行測試

10.2.2 自動化測試的分層

  • 本章聚焦的測試類型為
    • 「用戶驗收測試」(用戶角度) 第二象限
    • 「系統集成測試」(系統角度) 第三象限
  • 傳統自動化測試方式產生的測試案例類型通常偏上層測試
    • 形成測試捲筒冰淇淋 (頭重腳輕) => 不利於持續整合
      • 被測範圍較大:執行時間成本、準備成本都很高

測試捲筒冰淇淋

10-4-測試類別與被測對象範圍的對應關係.png

「快、捷、時、信」

良好的自動化測試實踐,應該要「快、捷、時、信」
項目說明
快速測試案例的執行速度要快
(持續整合的要求是,最好在十分鐘以內,不要超過15分鐘)
便捷每名工程師都可方便執行測試,不會影響到他人
及時一但功能發生變化,就能馬上告知本次代碼變更對軟體質量的影響
(若沒有一直開發新測試案例對新功能即時驗證,會導至反饋速度的降低)
可信不存在隨機失敗的現象。
持續整合實踐要求一但自動化測試案例失敗,必須立即修復
隨機失敗會大大增加工程師的無效投入,並降低工程師對持續整合的信心
透過傳統自動化測試的方式,能達到快、捷、時、信嗎?(困難)
快 => 降低時間成本
信 => 提高穩定性
  • 開發上層測試案例成本較高,穩定性差
    • 被測對象範圍較大,測資準備工作量大,執行時間久
    • 有外部依賴,不穩定性也高
  • 降低成本:
    • 減少上層測試案例數量
    • 增加下層測試案例數量
    • 形成穩定的正三角形

10-5-測試金字塔.png

10.2.3 不同類型的測試金字塔

軟體架構發展的趨勢朝「服務化」和「微服務化」發展
掀起大規模分散式應用服務浪潮
  • 服務化:軟體服務由「單體應用架構」拆分成「服務導向的架構(SOA)」
    • 服務之間透過RPC等方式進行溝通(RPC:Remote Procedure Call, 遠端過程呼叫)
  • 微服務化:服務導向架構 => 微服務架構/微核架構
    • 後台服務化模組被拆分成很多的微服務 (微服務架構)
    • 客戶端軟體向元件化或微核架構發展 (微核架構)

10-8-微核架構與微服務架構示意圖

1. 微核架構的測試金字塔

10-9-微核架構的測試金字塔

  • 端到端自動化測試
    • 「摸擬介面操作」 來驅動的自動化測試
  • API自動化測試
    • UI層之下, 「透過API介面」 來驅動下層業務邏輯的自動化測試
  • 元件或外掛間服務的介面自動化測試
    • 「兩個或兩個以上元件(外掛)間」 的功能正確性
  • 元件測試
    • 「單個元件或框架」 本身進行品質驗證
  • 自動化單元測試
    • 最細粒度的自動化測試

2. 微服務架構的測試金字塔

10-10-微服務架構的測試金字塔

  1. 單元測試:
    • 測試目標:驗證 「業務邏輯單元」 的正確性,不在乎上層程式要實作什麼功能
    • 什麼是單元?
      • 軟體中最小可測業務邏輯單元 (一個函式、一個Class)
      • 對外部依賴(如檔案系統、網路等)比較少
    • 測試運行時不需系統處於執行狀態
    • 測試運行速度快
  2. 業務元件或服務測試
    • 測試目標:驗證 「單個元件或服務」 的行為是否符合設計預期
    • 什麼是元件?
      • 由多個最小業務邏輯單元組成
      • 可能與本系統「內部」的其它元件互動,也可能負責與「外部」整合點進行互動
      • ex: GoCD 中的類別 MaterialService,就是負責與Git或Subversion打交道的一個元件
    • 測試通常不需要系統處於執行狀態,但可能涉及外部依賴(檔案系統、網路、資料庫等)
    • 執行進度可能比單元測試稍慢
  3. 契約測試,又稱消費者驅動的契約測試(consumer driven contracts test)
    • 測試目標:「兩個服務之間」 的契約
      • 測試消費者介面與服務者介面之間的正確性
      • 驗證服務者提供的資料是否為消費者所需要的
    • 契約:指軟體系統中各個服務間互動的資料標準格式
    • 10-11-服務間的契約
  4. 業務工作流測試
    • 測試目標:驗證 「多個被測服務」 之間是否可以正常工作,達成某一業務請求
    • 啟動執行兩個以上的微服務,進行業務流程上的測試
  5. 端到端測試
    • 「整個軟體服務」 的流程進行測試
      • 模擬用戶在可視化介面上執行各種操作
      • 若軟體服務對外提供非可視介面的服務(如API呼叫),這類測試也歸屬端到端測試
    • 從用戶的角度驗證整個功能的準確性和可用性
    • 不關注某一細小功能的實作

10.3 自動化測試的實施策略

  • 考慮自動化測試案例的成本,為了更好的投資報酬率,需要更聰明地啟動自動化測試實踐

10.3.1 增加自動化測試案例的著手點

1. 針對代碼熱區補充自動化測試案例

  • 程式碼熱區
    • 程式碼變動頻率相對較高 的檔案或函數
    • 經常出問題 的功能元件
    • 若非程式碼熱區,說明執行穩定,編寫自動化測試的投報率較低

2. 跟隨新功能開發的進度

  • 給目前的功能開發提供即時的品質回饋
  • 若只是在補充原有功能的自動化測試案例,無法即時發揮保護網的作用
  • 多數自動化測試案例由開發工程師自行負責編寫
    • 若同一功能由一人開發,一人編寫測試,就會產生溝通成本
      • (傳統自動化測試的缺點)

3. 從測試金字塔的中間層向上下兩端擴展

  • 上層開發成本高,下層單元測試覆蓋率小,中間投報率最好
  • ex: 採用微服務架構的服務端軟體 => 從契約層開始著手
  • ex: 手機端APP(微核架構) => 從元件級或API級的測試開始入手

4. 自動化測試案例的質量比數量重要

  • 在能達到「驗證品質目的」的前提下,自動化測試的案例越少越好 (降低成本)
  • 「在實作成本最低的測試層級上,進行相應業務邏輯的測試」
    • 不要在不同層級的測試(如單元測試層和元件測試層)中,針對相同的邏輯編寫測試案例
    • 數量夠就好,絕不寫不必要的測試程式碼

10.3.2 提高自動化測試的執行次數

  • 測試執行次數越多 => 成本越低、獲益越高
  • 如何提高執行次數?

1. 共享自動化測試案例 (測試可以被反覆利用,甚至自動化)

  • 反例:
    • 測試只保存在自己的電腦中
    • 測試只能在自己的環境中執行
    • 測試案例無法針對不同環境(如測試環境、預生產環境)進行適配
  • 正例:
    • 將自動化測試案例放到團隊的程式碼倉庫中
    • 整合到持續部署流水線中自動執行

2. 開發人員是自動化測試的第一用戶

  • 每個開發人員,隨時都能非常方便地執行自動化測試案例
    • 將自動化測試作為開發人員日常開發中的一張品質保護網
    • 而非測試人員用來驗收開發人員工作成果的工具

10.3.3 良好自動化測試的特徵

1. 案例之間必須相互獨立

  • 案例間若存在順序依賴
    • 就只能線性執行
    • 執行時間拉長,回饋效率降低
    • 搜尋失敗原因難度提高

2. 測試案例的運行結果必須穩定

  • 不穩定的測試案例只會提供錯誤的品質訊號,浪費團隊的時間

3. 測試案例的運行速度必須快

  • 將一個測試案例分解成多個獨立的測試案例,每個案例僅測原測試案例的一部份
    • => 平行執行
  • 「等待」改為「輪詢」,以很小的時間間隔不斷查詢是否到達下一步執行的狀態
    • => polling 取代 sleep

4. 測試環境應該統一 (最大化測試案例共享的獲益)

  • 反例:測試只能在某測試環境上執行,甚至只能在某開發人員的開發機器上執行
  • 想辦法讓大家的測試環境統一或是讓測試能適配不同的環境

10.3.4 共享自動化測試的維護職責

  • 自動化測試也是軟體程式碼,應花費時間心力使其易於維護,避免程式碼腐爛
  • 自動化測試應盡可能與生產程式碼同步變化
    • 沒有同步變化,執行就會失敗
    • 當執行自動化測試失敗後,就應該馬上進行修改
    • (可能是功能出錯,也可能是測試需要修改)
  • 「破窗效應」:
    • 犯罪學理論:
      • 環境中的不良現象如果被放任存在,會誘使人們仿效,甚至變本加厲
      • 一個廢棄的房子出現了一個破窗沒人理,久了就會越多,甚至出現塗鴉
      • 越來越多測試失敗卻沒有受到關注,久了就對自動化測試的結果視而不見

10.3.5 程式碼測試覆蓋率

  • 有人認為它是非常有用的指標
    • 應該要求達到一定比例的測試覆蓋度
  • 有人認為它是有用的工具,但它
    • 只能告訴你「哪些程式碼缺乏測試案例覆蓋」
    • 卻無法證明「被覆蓋的程式碼就一定是真正經過良好驗證的程式碼」
    • 提供一種錯誤的安全感
  • Google公司並沒有規定測試覆蓋率的統一標準,只有一個建議性標準:
    • 單元測試覆蓋率達到85%
  • Facebook於2004年剛上線時也沒寫自動化測試
    • 業務發展快速、工程師數量大幅增加
    • 交付品質變差、開發人員常常處於救火狀態
    • 2008年始,Facebook正式引入自動化測試實踐
    • Facebook 也無統一規定要寫多少自動化測試
    • Facebook 公司中,自動化測試案例的大多數由開發工程師自己負責

10-12-谷歌公司2014年自動化測試覆蓋率統計圖10-13-谷歌公司不同編程語言的測試覆蓋率統計10-14-2008-2012年Facebook自動化測試案例的增長趨勢

10.4 用戶驗收自動化測試要點

  • 用戶驗收自動化測試處於自動化測試金字塔的最高層,成本最高
  • 開發更多用戶驗收測試前,必須精心準備,以便以較低的成本持續維護比較健康的測試案例集

10.4.1 先搭建分層框架

  • 先選擇適合專案的測試框架,做一定的調整
  • 產生腳本程式後,進行測試腳本程式的分層重構

1. 測試案例的描述層

  • test case 描述

2. 測試案例的實現層

  • 實作 test case

3. 測試案例的接口層(介面層)

  • 把 test case 中 可以重用的東西提取出來

10.4.2 測試案例應保持低位(案例數應保持少量,低成本)

  • 測試案例數量不應太多
  • focus在驗證軟體服務的核心工作流程
  • 實作細節可交由下層的自動化測試案例來覆蓋
  • ex: 驗證系統登入行為時
    • 驗證目標主要在驗證整個登錄流程是否得到正確執行
    • 而不是驗證輸入資訊是否非法
    • 後者可透過更低層次的自動化測試案例來覆蓋

10.4.3 為自動化測試案例預留API

  • 少用模擬圖形介面操作的程式碼
    • 介面操作反應慢
    • 可能會有不容易定位,或執行不穩定的情況
  • 盡量呼叫位於介面下層的API來驅動業務流程的執行

10.4.5 測試數據的準備

  1. 通過一些規則,編寫程序自動生成數據(當規則複雜時,較難編寫程序)
  2. 通過錄制手工測試時產生的數據
  3. 將生產環境的非敏感數據克隆一份,或截取一個片段
  4. 進行生產環境數據的自動化錄制,並保存備份

10.5 其他質量檢查方法

10.5.1 差異批注測試方法

  • 一種半自動測試方法
    • 當做預定義的數據集輸入系統后,收集運行后的輸出結果,對其中需要驗證的數據進行提取,並將提取結果放入文本檔中,通過對比前後兩次測試的結果,用人工批注的方式進行半自動測試。 需要特別注意動態信息(日期時間)的處理,常見的工具包括TextTest和ApprovalTests等。

10-15-差異批注測試方法示意圖

10.5.2 代碼規範檢查與代碼動靜態檢測

  • 代碼風格規範檢查: 是指通過工具 ,依據團隊定義的一些代碼編寫規範,針對源代碼進行檢查,如發現破壞規範的代碼,就加以指正。
    • 工具常用的有 Checkstyle、PMD、SonarQube 等。
    • 增強代碼的可讀性和易維護性。
    • Google 工程師在做代碼評審時,對代碼可讀性要求就非常嚴格。
  • 代碼動靜態檢測: 通過一些工具對產品原始程式碼進行自動化掃描,發現代碼中存在的問題或潛在風險。
    • 靜態掃描: 寫好源代碼後,無須經過編譯器編譯,而直接使用一些掃描工具對進行掃描,找出代碼中存在的一些語義缺陷、安全漏洞的解決方案。
      • 常用的工具包括:lint,Coverity,ColcWork等。
    • 動態分析: 通過在真實或虛擬處理機器上執行目標程序進行分析,比如,在可能的漏洞處插入專門編製的故障發生函數,迫使目標軟體產生異常,然後通過監控程式來檢查是否發生了邊界溢出或者其他異常現象。
      • 常用工具包括:Valgrind,Purify等。
    當代碼庫的規模較大時,這種質量掃描工作可能會花費較長時間。
    1. 應該在提交構建之前,提供增量掃描的方式。
    2. 將完整代碼庫的掃描放到後期執行。
    3. 單獨執行。
    正如我們可能將提交構建與次級構建分開一樣,這也是為了在反饋時間與反饋質量之間取得平衡。

10.5.3 AI在測試領域的應用

  • 在代碼分析、缺陷定位等方面Al工具很多,其他UI、安全性測試也有一些: Appdiff、DiffBlue、BugDojo、微軟AI安全風險檢測工具、Facebook Sapienz等。雖然這些智能測試工具還在探索中,但已經有一些喜人的成果出現。

    例如 2018 月, Facebook的工程網站 code.facebook.com 上,Ke Mao 和 Mark Harman 撰寫了一篇文章,名為《Sapien z: Intelligent automated so ware testing at scale》,講述了 Sapienz 對 Facebook 自身安卓應用進行智能自動化軟件測試的結果,稱:「除能夠加速測試過程以外, Sapienz測試結果的假陽性率極低…… Sapienz的結果報告中,需要修復的比例占75%。」

将人工智能(AI)应用于软件测试中將AI應用於軟件測試中
  1. 查找和修復錯誤,利用AI進行更快速的測試
  2. 利用AI提高DevOps工作效率
  3. 將AI與機器學習相結合
使用AI進行軟件測試
  1. 從單元測試和靜態分析開始
  2. 向金字塔上移至API和UI級別

10.6 小結

  1. 自動化測試案例運行次數越多,平均成本越低,收益越大
  2. 自動化測試案例間應該盡可能獨立,互不影響
  3. 在質量有保障的前提下,自動化測試的案例越少越好
  4. 遺留代碼的自動化測試編寫應從代碼熱區開始
  5. 自動化測試案例從測試金字塔的中間層開始補充,投入產出比最高