實踐者的 DevOps 之路(4. 自動化測試)

之前的幾篇文章中我們談到了 DevOps 的分支模型,持續集成,而這次我會說一些 DevOps 中自動化測試的相關話題。

DevOps 一項核心的優勢在於能夠加快產品開發-上線-反饋的循環週期,用每一個更小,更快速的迭代驗證,提升產品的價值。但是在一個如此快速的過程中如何保證產品的質量與穩定性呢?自動化測試在其中扮演了相當重要的角色。

WHY

實踐者的 DevOps 之路(3. 持續集成 CI) 的文章中談到了一個典型 CI 流程應該包含的步驟,其中最重要的一個環節就是自動化測試。之所以自動化測試如此重要,是因爲它不僅提供了快速迭代的質量保障,也爲高速行駛的 DevOps 列車安裝了一道安全閘。在一些交付質量較差,線上 bug 不斷的系統中,我們會發現大多存在着以下的這些問題:

  • 大量的手工測試,複雜的測試用例,但是仍會遺漏重要的業務場景

  • 無法進行有效的迴歸測試,上線的新功能往往引發老功能的 bug

  • 開發人員本地測試不充分,導致開發與測試之間過多的返工,進而降低整個迭代的交付質量

一些開發團隊採取的解決方法無非是兩種,增加開發人員與測試用例的數量,希望用一張更大的「網」來捕獲那些 bug,可惜「網」越大,洞也越多。而另一種解決方案則是增加每個迭代的時間週期,從一週,兩週變爲一個月,並且讓開發批量提交代碼到測試環境,進行集中的測試。這樣的結果就是退化爲了一個小的瀑布模型,雖然從表面上看交付的「吞吐量」提升了,但是交付質量並沒有改變,反而產品的反饋時間大大延遲了。

思考一下這個問題的本質,我們所需要的是一種快速,高效的質量反饋機制,儘可能少的人工干預,每一次代碼的變更都應該觸發這種檢查機制,一旦發現問題就會通知我們,而我們也應該第一時間去修復那些問題。

自動化測試能夠很好的滿足以上這些需求,通過使用 Jenkins 這種 CI 集成工具,能夠非常方便的運行各個層面的測試代碼,在進入手工測試階段之前就最大限度的發現缺陷。

但是既然自動化測試是如此好的一項技術實踐,那麼爲什麼沒有成爲每個項目的必要組成部分呢?

How

實際項目中無法真正用好自動化測試的原因很多,總結下來無非以下幾種:

  • 不重視測試技術,大量依賴手工測試,對自動化測試的技術與理論也不夠了解

  • 過於聚焦在 UI 測試這類繁瑣,不穩定的測試場景,忽略了單元測試,接口測試這類高收益的自動化測試

  • 團隊內部無法有效地推廣類似單元測試這樣的技術,很難從最基礎的實踐開始自動化測試

面對這些問題時,不妨從下面兩點來思考解決的辦法。

老生常談的價值驅動

許多人對測試以及自動化測試的第一個問題往往是:“我項目中的(自動化)測試的覆蓋率應該是多少?”。一般我會問他,現在他項目中的測試覆蓋率是多少?答案往往是 0%。如果是 0% 的話那就很好解決,在編寫新代碼的過程中增加測試吧!

第二個經常被問到的問題是:“測試覆蓋率需要做到 100%嗎?如果不需要,那麼應該做到多少?”。我的答案很簡單,覆蓋率並不是關鍵,關鍵是你要明白需要測試的是什麼。

回到我們都熟悉的「測試金字塔」,如下圖:

整個圖很容易理解,越底層的測試運行速度越快,而且成本越低。反之,越往上運行速度越慢,且成本越高。所以我們應該最大限度的推行單元測試與集成(接口)測試,而有選擇的使用 UI 測試。在我看來單元測試是收益最高,效果最明顯的一種實踐。雖然之前提及測試覆蓋率並不是硬性的指標,但是在一個全新的團隊推行單元測試時可以暫時設定一個覆蓋率的指標,例如 70%,幫助開發人員形成編寫測試用例的習慣。在實際工作中,對於那些類似 DTO 這樣的純數據對象可以不編寫單元測試,因爲它們不沒有太高的價值,只有一些簡單的 set/get 方法。同樣的,對於與數據庫,或是其他外部資源交互的類也可以不編寫單元測試,而是把它們放到集成測試中。單元測試更加應該關注業務邏輯的實現與設計的合理性。

在集成測試與 UI 測試中價值的意義更加凸顯,因爲運行測試,準備數據的代價更高昂,而運行測試的時間也更長。我們應該從業務重要性,風險度的角度出發,分析每個接口與頁面,從而決定是否需要編寫對應的測試用例。

許多項目在推行自動化測試的初期階段,會要求每個接口,每個頁面都需要編寫測試用例。帶來的結果往往是付出了很大的精力與時間,但是由於 UI 變化頻率,集成測試數據準備的原因,測試很不穩定,開發團隊花費了大量時間在測試穩定性上,最後對於整個自動化測試喪失了信心,全盤否定。

先做好單元測試,之後在考慮價值的前提下逐漸增加接口與 UI 的測試覆蓋率纔是一個比較穩妥,易於推行的實踐方法。

必要的技術支撐

很多團隊對於測試技術的瞭解還是停留在 XUnit 與 Selenium 的階段。但是這幾年出現的技術已經大大提升了編寫,運行測試的工作體驗體驗。

使用 Spock 編寫的單元測試代碼更少,但是更具表達力,而各種 mock 框架的引入使得單元測試可以更加關注於類與類之間的交互。Mountebank 這樣的接口測試平臺讓接口測試不再變的繁瑣,可以非常方便的使用 stub 模擬各種接口的返回結果。

TestCafe,Cypress 或是 Puppeteer 讓 UI 測試變的不再像以前那樣繁瑣與脆弱,可以通過框架的 API 非常簡單的模擬各種主流瀏覽器的用戶行爲並驗證頁面的響應。

容器技術與雲平臺的普及,也爲自動化測試帶來了更多的可能性。在一些項目中,我們使用容器化技術,針對每個接口測試快速的生成一個容器化的完整環境,包括各種依賴的中間件與數據庫,完成測試之後即銷燬容器。這樣可以大大減少開發人員的負擔,讓他們不再把編寫接口測試看成一個痛苦的付出,而是對自己工作的一張安全網,更加願意去編寫測試用例。

What

在 DevOps 中我們應該追求怎樣的自動化測試?我的答案就是下面的這幾點:

  • 不要盲目追求覆蓋率,而是思考業務上的價值(重要性與風險)

  • 初始階段做好單元測試,然後考慮接口測試,以及 UI 的自動化測試

  • 針對 UI 這類可能變動頻繁,測試成本較高的部分,更加應該專注價值,而不是盲目的編寫大量測試用例

  • 調研一些最新的測試技術,高效先進的框架往往能夠爲你節省大量的時間

  • 善於使用容器化技術解決測試基礎套件的問題,提高測試的運行效率

  • 爲開發人員創造更友好的,編寫測試用例的開發環境

但也不要踏入技術萬能的陷阱中,整個團隊樹立正確的質量內建,根因分析文化,纔是自動化測試以及 DevOps 成功的關鍵。

相關閱讀:

很不幸,自動化測試永遠只能是必要非充分條件

面對疫情這樣的複雜問題,有什麼招呢?

DevOps關鍵能力之文化的力量——重磅新書預覽《加速》

小說體敏捷/DevOps轉型教科書

和實戰經驗分享

又到拼人品的時候,喜歡《獵豹行動》的朋友請賞個臉投票。

每人每天可以投3票,截止4月19日。謝謝。

關注公衆號看其他原創作品

敏於思 捷於行 

堅持每週輸出一篇高質量文章

覺得好看,點個“在看”或轉發給朋友們,歡迎你留言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章