本文所述內容在Windows系統下實踐完成,涉及的軟件版本信息如下:
注:部分軟件版本間兼容性十分重要,下文中會提及,使用其他版本時請注意。 |
1. 簡介
Selenium是用於測試 Web應用程序用戶界面 (UI)的常用框架。它是一款用於運行端到端功能測試的超強工具。您可以使用多個編程語言編寫測試,並且 Selenium能夠在一個或多個瀏覽器中執行這些測試。
1.1 歷史
-
Selenium1.0
2004年,ThoughtWorks公司的JasonHuggins和他所在的團隊採用Javascript編寫一種測試工具來驗證瀏覽器頁面的行爲。這個JavaScript類庫就是Selenium core,同時也是seleniumRC、Selenium IDE的核心組件。
關於命名 當時QTP mercury是主流的商業自動化工具,是化學元素汞(俗稱水銀),而Selenium是開源自動化工具,是化學元素硒,硒可以對抗汞。 |
Selenium 1.0 = Selenium IDE + Selenium Grid + SeleniumRC
n Selenium IDE Selenium IDE是嵌入到Firefox瀏覽器中的一個插件,實現簡單的瀏覽器操作的錄製與回放功能。 n Selenium Grid Selenium Grid是一種自動化的測試輔助工具,Grid通過利用現有的計算機基礎設施,能加快Web-App的功能測試。利用Grid可以很方便地實現在多臺機器上和異構環境中運行測試用例。 n Selenium RC Selenium RC(Remote Control)是Selenium家族的核心部分。Selenium RC 支持多種不同語言編寫的自動化測試腳本,通過Selenium RC的服務器作爲代理服務器去訪問應用,從而達到測試的目的。 Selenium RC分爲Client Libraries和Selenium Server。Client Libraries庫主要用於編寫測試腳本,用來控制Selenium Server的庫。Selenium Server負責控制瀏覽器行爲。 |
-
Selenium 2.0
2006年,Google的工程師SimonStewart發起了WebDriver的項目;因爲長期以來Google一直是Selenium的重度用戶,但卻被限制在有限的操作範圍內。
Selenium RC是在瀏覽器中運行JavaScript應用,使用瀏覽器內置的JavaScript翻譯器來翻譯和執行selenese命令(selenese是Selenium命令集合)。
WebDriver是通過原生瀏覽器支持或者瀏覽器擴展來直接控制瀏覽器。WebDriver針對各個瀏覽器而開發,取代了嵌入到被測Web應用中的JavaScript,與瀏覽器緊密集成,因此支持創建更高級的測試,避免了JavaScript安全模型導致的限制。除了來自瀏覽器廠商的支持之外,WebDriver還利用操作系統級的調用,模擬用戶輸入。
2011年,Selenium和Webdriver合併, Selenium2.0誕生。
Selenium與WebDriver原是屬於兩個不同的項目,WebDriver的創建者Simon Stewart早在2009年8月的一份郵件中解釋了項目合併的原因。 Selenium與WebDriver合併原因:爲何把兩個項目合併?部分原因是WebDriver解決了Selenium存在的缺點(例如能夠繞過JavaScript沙箱,我們有出色的API),部分原因是Selenium解決了WebDriver存在的問題(例如支持廣泛的瀏覽器),部分原因是因爲Selenium的主要貢獻者和我都覺得合併項目是爲用戶提供最優秀框架的最佳途徑。 |
Selenium 2.0 = Selenium 1.0 + WebDriver
需要強調的是,在Selenium 2.0中主推的是WebDriver,可以將其看作SeleniumRC的替代品。因爲Selenium爲了保持向下的兼容性,所以在Selenium 2.0中並沒有徹底地拋棄Selenium RC。
Selenium 2具有來自WebDriver的清晰面向對象 API,並能以最佳的方式與瀏覽器進行交互。Selenium 2不使用 JavaScript沙盒,它支持多種瀏覽器和多語言綁定。Selenium 2爲下列程序提供驅動程序:
-
Mozilla Firefox
-
Google Chrome
-
Microsoft Internet Explorer
-
Opera
-
Apple iPhone
-
Android browsers
-
……
藉助 Selenium 2,您可使用 Java、C#、Ruby、和 Python 編寫測試。Selenium2還提供基於 HtmlUnit的無外設驅動,是用於測試 Web應用程序的 Java框架。HtmlUnit運行速度特別快,但它不是一個真正與真實瀏覽器相關聯的驅動。
-
Selenium3.0
2016年7月,Selenium3.0悄悄發佈第一個beta版。
Selenium 3.0 = Selenium 2.0 + Selenium RC(Remote Control)
1.2 Selenium3現狀
1.2.1 更新
-
去掉了對selenium rc的支持。
-
全面擁抱java 8。
-
支持macOS (Sierra or later),支持官方的safaridriver。
-
通過ms官方的webdriverserver支持Edge瀏覽器。
-
只支持ie 9.0版本以上。
-
通過Mozilla官方的geckodriver來支持firefox。
儘管firefox driver非常的穩定高效,但firefoxdriver畢竟是google實現的。geckodriver的出現是必然的結果,因爲最新版本的firefox換引擎了,老的firefox driver應該是不支持新引擎的。
firefox driver究竟是什麼?爲什麼你一次都沒下載運行過? 這是因爲firefox driver包含在selenium各語言版本的分發包裏,使用webdriver啓動firefox的時候,webdriver會爲firefox安裝firefox driver擴展。 |
1.2.2 重要意義
•webdriver協議現在已經成爲業內公認的瀏覽器ui測試的標準實現。webdriver協議是google對開源測試領域的重要貢獻。
•各種官方支持意味着以後的瀏覽器ui測試的速度和穩定性會有較大的提升。
•瀏覽器ui自動化測試已經成爲了行業標配。
• selenium專注web測試。
2.1 資源列表
名稱 |
網址 |
Maven |
|
Selenium |
http://selenium-release.storage.googleapis.com/index.html |
Firefox |
http://ftp.mozilla.org/pub/firefox/releases/ |
Gecko driver |
https://github.com/mozilla/geckodriver/releases |
Chrome driver |
http://chromedriver.storage.googleapis.com/index.html https://npm.taobao.org/mirrors/chromedriver |
IE driver |
http://selenium-release.storage.googleapis.com/index.html |
Edge driver |
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ |
Opera driver |
https://github.com/operasoftware/operachromiumdriver/releases |
Safari driver |
|
PhantomJS driver |
2.2 Java
由於Selenium的限制,需要安裝Java8。
32位或64位依系統而定,如果是64位系統則兩個版本均可安裝。
2.3 Maven
我們需要創建一個測試工程,但該工程需要依賴很多jar包,爲了方便管理這些依賴,我們使用Maven進行管理。
下載Maven解壓即可使用。
我們主要需要配置Maven本地庫存放目錄,以及主倉庫地址,如:
<localRepository>E: /maven</localRepository> <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> |
注:上例使用的是阿里雲的Maven倉庫作爲鏡像站點,因爲比較快一點。
2.4 Eclipse
安裝Eclipse
(解壓)安裝Java或JavaEE版均可,但位數應與JDK匹配。
注:如果系統中JDK是綠色版,或其他註冊表信息缺失,或安裝有多個版本的JDK而不想使用默認的JDK啓動Eclipse,可以在Eclipse根目錄下找到配置文件eclipse.ini,並用文本編輯器打開,再在其中加入如下內容,指定用於啓動的JDK:
-vm <Java>/bin/java.exe |
這樣,應該就可以正常啓動Eclipse了。
配置Maven
然後,我們需要在Eclipse中使用剛剛配置好的Maven。
如下圖添加Maven配置,然後勾選使用該新配置。
然後,選擇使用Maven的配置文件,如下圖:
注意:選擇了Maven配置文件後,下面的本地倉庫路徑也會自動改變。最好,點擊下“Update Settings”更新下配置。
創建項目
要在項目中使用Maven需要創建Maven工程,因此,菜單中【New】à【Other…】,在如下彈出對話框選擇“MavenProject”:
下一步,可自定義工程位置:
下一步,根據需要選擇模板,通常測試選擇“quickstart”就可以了。
下一步,填寫參數:
完成創建,工程目錄結構如下。
其中,pom.xml文件即是工程Maven配置文件,相關依賴也將在其中配置。(具體配置見下文)
2.5 IntelliJ IDEA
待添加。
2.6 Selenium
我們可以在Selenium的官網上下載其軟件包,但由於我們使用Maven管理依賴,所以,我們只需要在工程pom.xml配置文件中加依賴即可。
<dependencies> … <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.8.1</version> </dependency> … </dependencies> |
2.7 JUnit
如果我們使用JUnit編寫測試用例,則需要在工程中增加其相關依賴:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> |
JUnit的使用這裏就不贅述了。
2.8 TestNG
待添加。
2.9 AutoIt
待添加。
2.10 Sikuli
待添加。
3. Selenium WebDriver的使用(For Java)
簡單來說,我們總是從創建WebDriver開始的,並通過WebDriver導航頁面和窗口,以及查找元素等等。
3.1 WebDriver的實例化
測試開始前,我們總是要實例化一個WebDriver對象,不同的瀏覽器構造方式不太一樣。
但總體來說,我們需要根據具體測試的瀏覽器來創建XXXDriver對象。通常的問題在於,瀏覽器可執行文件和驅動文件的位置。通常,如果瀏覽器被安裝在默認位置,則不需要在代碼中指定;而驅動文件如果加入Path路徑下,也不需要在代碼中指定。此種情況下,就可以直接new XXXDriver()創建WebDriver對象。
但一些情況下,我們可能想要手動配置測試環境,這可以通過代碼實現。
3.1.1 FirefoxDriver
指定Firefox可執行文件和驅動文件路徑最簡單的方法是,設置系統屬性:
System.setProperty("webdriver.gecko.driver", "…/geckodriver.exe"); System.setProperty("webdriver.firefox.bin", "…/firefox.exe"); |
當然,也可以使用GeckoDriverService來創建WebDriver:
FirefoxBinary bin = new FirefoxBinary(new File("…/firefox.exe")); GeckoDriverService service = new GeckoDriverService.Builder() .usingFirefoxBinary(bin) .usingDriverExecutable(new File("…/geckodriver.exe")) .build(); WebDriver driver = new FirefoxDriver(service); |
3.2 基本操作
通常,我們常用的基本操作都從WebDriver開始。
3.2.1 頁面操作
設置瀏覽器的窗口大小
driver.manage().window().maximize();//最大化 driver.manage().window().setSize(new Dimension(480, 800)); |
導航到測試頁面
driver.get( "http://www.baidu.com" ); //導航到頁面(方法一) driver.navigate().to( "http://www.baidu.com" ); //導航到頁面(方法二) |
“前進”和“後退”
driver.navigate().forward(); //前進 driver.navigate().back(); //後退 |
刷新
driver.navigate().refresh(); |
3.2.2 查找元素
常用的元素查找方法有下面兩種:
WebElement findElement(By by) java.util.List<WebElement> findElements(By by) |
findElement()返回第一個查找到的元素,如果不存在則拋出異常;findElements()返回查找到的所有元素,如果不存在返回空列表。
需要注意兩點:
-
Selenium推崇面向接口編程,因此,返回的元素都是接口WebElement;
-
WebElement也實現了查找接口,因此,也可以進行查找。
3.2.3 元素定位
查找元素時,需要指定“定位器”,通常我們使用抽象類org.openqa.selenium.By的靜態方法來創建所需的定位器。
-
By ID
通過ID查找。這是最高效也最常用的定位方式。但是,可能存在的陷阱是:網頁中ID並非唯一或者ID是自動生成的。使用中應該避免這些情況。
WebElement element = driver.findElement(By.id("xxx")); |
-
By Name
通過name屬性查找。
WebElement cheese = driver.findElement(By.name("cheese")); |
-
By XPath
通過XPath查找。WebDriver試圖在任何地方使用瀏覽器原生XPath能力,但是對於原生不支持XPath的瀏覽器,將提供實現。這可能導致一些非預期的行爲,除非你清楚不同XPath引擎間的差異。
Driver |
Tag and Attribute Name |
Attribute Values |
Native XPath Support |
Lower-cased |
As they appear in the HTML |
Yes |
|
Lower-cased |
As they appear in the HTML |
No |
|
Case insensitive |
As they appear in the HTML |
Yes |
比如如下頁面:
<input type="text" name="example" /> <INPUT type="text" name="other" /> |
查找語句爲:
List<WebElement> inputs = driver.findElements(By.xpath("//input")); |
匹配結果爲:
XPath expression |
|||
//input |
1 (“example”) |
2 |
2 |
//INPUT |
0 |
2 |
0 |
注意:有時元素不必聲明某些有默認值的屬性,比如input元素的type屬性可以缺省,缺省值爲text。但是在WebDriver中使用XPath時,你不能期望能夠匹配未聲明的默認屬性。
-
By Class Name
通過class屬性查找。實際使用中相同的class屬性一般對應多個元素,所以一般會查找到多個元素,然後取用第一個元素。
List<WebElement> cheeses = driver.findElements(By.className("cheese")); |
-
By Link Text
通過超鏈接文本查找超鏈接。
WebElement cheese = driver.findElement(By.linkText("cheese")); |
-
By Partial Link Text
通過部分超鏈接文本查找超鏈接。
WebElement cheese = driver.findElement(By.partialLinkText("cheese")); |
-
By Css Selector
通過Css Selector查找。如果瀏覽器默認原生支持css查詢,可參閱w3c css selectors;否則Sizzle被使用。IE6,7和FF3.0都使用Sizzle作爲css查詢引擎。
注意並非所有的瀏覽器都是等效的,有的css在一箇中起作用也許在另一箇中不會。
WebElement cheese = driver.findElement(By.cssSelector("#food span.dairy.aged")); |
-
By TagName
通過元素標籤名查找。
WebElement frame = driver.findElement(By.tagName("iframe")); |
3.2.4 通用操作
WebElement接口定義了很多元素的通用操作,包括點擊、輸入、信息獲取……,詳見API文檔。
3.2.5 特殊元素操作
有一些元素比較特殊,部分操作不在WebElement接口中定義,或借用某個不太直觀的方法。下面列舉一些比較特殊的用法。
-
文件域
輸入文件路徑:
file.sendKeys(filePath); |
-
下拉列表
對於下拉列表這種較複雜的元素,使用通用的方法來操作將不是那麼高效的。我們可以將其封裝爲Select對象,這將提供更多有用的方法便於操作。
Select select = new Select(driver.findElement(By.tagName("select"))); select.selectByVisibleText(“***”); select.deselectByVisibleText(“***”); select.selectByValue(“***”); select.deselectByValue(“***”); select.deselectAll(); select.getAllSelectedOptions(); select.getFirstSelectedOption(); |
-
表單
一旦填寫完表單,我們就期望提交它。一個提交的方法是找到“提交”按鈕並點擊它。
driver.findElement(By.id("submit")).click(); |
另外,元素都提供了一個方便的submit()方法。如果你調用一個處於表單中的元素的submit()方法,將沿DOM向上查找直到找到表單然後提交。如果元素不在表單中,則會拋出NoSuchElementException異常。
element.submit(); |
-
對話框
我們可以獲取到各種彈出對話框的對象,並可以執行accept、dismiss、讀取內容或者向prompt中輸入內容等操作。
Alert alert = driver.switchTo().alert(); alert.accept(); alert.dismiss(); alert.getText(); alert. sendKeys(); |
3.2.6 窗口及框架切換
擴展知識
需要理解的一點是,當瀏覽器打開一個頁面時,可能存在彈出窗口,或者頁面是框架集結構,或者包含有iframe。 這些情況下,Selenium的“焦點”是在主窗口的頂級文檔之上的。 要操作主窗口頂級文檔之外的元素,則需要轉換“焦點”。 |
Selenium支持在命名窗口間切換:
driver.switchTo().window(nameOrHandle); |
怎樣知道窗口的名字呢?查看一下打開它的JS或超鏈接:
<a href="somewhere.html" target="windowName">Click here to open a new window</a> |
另外,也可以使用窗口句柄,這可能需要迭代所有窗口句柄來獲取某個窗口的句柄了:
for (String handle : driver.getWindowHandles()) { driver.switchTo().window(handle); } |
在框架間切換也是類似的:
driver.switchTo().frame("frameName");
WebElement xf = driver.findElement(by); driver.switchTo().frame(xf);
driver.switchTo().defaultContent(); |
3.3 高級操作
3.3.1 鼠標操作
//拖拽元素到目標元素中 new Actions( driver ).dragAndDrop( element, target ).perform(); // hover new Actions(driver).moveToElement( text ).perform(); |
3.3.2 鍵盤操作
sendKeys(Keys.CONTROL, "a"); //組合鍵 |
3.3.3 等待
無條件等待
Sleeper.SYSTEM_SLEEPER.sleep(new Duration(5, TimeUnit.SECONDS)); |
等待有2種:顯性等待和隱性等待。
顯式等待
顯式等待使用WebDriverWait類和ExpectedCondition接口完成,編碼實現ExpectedCondition接口用以判斷某種條件,然後等待這種條件達成或超時。
WebElement myDynamicElement = (new WebDriverWait(driver, 10)) .until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement"))); |
ExpectedConditions類提供了許多靜態工廠方法,返回常用的ExpectedCondition對象。
隱式等待
隱式等待影響設置後全局的相關操作的等待時間。
//頁面加載超時時間設置爲5s。超時異常。 driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS); //定位對象超時時間設置爲10s。超時NoSuchElement異常。 driver.manage().timeouts().implicitlyWait( 10, TimeUnit.SECONDS ); //異步腳本的超時時間設置爲3s。 driver.manage().timeouts().setScriptTimeout(3, TimeUnit.SECONDS); |
3.3.4 截圖
測試過程中,可以把頁面截圖,保存成爲圖片。
需要注意,截取的圖片存在臨時目錄,所以需要將其拷貝到指定的目錄,否則測試完成可就找不到截圖了。
File screenshotFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile( screenshotFile, new File("E:\\1.png") ); |
3.3.5 執行JS
可以執行任意JS腳本來查找一個元素,並且只要返回一個DOM元素,它將被自動轉換爲WebElement對象。
WebElement element = (WebElement) ((JavascriptExecutor)driver).executeScript("return $('.cheese')[0]"); |
3.3.6 Cookie
Cookie c1 = new Cookie("name", "key-aaaaaaa"); Cookie c2 = new Cookie("value", "value-bbbbbb"); driver.manage().addCookie(c1); driver.manage().addCookie(c2);
//獲得 cookie Set<Cookie> coo = driver.manage().getCookies(); //刪除所有 cookie //driver.manage().deleteAllCookies(); |
3.3.7 下載
下載文件時有個特殊的問題是,可能會彈出下載窗口,而該窗口屬於系統窗口,超出了頁面範疇,並且selenium也沒有提供接口進行相關操作。
一種處理方案是通過類似autoIt這樣的腳本對下載窗口進行處理,另一種方案是配置瀏覽器使其自動下載到指定目錄。
當然,前一種方案已經超出了selenium的範疇,這裏不進行討論。我們來看第二種方案如何實現。
-
Firefox
FirefoxProfile profile = new FirefoxProfile(); profile.setPreference("browser.download.folderList", 2); profile.setPreference("browser.download.dir", "d:\\java"); profile.setPreference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream"); |
以上代碼設置了Firefox的首選項,它們分別代表:
browser.download.folderList
0 -下載到瀏覽器默認下載路徑;
2 -保存到指定目錄。
browser.download.dir
指定所下載文件的目錄
browser.helperApps.neverAsk.saveToDisk
指定要下載頁面的 Content-type值,“binary/octet-stream”爲文件的類型。
-
Chrome
HashMap<String, Object> chromePrefs = new HashMap<String, Object>(); chromePrefs.put("profile.default_content_settings.popups", 0); chromePrefs.put("download.default_directory", downloadFilepath); ChromeOptions options = new ChromeOptions(); HashMap<String, Object> chromeOptionsMap = new HashMap<String, Object>(); options.setExperimentalOption("prefs",chromePrefs); options.addArguments("--test-type"); DesiredCapabilities cap = DesiredCapabilities.chrome(); cap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap); cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true); cap.setCapability(ChromeOptions.CAPABILITY, options); |
profile.default_content_settings.popups
0 -禁止彈出下載窗口
download.default_directory
文件下載路徑
4. 附錄
4.1 注意事項
4.1.1 關於click()
當調用WebElement.click()時,如果被操作元素是不可用的(disabled),click()方法調用仍會是正常的,不會有異常。
所以,如果會出現被點擊的元素是不可用的情況,而點擊不可用元素又被認爲是非法的,那麼應該在click()調用前使用isEnable()方法檢查元素可用性。
4.1.2 driver.close() vs.driver.quit()
在測試結束後通常需要關閉瀏覽器,這個操作通常使用close()或quit()方法完成。但是兩者是有區別的,其方法說明也體現了這一點。
close() |
Close the current window, quitting the browser if it's the last window currently open. |
quit() |
Quits this driver, closing every associated window. |
對於close()而言,如果當前窗口是最後一個打開窗口,那麼關閉當前窗口退出瀏覽器;quit()則關閉每個關聯的窗口退出瀏覽器。
實際使用中發現,即使是隻有最後一個窗口的情況下,調用兩個方法還是有差異的。簡單來說,close()通常不會關閉驅動進程,會使驅動進程駐留內存;而quit()方法會關閉驅動進程,不過總是會有個進程終止錯誤,但可忽略。總之,應儘量使用quit()來結束測試。
4.2 FAQ
4.2.1 關於Firefox驅動兼容性
-
Gecko driver對Firefox的兼容性
Gecko驅動的發佈頁面會說明推薦的Fireofx版本
Note that with geckodrwer vO.19.O the following versions are recommended:
• Firefox 55.0 (and greater)
• Selenium 3.5 (and greater)
-
內置Webdriver對Firefox的兼容性
如果使用webdriver驅動,則需要在selenium-server-standalone-x.x.x.jar!\org\openqa\selenium\firefox\webdriver.xpi!\install.rdf
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>...</em:id>
<em:minVersion>3.0</em:minVersion>
<em:maxVersion>52 0</em:maxVersion>
</Description>
</em:targetApplication>
注:selenium3.8.1已不再使用Webdrver驅動,而轉用Gecko驅動,但這些文件還是保留的。
4.2.2 Headless
-
htmlunit
selenium內置無頭瀏覽器內核,純Java編寫,頁面渲染能力可能與預期不一致。
-
PhantomJS
使用 QtWebKit瀏覽器內核渲染頁面,基本可以和真正瀏覽器保持一致。
-
Chrome-headless
Google針對 Chrome瀏覽器 59版新增加的一種模式,可以讓你不打開UI界面的情況下使用 Chrome瀏覽器,所以運行效果與 Chrome保持完美一致。
ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--headless"); WebDriver driver = new ChromeDriver(chromeOptions); |
4.3 參考
4.3.1 Chrome driver 與 chrome版本對應
chromedriver版本 |
支持的Chrome版本 |
v2.34 |
v61-63 |
v2.33 |
v60-62 |
v2.32 |
v59-61 |
v2.31 |
v58-60 |
v2.30 |
v58-60 |
v2.29 |
v56-58 |
v2.28 |
v55-57 |
v2.27 |
v54-56 |
v2.26 |
v53-55 |
v2.25 |
v53-55 |
v2.24 |
v52-54 |
v2.23 |
v51-53 |
v2.22 |
v49-52 |
v2.21 |
v46-50 |
v2.20 |
v43-48 |
v2.19 |
v43-47 |
v2.18 |
v43-46 |
v2.17 |
v42-43 |
v2.13 |
v42-45 |
v2.15 |
v40-43 |
v2.14 |
v39-42 |
v2.13 |
v38-41 |
v2.12 |
v36-40 |
v2.11 |
v36-40 |
v2.10 |
v33-36 |
v2.9 |
v31-34 |
v2.8 |
v30-33 |
v2.7 |
v30-33 |
v2.6 |
v29-32 |
v2.5 |
v29-32 |
v2.4 |
v29-32 |
4.4 知識擴展
4.4.1 W3C WebDriver
參考文檔:
https://www.w3.org/TR/webdriver/