Selenium 4 的新技巧

Selenium Grid:一種機制,可讓您將測試分散到多台機器上。

在他的系列文章的第四篇也是最後一篇中,Simon Stewart 繼續談論 Selenium 4 即將推出的功能,並回顧 Selenium Grid 中的新功能。

在過去的幾篇部落格文章中,我們涵蓋了很多內容,包括如何為專案做出貢獻,以及您可以期望作為 Selenium 使用者的一些詳細資訊。但 Selenium 不僅僅是您用來編寫測試的 API,我們尚未涵蓋的重大功能之一是經過刷新的 Selenium Grid:一種機制,可讓您將測試分散到多台機器上。

在進一步說明之前,總是很高興承認我們從哪裡來,不僅因為它很有趣,而且還有助於解釋刷新設計的「原因」。

早在遠古時代 (2008 年),Jennifer Bevin 和 Jason Huggins 在 Google 開發了一個名為 Selenium Farm 的系統。這是一個位於某處櫥櫃中的機器群,可讓您執行原始的 Selenium 協定。當然,這是 Google 的規模,因此不只一個櫥櫃 :)

這讓 Google 的人們可以分散他們的測試並擴展到他們個人的機器之外。這是一個很棒的想法,以至於當 Jennifer 在 Selenium meetup 上談論 Farm 時,Philippe Haringou(當時在 ThoughtWorks)決定編寫一個相同的開源實作,他稱之為「Selenium Grid」。

Selenium Grid 是一項很棒的技術,但它有一個缺點:它只說原始的 Selenium RC 協定。這很好,但是 WebDriver 說的是不同的線路協定,稱為 JSON Wire Protocol,並且人們希望能夠同時使用 Selenium RC 和 WebDriver。

這就是 Francois Reynaud 進入畫面的地方。他在 eBay 工作,向 Michael Palotas 報告,他編寫了類似原始 Selenium Grid 的東西,但也適用於 JSON Wire Protocol。他們非常友善地將該工作貢獻給 Selenium 專案,它構成了 Selenium Grid 2 的基礎。我們當時決定,Selenium 獨立伺服器實際上將是一個「單一 Grid」:它將擁有設定 Selenium Grid 以及作為單一獨立伺服器運作所需的一切。合併程式碼並使其穩定花費了一段時間,但由於 Francois、Kristian Rosenvold 和許多其他人的努力,我們將 Grid 2 合併到主要的 Selenium 專案中,並在 2011 年發布了 Selenium 2。

即使 2011 年感覺不是很久以前,但現代世界已經發生了很大的變化。在 2011 年,我們沒有 Docker。我們沒有 Kubernetes,我們真的沒有 AWS。因此,Selenium Grid 並不知道這些東西即將到來,並且沒有編寫成可以利用它們。幸運的是,我們當時確實有虛擬機器,並且 Grid 2 的設計能夠支援它們。

這是一個名為 Zalenium 的出色專案的契機。Zalenium 由 Diego Molina 開發,在 Grid 2 的基礎上,新增了一個非常好的 UI 以及對 Docker 和 Kubernetes 的支援。這使 Selenium Grid 能夠繼續保持相關性和實用性至今,這是一項了不起的成就。

但是,就像我說的那樣,我們花費了時間來穩定 Grid 2:大約六個月的辛勤工作,主要由 Kristian 領導。那是因為雖然 Grid 2 很複雜,但程式碼很難閱讀和維護—而且很少有人可以做到。更糟糕的是,Grid 2 和原始 Selenium 伺服器的合併非常粗糙;實際上,兩個單獨的伺服器以相同的二進制檔發布。這導致 Grid 中發生問題,但在獨立模式下執行時則不會發生,反之亦然。

使用 Selenium 4,我們決定咬緊牙關並解決這三個問題。首先,我們想要更容易工作和維護的東西。其次,我們希望將伺服器合併為一個單一單元。第三,我們希望能夠利用我們現在可用的現代基礎架構世界,不僅以 Docker 和 Kubernetes 的形式,而且還能夠使用新興技術,例如分散式追蹤。

為此,我們研究了 Grid 提供的功能,並將每個部分建模為一個元件,我們可以「在記憶體中」執行(讓我們擁有一個單一的獨立伺服器),或者以更分散的方式執行,允許我們從原始 Selenium Grid 熟悉的「Hub 和 Node」架構,到完全分散式的設計。

第一個元件是「路由器」。它是 Grid 的入口點。您可以將其暴露於網際網路,它會將請求導向 Grid。它被設計為無狀態的,因此您可以根據需要向 Grid 新增更多路由器。

當路由器看到新的會話請求時,它會將其放置在「會話佇列」中。會話佇列由稱為「分配器」的元件讀取,該元件維護 Grid 中可以執行會話的所有位置的模型:我們稱它們為「插槽」。插槽由稱為「節點」的元件託管,每個節點可以有一個或多個插槽。當分配器從佇列中提取新的會話請求時,它會識別要使用的最合適的插槽,並將請求轉發到擁有該插槽的節點。節點啟動會話後,分配器將會話 ID 和正在執行測試的節點的 URL 放入「會話地圖」中—您可以將會話地圖視為會話 ID 到 URL 的簡單地圖—並且新的會話回應會發送回等待的測試。

執行中會話的請求(即,對於大多數 webdriver 呼叫!)的處理方式略有不同。路由器將使用會話地圖來查找要將請求轉發到哪個節點,從而避免完全需要分配器參與。這意味著您可以繼續向 Grid 新增節點,並且架構中的瓶頸更少,從而減慢您的請求速度。

從概念上講,Grid 內有這五個移動部件。但實際上還有第六個,即訊息匯流排。這五個 Grid 元件透過訊息匯流排在內部進行通訊,但是當您考慮 Grid 時,您需要考慮的實際元件是路由器、會話佇列、分配器和節點。

當您在「獨立」模式下執行 Selenium Grid 4 時,您實際上會得到一個「單一 Grid」。我們在單一程序中連接所有這些元件,但它們仍然都在那裡。

您也可以在傳統的 Hub 和 Node 方法中執行它,您在 Selenium Grid 2 中看到過,您啟動一個 Hub 和一個 Node,它會註冊。如果您最近使用過 Selenium Grid,那麼這可能是您熟悉的架構。在這種情況下,大多數元件(路由器、會話佇列和分配器)都在 Hub 中執行,而節點本身則執行會話。

Grid 4 的新功能是,如果您願意,可以進入完全分散式的模式。通常,您會希望為此使用類似 Kubernetes 的東西,並且某些關鍵元件旨在將資料儲存在資料庫或 Redis 中,以獲得更好的可靠性和可擴展性。

需要注意的是,在執行分散式 Grid 時,很難弄清楚發生了什麼事,尤其是在出現問題時。為了減輕這個問題,我們採用了 Open Telemetry 將可觀察性帶入 Grid。我們所說的可觀察性是什麼意思?它只是意味著我們希望能夠看到所有發生的事情。

最後,我們希望以有意義且有用的方式公開有關執行中 Grid 的資訊。原始 Grid 支援 JMX(Java 管理 API)和基於 HTML 的控制台。雖然不錯,但這並不容易查詢您可能感興趣的 Grid 的特定區域,而這些區域並未透過 UI 顯示(例如,有多少插槽可用,或找出特定會話在哪個節點上執行)為了提供更大的靈活性,我們選擇為 Grid 提供 GraphQL 端點。為了確保 GraphQL 端點足夠靈活,我們正在使用它建置新的 Grid 控制台。這也應該允許您從 Grid 中提取有用的指標和資訊,以滿足您的監控需求。

這些是新 Selenium Grid 的一些亮點。您最興奮的是什麼?

最初發布於 https://saucelabs.com/blog/whats-coming-in-selenium-4-the-new-selenium-grid

上次修改時間:2021 年 8 月 7 日:重新命名目錄 (e9895f27c26)