前不久,InfoQ向大家推薦了幾本有關軟件架構的新書,引起了國內讀者的廣泛興趣。其中一本是《開源應用架構(The Architecture of Open Source Applications)》, 來自知名開源項目的各位作者對軟件的設計進行了說明。通過對這些成功的系統架構進行概覽,讓軟件工程師可以徹底了解佳實踐和陷阱。InfoQ中文站響應 讀者的需求,整理了該書有關知名開源軟件架構的精彩內容,供國內開發社區借鑒。本期介紹的是瀏覽器自動化工具Selenium WebDriver的軟件架構,第一部分主要分享了Selenium WebDriver的演變歷史和架構觀點。
Selenium是一個瀏覽器自動化工具,通常用來編寫Web應用 的端到端測試。瀏覽器自動化工具準確執行你所期望的行為:自動化瀏覽器的某個控件,從而可以自動重復執行任務。這聽起來像是一個很容易解決的問題,但是 正如我們即將看到的那樣,其實Selenium成功的背后凝聚了大量的工作。
介紹Selenium WebDriver軟件架構的技術專家是來自Google的Simon Stewart,他是Selenium的核心貢獻者和Selenium WebDriver的創建者。
Simon Stewart首先談起了Selenium的組成部分:
在介紹Selenium架構之前,好先了解一下該項目的各個相關組成部分是如何結合在一起的。從較高的層次看,Selenium由三種工具組成。 第一個工具Selenium IDE,是Firefox的擴展插件,支持用戶錄制和回訪測試。錄制/回訪模式存在局限性,對許多用戶來說并不適合,因此第二個工具—— Selenium WebDriver提供了各種語言環境的API來支持更多控制權和編寫符合標準軟件開發實踐的應用程序。后一個工具——Selenium Grid幫助工程師使用Selenium API控制分布在一系列機器上的瀏覽器實例,支持并發運行更多測試。在項目內部,它們分別被稱為“IDE”、“WebDriver”和“Grid”。
追根溯源,Selenium和WebDriver初是兩個獨立的項目,Simon Stewart解釋了發展的歷史:
Jason Huggins在2004年發起了Selenium項目,當時他在ThoughtWorks公司開發內部的時間和費用(Time and Expenses)系統,該應用使用了大量的JavaScript。雖然Internet Explorer在當時是主流瀏覽器,但是ThoughtWorks還使用一些其他瀏覽器(特別是Mozilla系列),當員工在自己的瀏覽器中無法正常 運行T&E系統時會提交bug報告。當時的開源測試工具要么關注單一瀏覽器(通常是IE),要么是模擬瀏覽器(如HttpUnit)。購買商業 工具授權的成本會耗盡這個小型內部項目的有限預算,所以它們都不是可行的測試選項。
在自動化困難的情況下,通常會依靠手動測試。當開發團隊規模很小或者構建發布非常頻繁時,這種方式不太適用。同時,讓人手動執行原本可以自動化的腳本也是一種對人力的浪費。沉悶重復的任務越無聊,人們工作會越慢而且比機器犯更多錯誤。手動測試也不是一種選擇。
幸運的是,所有被測試的瀏覽器都支持Javascript。Jason和他所在的團隊有理由采用Javascript編寫一種測試工具來驗證應用的行為。他們受到FIT(Framework for Integrated Test) 的啟發,使用基于表格的語法替代了原始的Javascript,這種做法支持那些編程經驗有限的人在HTML文件中使用關鍵字驅動的方式來編寫測試。該 工具,初稱為“Selenium”,后來稱為“Selenium Core”,在2004年基于Apache 2授權發布。
Selenium的表格格式類似于FIT的ActionFixture。表格的每一行分為三列。第一列給出了要執行的命令名稱,第二列通常包含元 素標記符,第三列包含一個可選值。例如,如下格式表示了如何在名稱為“q”的元素中輸入字符串“Selenium WebDriver”:
type name=q Selenium WebDriver
因為Selenium過去使用純JavaScript編寫,它的初設計要求開發人員把準備測試的應用和Selenium Core、測試腳本部署到同一臺服務器上以避免觸犯瀏覽器的安全規則和JavaScript沙箱策略。在實際開發中,這種要求并不總是可行。更糟的是, 雖然開發人員的IDE能夠幫助他們快速處理代碼和瀏覽龐大的代碼庫,但是沒有針對HTML的相關工具。人們很快意識到維護一個中等規模的測試集是笨拙而 痛苦的過程。
為了解決這個問題和其他問題,我們編寫了HTTP代理,這樣所有的HTTP請求都會被Selenium截獲。使用代理可以繞過“同源”規則(瀏覽器 不支持Javascript調用任何當前頁面所在服務器以外的其他任何東西)的許多限制,從而緩解了首要弱點。這種設計使得采用多種語言編寫 Selenium綁定成為可能:它們只需把HTTP請求發送到特定URL。連接方法基于Selenium Core的表格語法嚴格建模,稱之為“Selenese”。因為語言綁定在遠程控制瀏覽器,所以該工具稱為“Selenium Remote Control”或者“Selenium RC”。
在Selenium處于開發階段的同時,另一款瀏覽器自動化框架WebDriver也正在ThoughtWorks公司的醞釀之中。 WebDriver的初代碼在2007年初發布。WebDriver項目的初衷是把端對端測試與底層測試工具隔離開。通常情況下,這種隔離手段通過適配 器(Adapter)模式完成。WebDriver正是來源于該方法在許多項目上的不斷實踐應用,初是HtmlUnit的封裝,工具發布后很快開始支持 Internet Explorer和Firefox。
在WebDriver初發布時,與Selenium RC存在顯著差異,盡管它們都屬于瀏覽器自動化的API工具。對于用戶來說,明顯的區別在于Selenium RC提供基于字典的API,所有方法都在一個類中開放,而WebDriver的API更面向對象。此外,WebDriver僅支持Java,而 Selenium RC提供廣泛的語言支持。技術差異也很明顯:Selenium Core(RC的基礎)基本上是JavaScript應用,運行在瀏覽器的安全沙箱之內。WebDriver則嘗試原生綁定到瀏覽器中,繞開了瀏覽器的安 全模型,代價是框架自身的開發投入顯著增加。