dubbo接口自動化用例性能優化


前言

去年換了一個新部門,看了下當前的自動化用例的情況,發現存在三類性能問題:

  • 本地調試運行時等待時間較長,就算是一個簡單的case,執行時間都需要1分鍾以上
  • 單用例執行時間比較長,部分用例執行時間超過2分鍾
  • 集成到CI中運行時,執行時間較長

對於上述三個問題花時間進行了一定程度的優化,總結如下

優化本地調試時間

通過調試可以發現,一個需要執行660ms的case,在執行前的初始化工作就需要消耗約1分半鍾,那么就需要思考下能否減少這部分初始化時間了。

公司用的自動化框架是基於AbstractTestNGSpringContextTests的框架。AbstractTestNGSpringContextTests是一個spring集成testNg的工具,可以通過ApplicationContext加載bean。ApplicationContext實現的默認行為就是在啟動服務器時將所有bean提前進行實例化。提前實例化意味着作為初始化過程的一部分,applicationContext實例會創建並配置所有的bean。

如果是作為一個spring服務,在啟動時將bean提前進行實例化,然后可以處理所有的請求,這樣的做法是很合理的。但是作為本地調試,更關注是自己case運行時所需要的bean是否實例化,而不需要將所有bean進行實例化。

查閱了下spring相關文檔,發現可以引入lazy-init來告訴ApplicationContext按需加載bean。
配置方式有兩種:

  1. default-lazy-init參數,其配置形式如下:
    <beans default-lazy-init="true" > </beans>
  2. lazy-init參數,其配置形式如下:
    <bean id="stu" lazy-init=“true”></bean>

配置完成后,運行了一下,發現並沒有速度上的提升,原因是之前編寫時將大部分的bean的初始化放在了測試用例里的基類里面,導致啟動時認為這些bean都需要初始化。

這說明要讓lazy-init生效,提高單用例的啟動速度,那就要盡可能少的使用不需要的bean,需要做一定改造:

  1. 將service/DAO初始化挪到測試用例里面。
  2. 去除不需要的多余的service/DAO。

按照上面的思路對用例進行了優化,可以將用例的初始化時間精簡到30秒左右。

單用例執行時間的優化

為什么會出現很多的用例執行時間超過2分鍾呢?做了一些分析和調試后,主要有幾個原因:

  • 業務決定了服務之間很多是通過消息的方式進行傳遞,存在異步調用,所以需要等待再進行后續執行,為了用例的穩定性往往設置了過大的sleep time。
  • 一些數據准備和初始化操作不合理,無謂的耗時。

下面來看幾個案例:

  1. 在beforeclass里面都會有一段初始化數據的操作,先調接口查詢數據是否存在,不存在則進行初始化,導致每運行一個測試用例類都需要做一次對應操作。

    實際上這些數據初始化完后可以一直被使用,不需要多次檢查,可以優化的地方是用個靜態變量判斷數據已初始化的話就不檢查,或者將該操作設置為跑一次用例集只運行一次。

  2. 大量使用了sleep做等待,如果操作需要等待1s左右才生效,那么用sleep往往需要sleep2秒,所以sleep一般會造成50%左右的性能浪費。
    引入異步校驗工具Awaitility對原有代碼進行改寫。

Awaitility的基本的語法為:

  • pollInterval:執行間隔
  • pollDelay:等待多久開始執行
  • atMoast:執行的超時時間
  • until()-> 執行其中的語句直到返回true或超時

這樣的寫法比較優雅簡介,如果判斷執行完成可以提前結束等待,避免時間浪費。

提高並發

當優化了單用例的運行時間后,雖然對總體自動化集成測試的運行速度有一定幫助,但當用例越來越多的時候,時間也會變得無法忍受,能想到的一個辦法是增加用例的並發。

用例能夠並發執行的前提是用例之間具有隔離性,一個用例的執行不會影響另一個用例的執行,比如我在店鋪A下單和在店鋪B下單這兩個用例就不會有干擾,又比如我在店鋪A創建商品和我在店鋪A下單也不會有影響。
所以考慮用例並發的時候,需要先針對自己的業務特性進行一定程度的分組隔離。

在我們的案例中,考慮對店鋪進行分組,用例並發用到的並發基本機制是testNG parallel="tests"/"class" thread-count=“N"
在實際執行中,分組的實施也會有兩種模式,按case的緯度還是按照類的緯度:
1.使用店鋪id分組進行並發,使用group=店鋪id 維度
優點:任意維度擴展
缺點:每個case需要加@group
2.把不同測試類按店鋪id分組,使用package/class維度
優點:改動簡單
缺點:需要每個測試類只使用一個店鋪id,缺乏擴展性,需要頻繁改動配置文件

最后選擇了按case緯度,因為現存的用例並未很好的按店鋪id進行組織,比較散亂,使用類的緯度改動較大。

使用了兩個並發以后,性能提升明顯,時間從547s->270s。

最后

解決了一部分性能問題后,尤其是提高了用例並發以后,對用例穩定性也更高了。

和開發寫代碼需要考慮異常和容錯處理一樣,測試人員在自動化設計、實施等各階段都需要考慮用例的穩定性問題:

  • 減少外部依賴。如果執行過程需要依賴其他系統的接口,那么其他系統發生了變更或故障就會影響自身用例的進行。可以考慮通過預先生成的數據來替代調用外部接口生成數據在用例中使用。第三方接口的調用可以考慮mock
。
  • 預置數據代替創建過程。由於操作越多穩定性越低,使用預置數據而不是實時生成它,速度更快,穩定性更高。
  • 使用不同維度進行隔離。通過隔離,用例執行失敗的臟數據就不會影響其他用例。
  • 調優:超時、等待時間。線上超時時間設置的比較短,測試環境的機器配置不如線上,需要適時調大超時和等待時間來保證接口調用不會超時。
  • 防御式編程。編寫測試代碼時不能假設數據已存在或者沒有臟數據殘留,所以預先的判斷和清理很重要,比如檢查到數據缺失就實時修復、用例運行之前考慮清除臨時數據等。
  • 定位並解決不穩定的問題。有時候偶現用例失敗,可以考慮給被測應用增加日志,同時持續多次運行用例多次(如 testNg 里增加threadPoolSize=1, invocationCount=50)來復現問題,最終解決問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM