Selenium 2 常見問題

從 Selenium 1 遷移到 Selenium 2 的注意事項

此文件先前位於 wiki 上 \

問:什麼是 WebDriver?

答:WebDriver 是一個用於編寫網站自動化測試的工具。它的目標是模仿真實使用者的行為,因此與應用程式的 HTML 互動。

問:那麼,它像 Selenium 嗎?還是 Sahi

答:目標是相同的(讓您測試您的網路應用程式),但實作方式不同。WebDriver 不是作為瀏覽器內的 Javascript 應用程式執行(受限於此帶來的限制,例如「同源」問題),而是控制瀏覽器本身。這表示它可以利用原生平台提供的任何功能。

問:什麼是 Selenium 2.0?

答:WebDriver 是 Selenium 的一部分。WebDriver 的主要貢獻是其 API 和原生驅動程式。

問:我該如何從使用原始 Selenium API 遷移到新的 WebDriver API?

答:遷移過程在 Selenium 文件中描述,網址為 http://seleniumhq.org/docs/appendix_migrating_from_rc_to_webdriver.html

問:WebDriver 支援哪些瀏覽器?

答:現有的驅動程式包括 ChromeDriver、InternetExplorerDriver、FirefoxDriver、OperaDriver 和 HtmlUnitDriver。如需每個驅動程式的更多資訊,包括它們的相對優勢和劣勢,請點擊連結至相關頁面。此外,也透過 AndroidDriver、OperaMobileDriver 和 IPhoneDriver 支援行動裝置測試。

問:所謂「以開發人員為中心」是什麼意思?

答:我們認為,在軟體應用程式開發團隊中,最適合建構其他人可以使用的工具的人員是開發人員。雖然直接使用 WebDriver 應該很容易,但將其作為更複雜工具的建構模組也應該很容易。因此,WebDriver 具有一個小型的 API,透過點擊您最愛的 IDE 中的「自動完成」按鈕即可輕鬆探索,並旨在無論您使用哪種瀏覽器實作,都能保持一致地運作。

問:我該如何直接執行 Javascript?

答:我們認為,在大多數需要執行 Javascript 的時候,都是因為正在使用的工具存在缺陷:它沒有發出正確的事件、沒有正確地與頁面互動,或者在 XmlHttpRequest 返回時沒有做出反應。我們寧願修正 WebDriver 以使其一致且正確地運作,而不是依賴測試人員找出要呼叫哪個 Javascript 方法。

我們也意識到,有時這會成為一種限制。因此,對於那些支援的瀏覽器,您可以透過將 WebDriver 實例轉換為 JavascriptExecutor (http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/JavascriptExecutor.html) 來執行 Javascript。在 Java 中,這看起來像這樣

WebDriver driver; // Assigned elsewhere
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("return document.title");

其他語言綁定將遵循類似的方法。請查看 UsingJavascript 頁面以取得更多資訊。

問:為什麼我的 Javascript 執行總是返回 null?

答:您需要從您的 javascript 片段返回一個值才能返回一個值,所以

js.executeScript("document.title");

將返回 null,但是

js.executeScript("return document.title");

將返回文件的標題。

問:我的 XPath 在一個瀏覽器中找到元素,但在其他瀏覽器中卻找不到。這是為什麼?

答:簡短的答案是,每個支援的瀏覽器處理 XPath 的方式略有不同,而您可能遇到了其中一個差異。完整的答案在 XpathInWebDriver 頁面上。

問:InternetExplorerDriver 在 Vista 上運作不佳。我該如何讓它如預期般運作?

答:InternetExplorerDriver 要求所有安全性網域都設定為相同的值(受信任或不受信任)。如果您無法修改安全性網域,則可以像這樣覆寫檢查

DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer();
capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
WebDriver driver = new InternetExplorerDriver(capabilities);

從常數的名稱可以看出,這可能會在您的測試中引入不穩定性。如果所有網站都位於相同的保護網域中,您應該沒問題。

問:除了 Java 之外,還支援其他語言嗎?

答:Python、Ruby、C# 和 Java 都由開發團隊直接支援。還有適用於 PHP 和 Perl 的 webdriver 實作。也計劃支援純 JS API。

問:我該如何處理彈出視窗?

答:WebDriver 提供處理多個視窗的能力。這是透過使用「WebDriver.switchTo().window()」方法切換到具有已知名稱的視窗來完成的。如果名稱未知,您可以使用「WebDriver.getWindowHandles()」來取得已知視窗的列表。您可以將句柄傳遞給「switchTo().window()」。

問:WebDriver 支援 Javascript 警示和提示嗎?

答:是的,使用 Alerts API (http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/Alert.html)

// Get a handle to the open alert, prompt or confirmation
Alert alert = driver.switchTo().alert();
// Get the text of the alert or prompt
alert.getText();  
// And acknowledge the alert (equivalent to clicking "OK")
alert.accept();

問:WebDriver 支援檔案上傳嗎?

答:是的。

您無法直接與原生 OS 檔案瀏覽器對話方塊互動,但我們做了一些魔術,以便如果您在檔案上傳元素上呼叫 WebElement#sendKeys("/path/to/file"),它會執行正確的操作。請確保您不要 WebElement#click() 檔案上傳元素,否則瀏覽器可能會掛起。

實用提示:您無法與隱藏元素互動,除非讓它們取消隱藏。如果您的元素被隱藏,則可以使用如下程式碼取消隱藏

((JavascriptExecutor)driver).executeScript("arguments[0].style.visibility = 'visible'; arguments[0].style.height = '1px'; arguments[0].style.width = '1px'; arguments[0].style.opacity = 1", fileUploadElement);

問:「onchange」事件在呼叫「sendKeys」後沒有觸發

答:WebDriver 將焦點留在您呼叫「sendKeys」的元素上。「onchange」事件只會在焦點離開該元素時觸發。因此,您需要移動焦點,或許可以點擊另一個元素。

問:我可以執行 WebDriver 子類別的多個實例嗎?

答:HtmlUnitDriver、ChromeDriver 和 FirefoxDriver 的每個實例都完全獨立於其他每個實例(對於 firefox 和 chrome,每個實例都有其自己的匿名設定檔)。由於 Windows 的運作方式,一次應該只會有一個 InternetExplorerDriver 實例。如果您需要一次執行多個 InternetExplorerDriver 實例,請考慮使用 Remote!WebDriver 和虛擬機器。

問:我需要使用代理伺服器。我該如何設定?

答:代理伺服器組態是透過 org.openqa.selenium.Proxy 類別完成的,如下所示

Proxy proxy = new Proxy();
proxy.setProxyAutoconfigUrl("http://youdomain/config");

// We use firefox as an example here.
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(CapabilityType.PROXY, proxy);

// You could use any webdriver implementation here
WebDriver driver = new FirefoxDriver(capabilities);

問:我該如何使用 HtmlUnitDriver 處理身份驗證?

答:在建立 HtmlUnitDriver 的實例時,覆寫「modifyWebClient」方法,例如

WebDriver driver = new HtmlUnitDriver() {
  protected WebClient modifyWebClient(WebClient client) {
    // This class ships with HtmlUnit itself
    DefaultCredentialsProvider creds = new DefaultCredentialsProvider();

    // Set some example credentials
    creds.addCredentials("username", "password");

    // And now add the provider to the webClient instance
    client.setCredentialsProvider(creds);

    return client;
  }
};

問:WebDriver 是執行緒安全的嗎?

答:WebDriver 不是執行緒安全的。話雖如此,如果您可以序列化對基礎驅動程式實例的存取,則可以在多個執行緒中共享參考。這是不建議的。另一方面,您可以為每個執行緒實例化一個 WebDriver 實例。

問:我該如何在 contentEditable iframe 中輸入內容?

答:假設 iframe 名為「foo」

driver.switchTo().frame("foo");
WebElement editable = driver.switchTo().activeElement();
editable.sendKeys("Your text here");

有時這不起作用,這是因為 iframe 沒有任何內容。在 Firefox 上,您可以在「sendKeys」之前執行以下操作

((JavascriptExecutor) driver).executeScript("document.body.innerHTML = '<br>'");

這是必要的,因為 iframe 預設沒有內容:沒有任何東西可以發送鍵盤輸入。此方法呼叫會插入一個空的標籤,這會很好地設定一切。

完成後,請記住切換出框架(因為所有進一步的互動都將針對此特定框架)

driver.switchTo().defaultContent();

問:WebDriver 無法在 Linux 上啟動 Firefox,因為 java.net.SocketException

答:如果在 Linux 上執行 WebDriver 時,Firefox 無法啟動,並且錯誤看起來像

Caused by: java.net.SocketException: Invalid argument
        at java.net.PlainSocketImpl.socketBind(Native Method)
        at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:365)
        at java.net.Socket.bind(Socket.java:571)
        at org.openqa.selenium.firefox.internal.SocketLock.isLockFree(SocketLock.java:99)
        at org.openqa.selenium.firefox.internal.SocketLock.lock(SocketLock.java:63)

這可能是由於機器上的 IPv6 設定所致。執行

sudo sysctl net.ipv6.bindv6only=0

使 socket 使用相同的呼叫綁定到主機的 IPv6 和 IPv4 位址。更永久的解決方案是透過編輯 /etc/sysctl.d/bindv6only.conf 來停用此行為

問:WebDriver 無法找到元素 / 沒有在頁面載入時封鎖

答:此問題可能會以各種方式顯現出來

  • 使用 WebDriver.findElement(…) 拋出 ElementNotFoundException,但元素顯然存在 - 檢查 DOM(使用 Firebug 等)清楚地顯示它。
  • 呼叫 Driver.get 會在 HTML 載入後返回 - 但由 onload 事件觸發的 Javascript 程式碼尚未完成,因此頁面不完整,並且無法找到某些元素。
  • 點擊元素 / 連結會觸發建立新元素的操作。但是,在點擊返回後呼叫 findElement(s) 找不到它。點擊不應該是封鎖的嗎?
  • 我如何知道頁面何時完成載入?

說明:WebDriver 通常具有封鎖 API。但是,在某些情況下,get 呼叫可能會在頁面完成載入之前返回。典型的範例是 Javascript 在頁面載入後開始執行(由 onload 觸發)。瀏覽器(例如 Firefox)會在基本 HTML 內容載入時通知 WebDriver,這就是 WebDriver 返回的時間。很難(如果不是不可能)知道 Javascript 何時完成執行,因為 JS 程式碼可能會排程在未來呼叫的函數、依賴伺服器回應等等。點擊也是如此 - 當平台支援原生事件(Windows、Linux)時,點擊是透過在 OS 層級發送具有元素座標的滑鼠點擊事件來完成的 - WebDriver 無法追蹤此點擊建立的確切操作順序。因此,封鎖 API 是不完美的 - WebDriver 無法等待所有條件都滿足後才繼續測試,因為它不知道這些條件。通常,重要的是下一個互動中涉及的元素是否存在且已準備就緒。

解決方案:使用 Wait 類別等待特定元素出現。此類別只會重複呼叫 findElement,每次都丟棄 NoSuchElementException,直到找到元素(或逾時)。由於這是許多使用者預設需要的行為,因此已實作一種隱式等待元素出現的機制。可以透過 WebDriver.manage().timeouts() 呼叫來存取它。(這之前在 issue 26 中追蹤)。

問:我該如何在頁面上觸發任意事件?

答:WebDriver 旨在模擬使用者互動 - 因此 API 反映了使用者可以與各種元素互動的方式。

觸發特定事件無法使用 API 直接達成,但可以使用 Javascript 執行功能來呼叫元素上的方法。

問:為什麼無法與隱藏元素互動?

答:由於使用者無法讀取隱藏元素中的文字,因此 WebDriver 也將不允許存取它。

但是,可以使用 Javascript 執行功能直接從元素呼叫 getText

WebElement element = ...;
((JavascriptExecutor) driver).executeScript("return arguments[0].getText();", element);

問:我該如何啟動已安裝擴充功能的 Firefox?

FirefoxProfile profile = new FirefoxProfile()
profile.addExtension(....);

WebDriver driver = new FirefoxDriver(profile);

問:我希望 WebDriver 可以做到……

答:如果您希望 WebDriver 執行某些操作,或者您發現了錯誤,請在 WebDriver 專案頁面中 新增一個 issue

問:Selenium 伺服器有時需要很長時間才能啟動新工作階段?

答:如果您在 linux 上執行,則需要增加可用於安全隨機數產生的熵量。大多數 linux 發行版可以安裝一個名為「randomsound」的套件來執行此操作。

在 Windows (XP) 上,您可能會遇到 http://bugs.sun.com/view_bug.do?bug_id=6705872,這通常表示要清除 temp 目錄中的大量檔案。temp 目錄。

問:Selenium WebDriver API 中相當於 TextPresent ? 的是什麼?

driver.findElement(By.tagName("body")).getText()

將取得頁面的文字。若要驗證 TextPresent/assertTextPresent,您可以從中使用您最愛的測試框架來斷言文字。若要 waitForTextPresent,您可能需要研究 WebDriverWait 類別。

問:Socket 鎖定似乎是一個糟糕的設計。我可以做得更好

答:用於保護 firefox 啟動的 socket 鎖定是根據以下設計約束建構的

  • 它在所有語言綁定之間共享;ruby、java 和任何其他綁定可以同時在同一部機器上共存。
  • 啟動 firefox 的某些關鍵部分必須在有問題的機器上獨佔鎖定。
  • socket 鎖定本身不是主要瓶頸,啟動 firefox 才是。

SocketLock 是 Lock 介面的實作。這允許為您自己的實作提供可插拔的策略。若要切換到不同的實作,請子類別化 FirefoxDriver 並覆寫「obtainLock」方法。

問:為什麼我在 python 中使用 send_keys 時會收到 UnicodeEncodeError

答:您的系統可能未設定 Locale。請設定一個 locale LANG=en_US.UTF-8 和 LC_CTYPE=“en_US.UTF-8”,例如。

上次修改時間:2024 年 4 月 5 日:連結失效 (#1612)[部署網站] (c73064b0d9b)