持續集成---減少持續集成的時間
在持續集成領域,一個產品的發布往往都有自己的過程周期(lifecycle),大體都會劃分為:構建->部署->測試->發布等幾個重要階段,其中測試是發布產品前不可或缺的重要階段,是產品質量的保證。而能讓持續集成奏效,除了要求測試腳本更充分健壯,還要求測試腳本運行得更快更好。這點對于小型項目而言可能顯得無關緊要,畢竟大多小項目的測試腳本不過百條,驗證點不過千“點”;但對于一個大型項目而言,測試代碼源文件可能成百上千,執行完所有的測試可能要等很久,而苦等之后的結果卻可能是滿眼的failure, 于是如果提高測試執行速度成為迫切需要解決的問題,試想把測試階段從2小時壓縮到1小時,再從1小時壓縮到30分鐘,每次時間壓縮帶來的不僅是技術人員本身的成就感,更是對整個產品發布過程體驗的改善。
那么如何加速測試的執行呢?提起速度,我們立馬可能聯想到“性能”調優的步驟:先進行tuning,然后找到問題的瓶頸所在,最后逐個擊破。本文暫不討論如何進行這些步驟, 而是基于C++和Java為語言案例,TestNG和Google test為測試框架,Jenkins為持續平臺做分析,從以下六個層次提出提高測試執行的一般方法:
硬件資源層次
工欲善其事必先利其器,提高硬件(CPU、內存、磁盤等)配置是改善執行速度的“硬”方法,硬件資源的優化不應僅僅局限在單機自身的各項指標提升,在需求不斷提高的情況下,可以考慮實施虛擬機、分布式集群等方式來進一步獲取更優的硬件資源,當然,涉及分布式執行時,可以借助以下持續集成平臺層次的“軟”實施來共同作用。
另外,在硬件資源緊張的情況下,不同項目或者不同團隊可能不得不復用一套測試環境,造成可利用資源更為緊張,此時可以錯開時間測試(例如A項目組測試定時在凌晨0點啟動,B項目組定時在凌晨2點)以提高速度。
語言編碼實現層次
測試代碼本身也是代碼,顯而易見,如果代碼編寫時注重效率,速度上肯定有所收益。這點可能需要“糾結”于一些日常的編碼細節:例如Java中Stringbuffer和Stringbuilder的比較;C++中是i++和++i的比較。這種語言層次提高效率的文章書籍很多,這里不做過多描述。在語言編碼層次上最重要的不是這些語言細節,而是避免一些消費時間的測試代碼設計,減少不必要的耗時操作,例如以下幾點:
(1) 冗余的日志信息,不合理的日志級別設置等
輸出日志帶來的磁盤頻繁訪問必然讓速度下降,所以在保證日志信息充足的前提下,盡量減少日志,或者只記錄失敗測試的日志(畢竟對于測試者而言很少去關注成功日志),可以讓測試加快。
(2) 不合理的等待
用戶執行完某個操作,必須等待某條件的發生(例如DB里面插入一條新數據)進而執行后續動作是測試中經常面對的場景,那么等待多久成為需要考慮的問題,假設用TimeUnit.MINUTES.sleep(1)等待一分鐘,在10秒即可滿足條件的場景下浪費的就是50秒,所以這里必須去考慮合理sleep的時間來兼顧對資源的消耗和運行速度的影響,同時在等待方式上也可以考慮是采用循環短時間條件等待或異步通知的方式去進行。
(3) 用例的過程
先執行完所有測試步驟,然后做對所有步驟做一次性校驗,還是做完一步校驗一步,這兩種方式的速度在不同場景下有所不同,所以需要權衡;相類似的,對于需要獲取DB連接的用例,是每條都執行獲取DB連接然后釋放連接,還是所有用例執行之前獲取連接,所有case執行完之后釋放連接也會對執行速度有所影響。
構建測試腳本層次
對于一個大型項目,源文件的數目龐大或依賴的dependency過多導致代碼編譯占用大量時間,如何提高編譯代碼的速度?除了使用更好的磁盤,注重代碼編寫時對編譯速度的影響,還可以針對不同的語言采取不同的有效策略,例如針對C++, 使用make命令編譯項目時,可以加上參數-j來并行編譯項目。-j參數的含義可以參考下文:
-j [jobs], --jobs[=jobs]
指定同步運行的作業(命令)的數量。如果有一個以上-j選項,那么只有最后一個有效。如果-j選項沒有參數,那么編譯過程就不會限制能夠同步運行的作業的數量。
需要說明的是,編譯過程可能要求特定的順序而導致并行編譯失敗,如果遇到這種問題,可以先并行、后串行(去掉-j)重復執行一次以解決。
而對于java,Maven 3 開始支持并發build,提供了以下幾種常見方式:
mvn -T 4 clean install # Builds with 4 threads
mvn -T 1C clean install # 1 thread per cpu core
mvn -T 1.5C clean install # 1.5 thread per cpu core
同時使用maven管理java項目常出現時間消耗在依賴jar的下載上,此時可以檢查是否有冗余失效的repository配置、較長的下載timeout時間設置、所選擇repository的連接速度等,甚至在不同測試環境下可以使用 profile來管理repository來加速測試腳本構建。
測試框架支持層次
在測試框架支持層次上,應該充分運用框架本身提高的豐富功能來提高測試執行速度,以Java測試框架TestNG為例:
(1) 利用timeout控制失效等待
如果某個測試用例等待某條件的觸發而陷入長時間等待,等待的時間過長往往對于用例本身而言已失效,特別是當條件永遠無法滿足時。因此需要控制用例執行允許的最大timeout時間。TestNG可以給test或者test suite設置 timeout時間,分別控制具體某個或一組(testing.xml配置)自動化測試用例執行的最大允許時間:
1. @Test(timeout = 1000)
2. testng.xml : <suite name="Module Test" parallel="none" time-out="200000">
(2) 利用@BeforeTest、@BeforeClass等條件注解,減少無意義測試
測試的順利完成都需要滿足很多基礎條件,例如需要測試環境就緒, 如果不使用@before類標簽,則當條件不具備時,仍然會執行完所有的用例,必然帶來巨大的時間浪費,因此使用@before類標簽可以避免無意義的測試,@before標記的方法一旦失敗,后續的相應的測試不會繼續進行。
(3) 使用框架自帶的多線程支持
例如對于TestNG自身,可以在testng.xml中設置parallel參數來指定是否并發以及并發的級別:methods|tests|classes,除了測試框架自身外,軟件項目管理工具也可以提供多線程支持,例如maven的測試組件maven-surefire-plugin,提供了并發參數的設置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <configuration> <parallel>methods</parallel> <threadCount>10</threadCount> </configuration> </plugin> |
持續集成平臺層次
現在市場上存在不少持續集成平臺,大多持續集成平臺支持并發執行用例然后匯總、發布測試結果,從而最大化提高測試執行速度。而并發執行的前提是測試代碼本身及測試代碼的組織支持并發,如果測試本來就含有多個模塊,那么直接并發運行多個模塊,最后匯總結果即可。如java以testng.xml為模塊,gtest以makefile為模塊,所以相比較順序執行4個模塊,并發使用4個Job并發執行,那么時間壓縮可以達到4倍。在實際應用中,即使在同一個模塊,我們仍然面對自動化測試用例數目過多運行速度過慢的問題,此時,可以考慮將單一模塊拆分成子模塊,對于Java而言較簡單,配置下測試套件的xml即可;而對C++而言,如果不允許直接復制粘貼原有的makefile,就需要重新設計makefile以復用, 例如將makefile中編譯的test cases定義分拆到多個makefile(如下圖測試模塊1的makefile引用了共用的makefile并添加了自己的測試用例)中,然后并發執行多個makefile。
為并發執行多個job, 持續集成平臺必須提供必備的支持,以Jenkins為例,可以使用multijob插件來實施,配置多個測試模塊同時進行.
并發完測試后,講所有測試結果匯總到一個地方,然后使用xunit plugin來匯總結果(如下圖),它可以匯總多個文件,且支持cpptest、,gtest等輸出結果格式。
過程改進層次
在產品的持續集成生命周期中,可以將測試拆分成兩部分放在兩個階段:基本功能快速校驗階段(fast fail)和基本功能之外的全面測試階段。如果產品在第一階段最基本的功能都無法通過,那么部署之后進行全面測試純屬浪費時間,這個階段的引入可以快速的校驗產品是否有必要開展全面測試。這點類似與測試用例中添加了@before類標簽所帶來的收效,不過更宏觀且階段劃分的更清晰。
原有過程:構建階段->部署階段->測試階段->發布階段
細化后過程:構建階段->部署階段->基本功能快速校驗階段->全面測試階段—>發布階段
這種過程優化可以利用持續集成平臺來支持,例如對于Jenkins系統,可以使用multijob插件,將基本功能快速校驗和全面測試階段分列在不同的phase即可,執行效果如下:
結論
通過上面由微觀到宏觀六個不同層次的分析可知,要加速測試用例的執行是一個系統的過程,單靠某一方面分析可能有所偏失,并不能將測試用例的執行速度發揮極致。同時,本文針對不同層次的分析也沒有提供step by step的方式描述每一個細節,只是點到為止,所以讀者可以根據自己采用的語言、測試框架、持續集成平臺做類似更有針對性的分析,相信在綜合不同層次的綜合調優后,可以讓持續集成實施的更快、更好。
posted on 2014-06-25 11:39 順其自然EVO 閱讀(244) 評論(0) 編輯 收藏 所屬分類: 測試學習專欄 、selenium and watir webdrivers 自動化測試學習