高效測試框架推薦之Ginkgo

自2015年開始,七牛工效團隊一直使用Go語言+Ginkgo的組合來編寫自動化測試用例,積累了大約5000+的數量。在使用和維護過程當中,咱們以爲Ginkgo的不少設計理念和功能很是贊,所以特分享給你們。git

本篇不是該框架的入門指導。若是您也編寫或維護過大量自動化測試用例,但願能得到一些共鳴.github

BDD(Behavior Driven Development)

要說Ginkgo最大的特色,筆者認爲,那就是對BDD風格的支持。好比:正則表達式

Describe("delete app api", func() {
        It("should delete app permanently", func() {...})
        It("should delete app failed if services existed", func() {...})

It's about expressiveness。Ginkgo定義的DSL語法(Describe/Context/It)能夠很是方便的幫助你們組織和編排測試用例。在BDD模式中,測試用例的標題書寫,要很是注意表達,要能清晰的指明用例測試的業務場景。只有這樣才能極大的加強用例的可讀性,下降使用和維護的心智負擔。express

可讀性這一點,在自動化測試用例設計原則上,很是重要。由於測試用例不一樣於通常意義上的程序,它在絕大部分場景下,看起來都像是一段段獨立的方法,每一個方法背後隱藏的業務邏輯也是細小的,不具通識性。這個問題在用例量少的狀況下,還不明顯。但當用例數量上到必定量級,你會發現,如國能快速理解用例究竟是能作什麼的,真的很是重要。而這正是BDD能補足的地方。api

不過仍是要強調,Ginkgo只是提供對BDD模式的支持,你的用例最終呈現的效果,仍是依賴你本身的書寫。服務器

進程級並行,穩定高效

相應的咱們知道,BDD框架,由於其DSL的深度嵌套支持,會存在一些共享上下文的資源,如此的話想作線程級的併發會比較困難。而Ginkgo巧妙的避開了這個問題,它經過在運行時,運行多個被測服務的進程,來達到真正的並行,穩定性大大提升。其使用姿式也很是簡單,ginkgo -p命令就能夠。在實踐中,咱們一般使用32核以上的服務器來跑集測,執行效率很是高。併發

這裏有個細節,Ginkgo雖然並行執行測試用例,但其輸出的日誌和測試報告格式,仍然是整齊不錯亂的,這是如何作到的呢?原來,經過源碼會發現,ginkgo CLI工具在並行跑用例時,其內部會起一個監聽隨機端口的本地服務器,來作不一樣進程之間的消息同步,以及日誌和報告的聚合工做,是否是很巧妙?app

其餘的一些Tips

Ginkgo框架的功能很是強大,對常見測試場景的都有比較好的支持,即便是一些略顯複雜的場景,好比:框架

  • 在平時的代碼中,咱們常常會看到須要作異步處理的測試用例。可是這塊的邏輯若是處理很差,用例可能會由於死鎖或者未設置超時時間而異常卡住,很是的惱人。好在Ginkgo專門提供了原生的異步支持,能大大下降此類問題的風險。相似用法:異步

    It("should post to the channel, eventually", func(done Done) {
        c := make(chan string, 0)
        go DoSomething(c)
        Expect(<-c).To(ContainSubstring("Done!"))
        close(done)
    }, 0.2)
  • 針對分佈式系統,咱們在驗收一些場景時,可能須要等待一段時間,目標結果才生效。而這個時間會由於不一樣集羣負載而有所不一樣。因此簡單的硬編碼來sleep一個固定時間,很明顯不合適。這種場景下如果使用Ginkgo對應的matcher庫GomegaEventually功能就很是的貼切,在大大提高用例穩定性的同時,最大可能的減小無用的等待時間。
  • 筆者一直認爲,自動化測試用例不該該僅僅是QA手中的工具,而應該儘量多的做爲業務驗收服務,輸出到CICD,灰度驗證,線上驗收等儘量多的場景,以服務於整個業務線。一樣利用Ginkgo咱們能夠很容易作到這一點:
    • CICD: 在定義suite時,使用RunSpecWithDefaultReporters方法,可讓測試結果既輸出到stdout,還能夠輸出一份Junit格式的報告。這樣就能夠經過相似Jenkins的工具方便的呈現測試結果,而不用任何其餘的額外操做。
    • TaaS(Test as a Service): 經過ginkgo build或者原生的go test -c命令,能夠方便的將測試用例,編譯成package.test的二進制文件。如此的話,咱們就能夠方便的進行測試服務分發。典型的,如交付給SRE同窗,輔助其應對線上灰度場景下的測試驗收。因此在測試用例的組織上,這裏有個小建議,過往我會看到有同窗會習慣一個目錄就定義一個suite文件,這樣編譯出的二進制文件就很是多,不利於分發。因此建議不要定義太多的suite,能夠一條產品就一個suite入口,其餘的用例包經過_導入進來。好比:

另外,值得說道的是,Ginkgo框架在提供強大功能和靈活性的同時,有些地方也須要使用者特別留心:

  • DescribeTable功能是對TableDriven模式的友好支持,但它的原理是經過Entry在用例執行以前,經過反射機制來自動生成It方法,因此若是指望相似BeforeEach+It的原生組合來使用BeforeEach+Entry的話,可能在值類型的變量傳遞上,會不符合預期。其實,相較於DescribeTable+Entry的模式,我我的更傾向於經過方法+多個It的原生組合來寫用例,雖然代碼量顯得有點多,可是用例表達的邏輯主題會更清晰,可讀性較高。相似以下:
  • Ginkgo CLI的focus和skip命令很是好用,可以靈活的指定想執行或者排除的測試用例。不過要注意的是,focus和skip傳入的是正則表達式,而適配這個正則的,是組成用例的全部的Container標題的組合(Suite+Describe+Context+It), 這些標題從外到裏拼接成的完整字符串,因此使用時當注意。

都有誰在用Ginkgo?

Ginkgo的官方文檔很是詳細,很是利於使用。另外,咱們看到著名的容器雲項目Kubernetes也是使用Ginkgo框架來編寫其e2e測試用例。

最後,若是您也使用Go語言來編寫測試用例,不妨嘗試下Ginkgo。

Contact me ?

Email: jinsdu@outlook.com
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi

相關文章
相關標籤/搜索