<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # WebDriverJS WebDriver 的 JavaScript 語言綁定。本文包含以下內容: - 介紹 - 快速上手 - 在 Node 中運行 - 在瀏覽器中運行 - 設計細節 - 管理異步 API - 同服務端通訊 - /xdrpc - 未來計劃 ## 介紹 WebDriver 的 JavaScript 綁定(WebDriverJS),可以使 JavaScript 開發人員避免上下文切換的開銷,并且可以讓他們使用和項目開發代碼一樣的語言來編寫測試。WebDriverJS 既可以在服務端運行,例如 Node,也可以在瀏覽器中運行。 **警告:** WebDriverJS 要求開發者習慣異步編程。對于那些 JavaScript 新手來說可能會發現 WebDriverJS 有點難上手。 ## 快速上手 ### 在 Node 中運行 雖然 WebDriverJS 可以在 Node 中運行,但它至今還沒有實現本地驅動的支持(也就是說,你的測試必須使用一個遠程的 WebDriver 服務)。并且,你必須編譯 Selenium 服務端,將其添加到 WebDriverJS 模塊。進入 Selenium 客戶端的根目錄,執行: $ ./go selenium-server-standalone //javascript/node:webdriver 當兩個目標都被編譯好以后,啟動服務和 Node,開始編寫測試代碼: $ java -jar build/java/server/src/org/openqa/grid/selenium/selenium-standalone.jar & $ node var webdriver = require('./build/javascript/node/webdriver'); var driver = new webdriver.Builder(). usingServer('http://localhost:4444/wd/hub'). withCapabilities({ 'browserName': 'chrome', 'version': '', 'platform': 'ANY', 'javascriptEnabled': true }). build(); driver.get('http://www.google.com'); driver.findElement(webdriver.By.name('q')).sendKeys('webdriver'); driver.findElement(webdriver.By.name('btnG')).click(); driver.getTitle().then(function(title) { require('assert').equal('webdriver - Google Search', title); }); driver.quit(); ### 在瀏覽器中運行 除了 Node,WebDriverJS 也可以直接在瀏覽器中運行。編譯比Node方式少很多依賴的瀏覽器模塊,運行: $ ./go //javascript/webdriver:webdriver 為了和可能不在同一個域下的 WebDriver 的服務端進行通信,客戶端使用的是修改過的 [JsonWireProtocol](https://code.google.com/p/selenium/wiki/JsonWireProtocol) 和 [cross-origin resource sharing](https://code.google.com/p/selenium/wiki/WebDriverJs#Cross-Origin_Resource_Sharing): <!DOCTYPE html> <script src="webdriver.js"></script> <script> var client = new webdriver.http.CorsClient('http://localhost:4444/wd/hub'); var executor = new webdriver.http.Executor(client); // 啟動一個新瀏覽器,這個瀏覽器可以被這段腳本控制 var driver = webdriver.WebDriver.createSession(executor, { 'browserName': 'chrome', 'version': '', 'platform': 'ANY', 'javascriptEnabled': true }); driver.get('http://www.google.com'); driver.findElement(webdriver.By.name('q')).sendKeys('webdriver'); driver.findElement(webdriver.By.name('btnG')).click(); driver.getTitle().then(function(title) { if (title !== 'webdriver - Google Search') { throw new Error( 'Expected "webdriver - Google Search", but was "' + title + '"'); } }); driver.quit(); </script> #### 控制宿主瀏覽器 啟動一個瀏覽器運行 WebDriver 來測試另一個瀏覽器看起來比較冗余(相比在 Node 中運行而言)。但是,使用 WebDriverJS 在瀏覽器中運行自動化測試是瀏覽器真實在跑這些腳本的。這只要服務端的 url 和瀏覽器的 session id 是已知的就可以實現。這些值可能會直接傳遞給 builder,它們也可以通過從頁面 url 的查詢字符串中解析出來的 wdurl 和 wdsid 定義 。 <!-- Assuming HTML URL is /test.html?wdurl=http://localhost:4444/wd/hub&wdsid=foo1234 --> <!DOCTYPE html> <script src="webdriver.js"></script> <input id="input" type="text"/> <script> // Attaches to the server and session controlling this browser. var driver = new webdriver.Builder().build(); var input = driver.findElement(webdriver.By.tagName('input')); input.sendKeys('foo bar baz').then(function() { assertEquals('foo bar baz', document.getElementById('input').value); }); </script> ##### 警告 在瀏覽器中使用 WebDriverJS 有幾個需要注意的地方。首先,webdriver.Builder 類只能用于已存在的 session。為了獲得一個新的 session,你必須像上面的例子那樣手工創建。其次,有一些命令可能會影響運行 WebDriverJS 腳本的頁面。 - webdriver.WebDriver#quit: quit 命令將終止整個瀏覽器進程,包括在運行 WebDriverJS 的窗口。除非你確定要這樣做,否則不要使用這個命令。 - webdriver.WebDriver#get: WebDriver 的接口被設計為盡量接近用戶的操作。這意味著無論 WebDriver 客戶端當前聚焦在哪個幀,導航命令(如:driver.get(url))總是指向最高層的幀。在操作宿主瀏覽器時,WebDriverJS 腳本可以通過使用 .get 命令導航離開當前頁面,而當前頁面仍然獲得焦點。 如果要自動操作一個宿主瀏覽器但仍想在頁面間跳轉,請把WebDriver客戶端的焦點設在另一個窗口上(這和Selenium RC 的多窗口模式的概念非常相似): <!DOCTYPE html> <script src="webdriver.js"></script> <script> var testWindow = window.open('', 'slave'); var driver = new webdriver.Builder().build(); driver.switchTo().window('slave'); driver.get('http://www.google.com'); driver.findElement(webdriver.By.name('q')).sendKeys('webdriver'); driver.findElement(webdriver.By.name('btnG')).click(); </script> #### 調試 Tests 你可以使用 WebDriver 的服務來調試在瀏覽器中使用 WebDriverJS 運行的測試。 $ ./go selenium-server-standalone $ java -jar \ -Dwebdriver.server.session.timeout=0 \ build/java/server/src/org/openqa/grid/selenium/selenium-standalone.jar & 啟動服務后,訪問 WebDriver 的控制面板: http://localhost:4444/wd/hub。你可以使用這個控制面板查看,創建或者刪除 sessions。選擇一個要調試的 session 后,點擊 “load script” 按鈕。在彈出的對話框中,輸入你的 WebDriverJS 測試的地址:服務端將在你的瀏覽器中打開這個頁面,這個頁面的 url 含有額外的參數用于 WebDriverJS 客戶端和服務端的通訊。 ##### 支持的瀏覽器 - IE 8+ - Firefox 4+ - Chrome 12+ - Opera 12.0a+ - Android 4.0+ ## 設計細節 ### 管理異步 API 不同于其他那些提供了阻塞式 API 的語言綁定,WebDriverJS 完全是異步的。為了追蹤每個命令的執行狀態, WebDriverJS 對 “promise” 進行了擴展。promise 是一個這樣的對象,它包含了在未來某一點可用的一個值。JavaScript 有幾個 promise 的實現,WebDriverJS 的 promise 是基于 CommonJS 的 [Promise/A](http://www.google.com/url?q=http%3A%2F%2Fwiki.commonjs.org%2Fwiki%2FPromises%2FA&sa=D&sntz=1&usg=AFQjCNGC0NMXO-81exam-S5HjTuOxaV_mw) 提議,它定義了 promise 是任意對象上的 then 函數屬性。 /** * Registers listeners for when this instance is resolved. * * @param {?function(*)} callback The function to call if this promise is * successfully resolved. The function should expect a single argument: the * promise's resolved value. * @param {?function(*)=} opt_errback The function to call if this promise is * rejected. The function should expect a single argument: the failure * reason. While this argument is typically an {@code Error}, any type is * permissible. * @return {!Promise} A new promise which will be resolved * with the result of the invoked callback. */ Promise.prototype.then = function(callback, opt_errback) { }; 通過使用 promises,你可以將一連串的異步操作連接起來,確保每個操作執行時,它之前的操作都已經完成: var driver = new webdriver.Builder().build(); driver.get('http://www.google.com').then(function() { return driver.findElement(webdriver.By.name('q')).then(function(searchBox){ return searchBox.sendKeys('webdriver').then(function() { return driver.findElement(webdriver.By.name('btnG')).then(function(submitButton) { return submitButton.click().then(function() { return driver.getTitle().then(function(title) { assertEquals('webdriver - Google Search', title); }); }); }); }); }); }); 不幸的是,上述范例非常冗長,難以辨別測試的意圖。為了提供一套不降低測試可讀性的干凈利落的異步操作 API, WebDriverJS 引入了一個 promise “管理器” 來調度和執行所有的命令。 簡言之,promise 管理器處理用戶自定義任務的調度和執行。管理器保存了一個任務調度的列表,當列表中的某個任務執行完畢后,依次執行下一個任務。如果一個任務返回了一個 promise,管理器將把它當做一個回調注冊,在這個 promise 完成后恢復其運行。WebDriver 將自動使用管理器,所以用戶不需要使用鏈式調用。因此,之前的 google 搜索的例子可以簡化成: var driver = new webdriver.Builder().build(); driver.get('http://www.google.com'); var searchBox = driver.findElement(webdriver.By.name('q')); searchBox.sendKeys('webdriver'); var submitButton = driver.findElement(webdriver.By.name('btnG')); submitButton.click(); driver.getTitle().then(function(title) { assertEquals('webdriver - Google Search', title); }); #### On Frames and Callbacks 就內部而言,promise 管理器保存了一個調用棧。在管理器執行循環的每一圈,它將從最頂層幀的隊列中取一個任務來執行。任何被包含在之前命令的回調中的命令將被排列在一個新幀中,以確保它們能在所有早先排列的任務之前運行。這樣做的結果是,如果你的測試是 written-in line,所有的回調都使用函數字面量定義,命令將按照它們在屏幕上出現的垂直順序來執行。例如,考慮以下 WebDriverJS 測試用例: driver.get(MY_APP_URL); driver.getTitle().then(function(title) { if (title === 'Login page') { driver.findElement(webdriver.By.id('user')).sendKeys('bugs'); driver.findElement(webdriver.By.id('pw')).sendKeys('bunny'); driver.findElement(webdriver.By.id('login')).click(); } }); driver.findElement(webdriver.By.id('userPreferences')).click(); 這個測試用例可以使用 WebDriver 的 Java API 重寫如下: driver.get(MY_APP_URL); if ("Login Page".equals(driver.getTitle())) { driver.findElement(By.id("user")).sendKeys("bugs"); driver.findElement(By.id("pw")).sendKeys("bunny"); driver.findElement(By.id("login")).click(); } driver.findElement(By.id("userPreferences")).click(); #### 錯誤處理 既然所有 WebDriverJS 的操作都是異步執行的,我們就不能使用 try-catch 語句。取而代之的是,你必須為所有命令的 promise 返回注冊一個錯誤處理的函數。這個錯誤處理函數可以拋出一個錯誤,在這種情況下,它將被傳遞給鏈中的下一個錯誤處理,或者他將返回一個不同的值來抑制這個錯誤并切換回回調處理鏈。 如果錯誤處理器沒有正確的處理被拒絕的 promise(不只是哪些來自于 WebDriver 命令的),則這個錯誤會傳播至錯誤處理鏈的父級幀。如果一個錯誤沒有被抑制而傳播到了頂層幀,promise 管理器要么觸發一個 uncaughtException 事件(如果有注冊監聽的話),或者將錯誤拋給全局錯誤處理器。在這兩種情況下,promise 管理器都將拋棄所有隊列中后續的命令。 // 注冊一個事件監聽未處理的錯誤 webdriver.promise.Application. getInstance(). on('uncaughtException', function(e) { console.error('There was an uncaught exception: ' + e.message); }); driver.switchTo().window('foo').then(null, function(e) { // 忽略 NoSuchWindow 錯誤,讓其他類型的錯誤繼續向上冒泡 if (e.code !== bot.ErrorCode.NO_SUCH_WINDOW) { throw e; } }); // 如果上面的錯誤不被抑制的話,這句將永遠不會執行 driver.getTitle(); ### 同服務端通訊 當在服務端環境中運行時,客戶端不受安全沙箱的約束,可以簡單的發送 http 請求(例如:node 的 http.ClientRequest)。當在瀏覽器端運行時,WebDriverJS 客戶端就會收到同源策略的約束。為了和可能不在同一個域下的服務端通訊,WebDriverJS 客戶端使用的是修改過的 JsonWireProtocol 和 cross-origin resource sharing。 #### Cross-Origin Resource Sharing 如果一個瀏覽器支持 cross-origin resource sharing (CORS), WebDriverJS 將使用 cross-origin XMLHttpRequests (XDR) 發送命令給服務端。服務端要想支持 XDR,就需要響應 preflight 請求,并帶有合適的 access-control 頭。 Access-Control-Origin: * Access-Control-Allow-Methods: DELETE,GET,HEAD,POST Access-Control-Allow-Headers: Accept,Content-Type 在編寫本文時,已有 Firefox 4+, Chrome 12+, Safari 4+, Mobile Safari 3.2+, Android 2.1+, Opera 12.0a, 和 IE8+ 支持 CORS。不幸的是,這些瀏覽器的實現并不一致,也不是完全都遵循 W3C 的規范。 - IE 的 XDomainRequest 對象,比其 XMLHttpRequest 對象的功能要弱。XDomainRequest 只能發送哪些標準的 form 表單可以發送的請求。這限制了 IE 只能發送 get 和 post 請求(wire 協議要求支持 delete 請求)。 - WebKit 的 CORS 實現禁止了跨域請求的重定向,即使 access-control 頭被正確設置了也是如此。 - 如果返回一個服務端錯誤(4xx 或 5xx),IE 和 Opera 的實現將觸發 XDomainRequest/XMLHttpRequest 對象的錯誤處理,但是拿不到服務端返回的信息。這使得它們無法處理以標準的 JSON 格式返回的錯誤信息。 為了彌補這些短處,當在瀏覽器中運行時,WebDriverJS 將使用修改過的 JsonWireProtocol 和通過 /xdrpc 路由所有的命令。 #### /xdrpc **POST /xdrpc** 作為命令的代理,所有命令相關的內容必須被編碼成 JSON 格式。命令的執行結果將在 HTTP 200 響應中作為一個標準的響應結果返回。客戶端依賴于響應的轉臺嗎以確認命令是否執行成功。 **參數:** - method - {string} http 方法 - path - {string} 命令路徑 - data - {Object} JSON 格式的命令參數 **返回:** {*} 命令執行的結果。 舉個例子,考慮以下 /xdrpc 命令: POST /xdrpc HTTP/1.1 Accept: application/json Content-Type: application/json Content-Length: 94 {"method":"POST","path":"/session/123/element/0a/element","data":{"using":"id","value":"foo"}} 服務端將編碼這個命令并重新分發: POST /session/123/element/0a/element HTTP/1.1 Accept: application/json Content-Type: application/json Content-Length: 28 {"using":"id","value":"foo"} 不管是否成功,命令的執行結果都將作為一個標準的 JSON 返回: HTTP/1.1 200 OK Content-Type: application/json Content-Length: 60 {"status":7,"value":{"message":"Unable to locate element."}} ## 未來計劃 以下是一些預期要做的事情。但什么時候完成,在現在仍然未知。如果你有興趣參與開發,請加入 selenium-developers@googlegroups.com。當然,這是一個開源軟件,你完全不需要等待我們。如果你有好主意,就馬上開工吧:) - 使用 AutomationAtoms 實現一個純 JavaScript 的命令執行器。這將允許開發者使用 js 編寫非常輕量的測試代碼,并且可以運行在任何服瀏覽器中(當然,仍然會收到同源策略的限制)。 - 基于擴展實現一個 SafariDriver。 - 為 Node 提供本地瀏覽器支持,而不需要通過 WebDriver Server 運行。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看