本文首發於 Nebula Graph 公眾號 NebulaGraphCommunity,Follow 看大廠圖資料庫技術實踐。
測試框架的演進
截止目前為止,在 Nebula Graph 的開發過程中,測試框架一共發生三次較大的改動,如下圖所示。在不斷的演進中,團隊還是積累了一些經驗和教訓,希望藉由此文做個簡單的介紹和梳理。
對於一個資料庫產品而言,測試的重要性不言而喻,如何強調都不為過。所以測試框架無論切換到誰,出發點始終只有一個:方便快速的積累測試用例來保障 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 的測試。
[基於 GTest 的測試]
[基於 pytest 的測試]
[基於 BDD 的測試]
從上述對比可以看出,我們越來越靠近“測試”本真,只要關心輸入和輸出,無需再編碼組裝測試資料,再輔以一些小的自動化工具,便極大的降低了新增用例的門檻。
期望和實現
在擴充基於 TCK 的測試框架之前,我們給本次的升級定了如下幾個期望達成的目標:
- 新增用例簡單,構造期望資料方便;
- 支援匯入其他的測試資料集;
- 複用 pytest 框架的靈活性,尤其是 plugins 和 fixture 等機制;
- 相容 Match TCK 用例;
為了達成上述目標,我們開始了新的技術選型和模組設計。在構建 Nebula Graph 自己的 TCK 測試框架之前,首選要選擇一個“合適的”測試框架,針對該框架的基本要求有如下的幾點:
- 對基於 BDD 的測試有完善的支援;
- 方便靈活可擴充;
- 最好能與已有的 pytest 的用例相容並存。
實現 BDD 的測試框架有很多,即便在 python 語言環境下也是一道多選題,比如 pytest-bdd, behave 等。鑑於上述目標中的第三點,我們選擇了基於 pytest-bdd 來構建 Nebula Graph 的整個測試流程。 pytest-bdd 是 pytest 的一個外掛,可以很好的支援 BDD 的特性同時又可以直接利用 pytest 的功能,比較契合我們的預期。
在選定測試框架之後,便開始設計整個測試流程的各個模組,大體結構可以劃分為五個部分:ConnectionManager、DataLoader、Parser、Comparator、Reporter。
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 小助手會拉你進群~~