算法自動化測試的挑戰與思考

1、背景

從入職到如今已經有3個多月了,從最初的對於電商廣告業務和算法測試的一頭霧水,到如今的漸漸瞭解,基本上已經能夠勝任項目的常規質量保障任務。然而,目前的質量保障手段依然停留在手工測試層面,自動化相對來講依然是比較空白。git

關於持續集成和自動化,早已不是新鮮的話題。可是搜了下內網上關於自動化的一些話題,發現最近的一些文章仍是有很多關於自動化價值的討論,我以爲自動化測試其實跟任何一種其它測試類型(包括功能測試、異常測試、性能測試、穩定性測試等)同樣,它自己屬於測試範疇的一種。既然是測試,咱們首先要明白的是「測試需求」是什麼。盲目地爲了自動化而自動化,致使自動化使用姿式不當或者目標不明確,甚至不知道痛點在哪,是沒法將自動化作好的。github

以前在TesterHome發表過一篇關於自動化的文章《我對自動化測試的一些認識》,可能隨着當前行業測試技術的快速發展,有一些技術手段已經有些陳舊,可是其中的大部分觀點至少到目前爲止與當前本身的思想仍是比較一致的。歡迎有興趣的測試同窗一塊兒探討,對不足之處進行指正批評。web

2、算法測試的痛點

目前我負責的是廣告算法的質量保障工做,測試開發比將近1:20,按目前的狀況來看,開發數量還有增大的趨勢。整個團隊並行在推動的項目可能在10個左右,整體來講測試資源很是緊張。算法

一方面,做爲一個測試開發同窗,在兼顧業務保障的同時,每每還須要保障多個組內外平臺及工具的開發或者其餘流程溝通推進的相關工做。另外一方面,咱們的開發同窗其實都有較高的質量意識,有強烈的自測訴求,可是缺少高效的自測手段。數據庫

所以,如何將項目測試過程固化沉澱、造成自動化保障體系,賦能開發自測,釋放測試本身的資源,是當前不得不進行的一個事情。apache

3、算法業務特色

1. 與網站應用/工程測試的比較

算法由於其自身的特殊性,大部分廣告算法其實是對已有算法的改進和結合,涉及的技術包括點擊率預估、搜索、推薦、圖、NLP、圖像等。以搜索廣告爲例,在流量變現方面,它的主要優化方向集中在兩個方面:排序(點擊率預估、出價優化)和匹配(召回、相關性)。從工程的角度來看,大部分項目對工程結果的影響是廣告商品的排序不一樣或是召回商品的內容和數量變化。不一樣於傳統的網站應用/工程測試(可能會有不斷的新功能的產出),相對來講,若是拋開算法效果測試來看,在功能層面,算法的工程結果是比較穩定的。框架

2. 與傳統接口測試的比較

算法的開發主要包含兩部分:離線任務開發和在線工程開發。離線任務開發包括數據分析、業務建模、特徵提取、模型訓練、模型調參等。在線工程開發主要是將算法模型服務化,以接口的形式提供給外部去調用。從集成測試的角度來看,算法的功能測試能夠歸爲「接口測試」的範疇。工具

傳統的接口測試,除了校驗接口的返回狀態碼是否正確外,比較容易根據業務的處理邏輯對返回的結果字段進行校驗。好比查詢類的get接口,咱們能夠經過接口的返回結果與數據庫的結果進行比較;好比提交類的post接口,咱們也能夠經過調用接口,根據傳入的參數的不一樣,結合對系統的不一樣處理邏輯的瞭解以及數據庫獲得一個肯定的預期返回。post

與之相對的,算法的接口沒有一個肯定的預期。同一個接口,傳入徹底相同的參數,在不一樣的時間段調用可能會返回不一樣的結果。由於不少時候,算法的接口返回是一個機率值,如「某個商品被某個用戶點擊的機率」,影響算法返回結果的因素,除了服務代碼以外,還包括索引的版本、特徵詞典的版本。特徵詞典的版本每每是日更新,而索引包含日級別的全量更新和實時的增量更新。雖然算法的功能相對穩定,可是算法的不斷調整,其實是對同一批接口的不斷調整。性能

3. 當前的主要測試手段

目前算法工程質量的保障,主要仍是集中在在線部分的測試。離線部分由於其時效性,每每會有T-一、T-2的延遲,更多的採用監控保證其質量。而對於在線部分的測試,主要的保障方式包括:

  • CodeReview
  • 功能驗證
  • 線上請求日誌回放
  • 性能測試
  • 穩定性測試

線上請求日誌回放主要是基於線上的access_log日誌,分別在新版本的環境和base環境進行請求回放,比較返回結果各個字段值的差別。是一種對功能驗證的補充,避免人爲地構造數據可能沒法覆蓋線上的全部場景。

4、算法自動化測試的挑戰

前面說了,當前算法自動化測試的目標主要是想解決工程測試方面的效率問題,釋放測試在工程質量保障方面的人力投入,所以本文主要是針對算法的「工程」測試自動化方面的一些思考。

理想的自動化測試鏈路應該是:

  • 代碼提交
  • 靜態代碼檢查
  • 單元測試
  • 代碼打包
  • 詞典更新
  • 測試環境部署
  • 索引更新
  • 功能冒煙迴歸
  • 線上日誌回放
  • 變動代碼覆蓋率統計
  • 模塊壓測
  • 集成壓測
  • 測試報告

整條鏈路的迴歸時間控制在一個小時之內,過程當中既有中間測試結果的即時透出,也有最終報告的展示。下面是對於自動化測試鏈路的各個環節存在的一些挑戰的思考:

1. 代碼提交和管理

目前的開發代碼大部分都是用git去管理,可是並無一個明確且嚴格遵照的代碼分支管理策略,且沒有打Tag的習慣。算法和引擎開發同窗有不一樣的開發習慣:

  • 算法的同窗開發習慣是在線上分支master上拉一個feature分支,用於新版本的開發,而後待feature全量發佈上線後再將feature合回master。
  • 引擎的同窗開發習慣是直接將代碼合到master上提測。

從測試的角度來看,這兩種都存在一些問題:

  • 第一種方式,雖然保證了master一直是穩定可用的版本,可是當有多個同窗並行在此項目上開發多個feature時候,在多個feature先後相繼須要發佈的時候,可能都是基於舊的master分支拉出的代碼,如何相互合併是一個問題。且當feature分支上線後,再合併到master,若是出現conflict,沒法保證解決conflict後的master代碼與線上的代碼一致。
  • 第二種方式,能保證提測的代碼是合併conflict後的最新代碼,同時也是測試經過後上線的真實代碼。可是會影響到master分支的穩定性,當線上出現一些問題,須要緊急回滾的時候可能會出現問題。

在分支管理上不妨能夠參考一些優秀開源項目(如 apache/sparkapache/flinktensorflow/tensorflow等)的廣泛作法:

  • 對於只有一個大版本的代碼,只維護一條master分支。一般大部分項目只有一個大版本,一些特殊的項目可能會存在多個大版本,如SP有3.0版本和2.0版本在線上同時使用,則相應維護兩個分支。
  • 開發時,從master拉代碼到本地進行開發,本地自測完成後合代碼進master,及時解決衝突。
  • 提測時,以tag的方式提測。好比目前要上線的RS服務版本爲v1.0,則第一次提測在master分支上打tag名v1.0.1。若是測試不經過,修改代碼後從新提測,打tag名v1.0.2,依次類推。
  • 最終測試經過後,打一個沒有後綴的tag:v1.0,代表是測試經過的可用版本。
  • 最終上線基於tag:v1.0進行發佈。
  • 當線上驗證經過,且運行穩定後,能夠在上線一週後將v1.0.一、v1.0.2……等過程當中的提測tag刪除,只保留最後上線的穩定版本tag:v1.0。
  • 用一樣的辦法上線v2.0時,若是發生線上問題,須要回滾,能夠當即回滾到tag:v1.0。

2. 靜態代碼檢查

靜態代碼檢查是一項低投入高回報的工程,從集團推出Java開發規約可見其重要性。「低投入」是由於只要一次配置,能夠無限次的檢查。「高回報」是它不只能夠幫咱們糾正代碼書寫規範的一些問題,還能夠發現一些諸如「空指針異常」、「I/O及數據庫鏈接資源使用後未關閉」、「冗餘變量」等一些重大的工程風險。

對於Java,有集團規約插件、PMD、CheckStyle、FindBugs等能夠很方便地使用,而算法的開發則大可能是使用C++,相應的靜態代碼檢查工具還須要調研。目前瞭解到的有cppcheck、clint等。

3. 單元測試

目前RS服務已經使用了Google C++單元測試框架「Gtest」進行單元測試的編寫,可是還處於剛剛起步狀態,這部分須要去推進開發好好地補充測試用例,給出單元測試的覆蓋狀況統計,不讓單測僅僅是流於形式。後續須要將單測的經過率和覆蓋率數據透出到報告中。

4. 算法打包部署

不一樣於Java工程,基於Maven或Gradle,能夠經過命令行很方便地實現整個工程「一鍵編譯打包」,並且目前集團的Java應用大都已經能夠基於Aone平臺很方便地發佈。而算法的發佈由於其索引和詞典的特殊存在,沒法經過Aone很好地集成。算法包的發佈包含三塊內容:so文件(代碼編譯後的結果)、conf(配置)、data(詞典),過程一般包含RPM打包和詞典更新兩個步驟,其中RPM包會包含so文件、conf和部分data。目前不一樣算法模塊發佈的平臺各異,包括suez、drogo、autoweb等等,如何去規整並實現測試環境的自動發佈是一項挑戰。同時,在環境部署完畢後,咱們還要保證新版本環境和base環境索引的一致性,或者當索引的構建也發生改變時,須要保證構建索引的商品庫的一致性。

5. 功能冒煙迴歸

這一塊須要對每一個算法服務的使用場景進行具體的分析和細緻的梳理,好比RS服務,它有來自bp、rsproxy、dump、rspe等不一樣的調用方的請求,每一個調用方的可能的使用場景都須要一一梳理,從而提取出必要的冒煙接口測試用例。前面提到過算法接口每次調用的返回值可能會變化,
所以這部分用例的意義在於檢測服務接口是否針對各個場景有正常的返回,返回結果的各個字段的值是否在一個合理範圍內。

6. 線上日誌回放

相比人爲地構造數據,和AB切流實驗,線上日誌回放是一項相對覆蓋面廣且高效低成本的方式,經過自動化地回放大量的日誌請求,咱們能夠發現新的算法版本是否對某一些不應產生變化的結果字段產生了影響,也能夠發現一部分算法的效果問題:如出價優化時,總體價格是調高了仍是調低了。

7. (變動)代碼覆蓋率統計

Java中有成熟的Jacoco能夠用於工程覆蓋率(深刻到行、方法、類等不一樣級別)的統計,結合git的diff日誌,還能夠去挖掘工程兩個不一樣版本間變化的代碼的覆蓋狀況。而C++的覆蓋率統計方式仍須要調研。

8. 性能壓測

性能壓測包括模塊壓測和集成壓測。模塊壓測指的是如RS這樣單個服務的壓測,而集成壓測是從ha3端或者SP端去看總體性能的狀況。一般,性能的測試都是須要有必定經驗的測試人員基於測試分析來制定詳細的壓測方案並予以執行和結構分析。可是,以前提過,算法的項目發佈有很大的共性,正是基於這些共性,使得自動化壓測成爲了可能。要實現自動化地壓測,除了要編寫通用的壓測腳本,還要有穩定的施壓環境做爲持續集成的節點機器。同時還須要去實現自動化地採集被壓環境的系統性能變化數據(如cpu、內存、磁盤i/o、網卡性能等)。

9. 報告生成

要實現最終報告的自動化生成,須要涉及到整條鏈路的各個環節數據的自動採集,以及各項數據呈現和報表的展現,透出和提煉出對研發過程有幫助的數據,給出相應地測試結論。

5、總結

以上是我的對於算法工程質量保障的一些小小的想法,目的是將本身從「項目輪流轉」的現狀中解放出來。整條鏈路看似冗長,可是羅馬不是一天建成的,我相信只要朝着正確的方向前進,自動化的效果會一步步地顯現出來。

相關文章
相關標籤/搜索