基於 BDD 理論的 Nebula 集成測試框架重構(上篇)

本文首發於 Nebula Graph 公眾號 NebulaGraphCommunity,Follow 看大廠圖資料庫技術實踐。

基於 BDD 理論的 Nebula 集成測試框架重構(上篇)

測試框架的演進

截止目前為止,在 Nebula Graph 的開發過程中,測試框架一共發生三次較大的改動,如下圖所示。在不斷的演進中,團隊還是積累了一些經驗和教訓,希望藉由此文做個簡單的介紹和梳理。

基於 BDD 理論的 Nebula 集成測試框架重構(上篇)

對於一個資料庫產品而言,測試的重要性不言而喻,如何強調都不為過。所以測試框架無論切換到誰,出發點始終只有一個:方便快速的積累測試用例來保障 Nebula Graph 功能的穩定。這裡提到的「方便快速」,不是局限於「開發者」這個群體,而是需要面向 Nebula Graph 的所有用戶,可能是運維、文檔甚至是非技術相關人員。為了實現這點目標,最好是能夠讓用戶進行「無碼編程」甚至不需要編程。

縱觀大多數的資料庫產品,往往是訂製一套自己的文本規則,開發者基於這套規則來提交測試,前期我們也有過這方面的嘗試,後續考慮到要從頭實現訂製功能太多,再加上用戶又需要學習一套新的規則,最終沒有真正的切換過去。直到我們開始做兼容 openCypher 的 MATCH 功能時,注意到 TCK 這個 repo,這雖然是一個兼容性的測試套件,但給我們實現 Nebula Graph 的集成測試提供了新的思路。前述嘗試不好落地的一個原因是 Nebula Graph 返回的結果集中是一個可能含有點、邊和路徑的複合數據結構,採用類似 JSON 的方式不是不可,只是不夠優雅簡潔。結果集多了之後,便有「形式」大於「內容」之嫌,結構上的描述遠超真正關心的數據,啰嗦冗長,不勝其煩。而 TCK 中制定的這套描述點、邊和路徑的描述規則足夠簡單直觀,又契合 MATCH 中的 Pattern 語句,前後呼應,只要用過 openCypher 的用戶,很容易接受和理解。只是針對 Nebula Graph 的強 schema 要求,需要對其規則做些拓展,但無傷大雅,鑒於上述的優點,讓我們堅定的走向 BDD 的測試框架。

Nebula Graph 端到端的功能測試其實是個「黑盒」測試,主要完成的事情抽象出來就是:執行一條 nGQL 語句,比較返回的結果集。

首先通過下述測試用例的複雜度比較,我們可以直觀的感受到每一次的進步,從上至下依次為:1. 基於 GTest 的測試;2. 基於 pytest 的測試;3. 基於 BDD 的測試。

基於 BDD 理論的 Nebula 集成測試框架重構(上篇)
[基於 GTest 的測試]
基於 BDD 理論的 Nebula 集成測試框架重構(上篇)
[基於 pytest 的測試]
基於 BDD 理論的 Nebula 集成測試框架重構(上篇)
[基於 BDD 的測試]

從上述對比可以看出,我們越來越靠近「測試」本真,只要關心輸入和輸出,無需再編碼組裝測試數據,再輔以一些小的自動化工具,便極大的降低了添加用例的門檻。

期望和實現

在拓展基於 TCK 的測試框架之前,我們給本次的升級定了如下幾個期望達成的目標:

  1. 添加用例簡單,構造期望數據方便;
  2. 支援導入其他的測試數據集;
  3. 復用 pytest 框架的靈活性,尤其是 plugins 和 fixture 等機制;
  4. 兼容 Match TCK 用例;

為了達成上述目標,我們開始了新的技術選型和模組設計。在構建 Nebula Graph 自己的 TCK 測試框架之前,首選要選擇一個「合適的」測試框架,針對該框架的基本要求有如下的幾點:

  1. 對基於 BDD 的測試有完善的支援;
  2. 方便靈活可拓展;
  3. 最好能與已有的 pytest 的用例兼容並存。

實現 BDD 的測試框架有很多,即便在 python 語言環境下也是一道多選題,比如 pytest-bddbehave 等。鑒於上述目標中的第三點,我們選擇了基於 pytest-bdd 來構建 Nebula Graph 的整個測試流程。 pytest-bdd 是 pytest 的一個插件,可以很好的支援 BDD 的特性同時又可以直接利用 pytest 的功能,比較契合我們的預期。

在選定測試框架之後,便開始設計整個測試流程的各個模組,大體結構可以劃分為五個部分:ConnectionManagerDataLoaderParserComparatorReporter

ConnectionManager

管理同 nebula graph 之間的連接,包括出錯重試、錯誤過濾等功能。

DataLoader

讀取 CSV 數據文件,解析配置中的數據類型,拼接插入數據的 INSERT 語句等。

Parser

解析 TCK 中描述的點、邊和路徑的字元串,轉成 Nebula 定義的 Value 結構,方便比較。

Comparator

負責不同的 Value 結構的值比較,包括基礎數據類型和複合數據類型,複合數據類型有:List、Map、Set、Vertex、Edge 和 Path 等。

Reporter

更好的輸出出錯的 nGQL 語句在 feature 文件中的位置和行號等訂製功能。

模組之間相互獨立又相互聯繫,再配合著 pytest 中 fixture 不同的 scope 可以很好的完成不同場景的隔離和測試。

何為 BDD

前文提到了很多次的 BDD,我們了解 TDD 和 DDD 比較多,可能對何為 BDD 還持有疑問。所謂 BDD 其實是由 TDD 演進而來的一種測試方法,即行為驅動測試(behavior-driven development)。通過用自然語言書寫測試用例的方式完成測試,對開發人員之外的參與者更加的友好,從而拉近了開發者和用戶之間的距離。在我們實踐過程中發現,其實 BDD 的這套方式方法不止對管理軟體品質有效,對繁雜的需求管理也是一個很好的補充手段。用戶的需求描述不再局限於複雜的場景描述,可以通過期望的查詢語句、過程和結論來跟開發者對齊功能需求,這些需求文件在功能開發完畢之後反過來又變成了測試場景用例,可謂一舉兩得。

說到 BDD,是離不開 Gherkin 語言的。它定義了一組基本的語法規則用來有效的組織普通文本的結構,以便於 BDD 測試工具可以理解文本中描述的內容。存放 Gherkin 語言文本的文件以 .feature 作為拓展名,其中可以描述很多的場景(Scenario)以及每個場景中的步驟是什麼(Given/When/Then)。這些語法的規則非常簡單易懂,而且關鍵詞數量也少,所以閱讀 Gherkin 的測試文本就像「一問一答」的對話,很容易上手。

Nebula Graph 的測試框架期望藉助 BDD 的方法打造一個純「黑盒」的測試流程,無論用戶是否是開發者都只需要關注兩點,輸入的 nGQL 是什麼和期望返回的結果數據是什麼?如此才能減輕用戶添加用例的心智負擔,方便其為 Nebula Graph 添磚加瓦。在我們完成框架改造半年之內,內部便已經積累了大約 2500 個測試用例,為 2.0 項目的重構提供了有力的品質保證。所有的用例都分門別類的置於 repo 中的 tests/tck/features 目錄中,這些用例本質上也是一部 nGQL 的使用指南,下次用戶再碰到棘手的問題不知如何用 nGQL 描述時,也可以先參考這裡的用例。

總結

本篇簡單回顧了 Nebula Graph 的測試框架的演變歷程,後續會向大家展示目前測試框架已經完成的功能以及如何使用它來測試對 Nebula Graph 源碼的改動。

交流圖資料庫技術?加入 Nebula 交流群請先填寫下你的 Nebula 名片,Nebula 小助手會拉你進群~~