<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 為什么要寫測試? Web應用程序越來越復雜,這意味著有更多的可能出錯。測試是幫助我們提高代碼質量、降低錯誤的最好方法和工具之一。 * 測試可以確保得到預期結果。 * 加快開發速度。 * 方便維護。 * 提供用法的文檔。 ## 測試的類型 ### 單元測試 單元測試(unit testing)指的是以軟件的單元為單位,對軟件進行測試。單元(unit)可以是一個函數,也可以是一個模塊或組件。它的基本特征就是,只要輸入不變,必定返回同樣的輸出。 單元測試這個詞,本身就暗示,軟件應該以模塊化結構存在。每個模塊的運作,是獨立于其他模塊的。一個軟件越容易寫單元測試,往往暗示著它的模塊化結構越好,各模塊之間的耦合就越弱;越難寫單元測試,或者每次單元測試,不得不模擬大量的外部條件,很可能暗示軟件的模塊化結構越差,模塊之間存在較強的耦合。 單元測試的要求是,每個模塊都必須有單元測試,而軟件由模塊組成。 單元測試通常采取斷言(assertion)的形式,也就是測試某個功能的返回結果,是否與預期結果一致。如果與預期不一致,就表示測試失敗。 單元測試是函數正常工作、不出錯的最基本、最有效的方法之一。 每一個單元測試發出一個特定的輸入到所要測試的函數,看看函數是否返回預期的輸出,或者采取了預期的行動。單元測試證明了所測試的代碼行為符合預期。 單元測試有助于代碼的模塊化,因此有助于長期的重用。因為有了測試,你就知道代碼是可靠的,可以按照預期運行。從這個角度說,測試可以節省開發時間。單元測試的另一個好處是,有了測試,就等于就有了代碼功能的文檔,有助于其他開發者了解代碼的意圖。 單元測試應該避免依賴性問題,比如不存取數據庫、不訪問網絡等等,而是使用工具虛擬出運行環境。這種虛擬使得測試成本最小化,不用花大力氣搭建各種測試環境。 單元測試的步驟 * 準備所有的測試條件 * 調用(觸發)所要測試的函數 * 驗證運行結果是否正確 * 還原被修改的記錄 ### 集成測試 集成測試(Integration test)指的是多個部分在一起測試,比如在一個測試數據庫上,測試數據庫連接模塊。 ### 功能測試 功能測試(Functional test)指的是,自動測試整個應用程序的某個功能,比如使用Selenium工具自動打開瀏覽器運行程序。 ## 開發模式 ### TDD TDD是“測試驅動的開發”(Test-Driven Development)的簡稱,指的是先寫好測試,然后再根據測試完成開發。使用這種開發方式,會有很高的測試覆蓋率。 TDD的開發步驟如下。 * 先寫一個測試。 * 寫出最小數量的代碼,使其能夠通過測試。 * 優化代碼。 * 重復前面三步。 TDD開發的測試覆蓋率通常在90%以上,這意味著維護代碼和新增特性會非常容易。因為測試保證了你可以信任這些代碼,修改它們不會破壞其他代碼的運行。 TDD接口提供以下四個方法。 * suite() * test() * setup() * teardown() 下面代碼是測試計數器是否加1。 ~~~ suite('Counter', function() { test('tick increases count to 1', function() { var counter = new Counter(); counter.tick(); assert.equal(counter.count, 1); }); }); ~~~ ### BDD BDD是“行為驅動的開發”(Behavior-Driven Development)的簡稱,指的是寫出優秀測試的最佳實踐的總稱。 BDD認為,不應該針對代碼的實現細節寫測試,而是要針對行為寫測試。BDD測試的是行為,即軟件應該怎樣運行。 BDD接口提供以下四個方法。 * describe() * it() * before() * after() * beforeEach() * afterEach() 下面是測試計數器是否加1的BDD寫法。 ~~~ describe('Counter', function() { it('should increase count by 1 after calling tick', function() { var counter = new Counter(); var expectedCount = counter.count + 1; counter.tick(); assert.equal(counter.count, expectedCount); }); }); ~~~ ## 斷言 斷言是判斷實際值與預期值是否相等的工具。 斷言有assert、expext、should三種風格,或者稱為三種寫法。 ~~~ // assert風格 assert.equal(event.detail.item, '(item).); // expect風格 expect(event.detail.item).to.equal('(item)'); // should風格 event.detail.item.should.equal('(item)'); ~~~ Chai.js是一個很流行的斷言庫,同時支持上面三種風格。 (1) assert風格 ~~~ var assert = require('chai').assert; var foo = 'bar'; var beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }; assert.typeOf(foo, 'string', 'foo is a string'); assert.equal(foo, 'bar', 'foo equal `bar`'); assert.lengthOf(foo, 3, 'foo`s value has a length of 3'); assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea'); ~~~ 上面代碼中,assert方法的最后一個參數是錯誤提示信息,只有測試沒有通過時,才會顯示。 (2)expect風格 ~~~ var expect = require('chai').expect; var foo = 'bar'; var beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }; expect(foo).to.be.a('string'); expect(foo).to.equal('bar'); expect(foo).to.have.length(3); expect(beverages).to.have.property('tea').with.length(3); ~~~ (3)should風格 ~~~ var should = require('chai').should(); var foo = 'bar'; var beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }; foo.should.be.a('string'); foo.should.equal('bar'); foo.should.have.length(3); beverages.should.have.property('tea').with.length(3); ~~~ ## Mocha.js Mocha是一個測試框架,也就是運行測試的工具。它使用下面的命令安裝。 ~~~ $ npm install -g mocha ~~~ Mocha自身不帶斷言庫,所以還需要安裝一個斷言庫,這里選用Chai.js。 ~~~ $ npm install -g chai ~~~ Mocha默認執行test目錄的腳本文件,所以我們將所有測試腳本放在test子目錄。 Mocha允許指定測試腳本文件,可以使用通配符,同時指定多個文件。 ~~~ $ mocha --reporter spec spec/{my,awesome}.js $ mocha --ui tdd test/unit/*.js etc ~~~ 如果希望測試非存放于test子目錄的測試用例,可以在test子目錄中新建Mocha的配置文件mocha.opts。在該文件中寫入以下內容。 ~~~ server-tests ~~~ 上面代碼指定Mocha默認測試server-tests子目錄的測試腳本。 ~~~ server-tests --recursive ~~~ 上面代碼中,--recursive參數指定同時運行子目錄中的測試用例腳本。 report參數用于指定Mocha的報告格式。 ~~~ $ mocha --reporter spec server-test/*.js ~~~ 上面代碼指定報告格式是spec。 grep參數用于搜索測試用例的名稱(即it方法的第一個參數),然后只執行匹配的測試用例。 ~~~ $ mocha --reporter spec --grep "Fnord:" server-test/*.js ~~~ 上面代碼只測試名稱中包含“Fnord:”的測試用例。 invert參數表示只運行不符合條件的測試腳本。 ~~~ $ mocha --grep auth --invert ~~~ 測試腳本中,describe方法和it方法都允許調用only方法,表示只運行某個測試套件或測試用例。 ~~~ describe("using only", function() { it.only("this is the only test to be run", function() { }); it("this is not run", function() { }); }); ~~~ 上面代碼中,只有第一個測試用例會運行。 describe方法和it方法還可以調用skip方法,表示跳過指定的測試套件或測試用例。 ~~~ describe("using only", function() { it.skip("this is the only test to be run", function() { }); it("this is not run", function() { }); }); ~~~ 上面代碼中,只有第二個測試用例會執行。 如果測試用例包含異步操作,可以done方法顯式指定測試用例的運行結束時間。 ~~~ it('logs a', function(done) { var f = function(){ console.log('logs a'); done(); }; setTimeout(f, 500); }); ~~~ 上面代碼中,正常情況下,函數f還沒有執行,Mocha就已經結束運行了。為了保證Mocha等到測試用例跑完再結束運行,可以手動調用done方法 ## WebDriver WebDriver是一個瀏覽器的自動化框架。它在各種瀏覽器的基礎上,提供一個統一接口,將接收到的指令轉為瀏覽器的原生指令,驅動瀏覽器。 WebDriver由Selenium項目演變而來。Selenium是一個測試自動化框架,它的1.0版叫做Selenium RC,通過一個代理服務器,將測試腳本轉為JavaScript腳本,注入不同的瀏覽器,再由瀏覽器執行這些腳本后返回結果。WebDriver就是Selenium 2.0,它對每個瀏覽器提供一個驅動,測試腳本通過驅動轉換為瀏覽器原生命令,在瀏覽器中執行。 ### 定制測試環境 DesiredCapabilities對象用于定制測試環境。 * 定制DesiredCapabilities對象的各個屬性 * 創建DesiredCapabilities實例 * 將DesiredCapabilities實例作為參數,新建一個WebDriver實例 ### 操作瀏覽器的方法 WebDriver提供以下方法操作瀏覽器。 close():退出或關閉當前瀏覽器窗口。 ~~~ driver.close(); ~~~ quit():關閉所有瀏覽器窗口,中止當前瀏覽器driver和session。 ~~~ driver.quit(); ~~~ getTitle():返回當前網頁的標題。 ~~~ driver.getTitle(); ~~~ getCurrentUrl():返回當前網頁的網址。 ~~~ driver.getCurrentUrl(); ~~~ getPageSource():返回當前網頁的源碼。 ~~~ // 斷言是否含有指定文本 assert(driver.getPageSource().contains("Hello World"), "預期含有文本Hello World"); ~~~ click():模擬鼠標點擊。 ~~~ // 例一 driver.findElement(By.locatorType("path")) .click(); // 例二 driver.get("https://www.google.com"); driver.findElement(By.name("q")) .sendKeys("webDriver"); driver.findElement(By.id("sblsbb")) .click(); ~~~ clear():清空文本輸入框。 ~~~ // 例一 driver.findElement(By.locatorType("path")).clear(); // 例二 driver.get("https://www.google.com"); driver.findElement(By.name("q")) .sendKeys("webDriver"); driver.findElement(By.name("q")) .clear(); driver.findElement(By.name("q")) .sendKeys("testing"); ~~~ sendKeys():在文本輸入框輸入文本。 ~~~ driver.findElement(By.locatorType("path")) .sendKeys("your text"); ~~~ submit():提交表單,或者用來模擬按下回車鍵。 ~~~ // 例一 driver.findElement(By.locatorType("path")) .submit(); // 例二 driver.get("https://www.google.com"); driver.findElement(By.name("q")) .sendKeys("webdriver"); element.submit(); ~~~ findElement():返回選中的第一個元素。 ~~~ driver.get("https://www.google.com"); driver.findElement(By.id("lst-ib")); ~~~ findElements():返回選中的所有元素(0個或多個)。 ~~~ // 例一 driver.findElement(By.id("searchbox")) .sendKeys("webdriver"); driver.findElements(By.xpath("//div[3]/ul/li")) .get(0) .click(); // 例二 driver.findElements(By.tagName("select")) .get(0) .findElements(By.tagName("option")) .get(3) .click() .get(4) .click() .get(5) .click(); // 例三:獲取頁面所有鏈接 var links = driver .get("https://www.google.com") .findElements(By.tagName("a")); var linkSize = links.size(); var linksSrc = []; console.log(linkSize); for(var i=0;i<linkSize;i++) { ? linksSrc[i] = links.get(i).getAttribute("href"); } for(int i=0;i<linkSize;i++){ ? driver.navigate().to(linksSrc[i]); ? Thread.sleep(3000); } ~~~ 可以使用`size()`,查看到底選中了多少個元素。 ### 網頁元素的定位 WebDriver提供8種定位器,用于定位網頁元素。 * By.id:HTML元素的id屬性 * By.name:HTML元素的name屬性 * By.xpath:使用XPath語法選中HTML元素 * By.cssSelector:使用CSS選擇器語法 * By.className:HTML元素的class屬性 * By.linkText:鏈接文本(只用于選中鏈接) * By.tagName:HTML元素的標簽名 * By.partialLinkText:部分鏈接文本(只用于選中鏈接) 下面是一個使用id定位器,選中網頁元素的例子。 ~~~ driver.findElement(By.id("sblsbb")).click(); ~~~ ### 網頁元素的方法 以下方法屬于網頁元素的方法,而不是webDriver實例的方法。需要注意的是,有些方法是某些元素特有的,比如只有文本框才能輸入文字。如果在網頁元素上調用不支持的方法,WebDriver不會報錯,也不會給出給出任何提示,只會靜靜地忽略。 getAttribute():返回網頁元素指定屬性的值。 ~~~ driver.get("https://www.google.com"); driver.findElement(By.xpath("//div[@id='lst-ib']")) .getAttribute("class"); ~~~ getText():返回網頁元素的內部文本。 ~~~ driver.findElement(By.locatorType("path")).getText(); ~~~ getTagName():返回指定元素的標簽名。 ~~~ driver.get("https://www.google.com"); driver.findElement(By.xpath("//div[@class='sbib_b']")) .getTagName(); ~~~ isDisplayed():返回一個布爾值,表示元素是否可見。 ~~~ driver.get("https://www.google.com"); assert(driver.findElement(By.name("q")) .isDisplayed(), '搜索框應該可選擇'); ~~~ isEnabled():返回一個布爾值,表示文本框是否可編輯。 ~~~ driver.get("https://www.google.com"); var Element = driver.findElement(By.name("q")); if (Element.isEnabled()) { ? driver.findElement(By.name("q")) .sendKeys("Selenium Essentials"); } else { ? throw new Error(); } ~~~ isSelected():返回一個布爾值,表示一個元素是否可選擇。 ~~~ driver.findElement(By.xpath("//select[@name='jump']/option[1]")) .isSelected() ~~~ getSize():返回一個網頁元素的寬度和高度。 ~~~ var dimensions=driver.findElement(By.locatorType("path")) .getSize();? dimensions.width; dimensions.height; ~~~ getLocation():返回網頁元素左上角的x坐標和y坐標。 ~~~ var point = driver.findElement(By.locatorType("path")).getLocation(); point.x; // 等同于 point.getX(); point.y; // 等同于 point.getY(); ~~~ getCssValue():返回網頁元素指定的CSS屬性的值。 ~~~ driver.get("https://www.google.com"); var element = driver.findElement(By.xpath("//div[@id='hplogo']")); console.log(element.getCssValue("font-size")); console.log(element.getCssValue("font-weight")); console.log(element.getCssValue("color")); console.log(element.getCssValue("background-size")); ~~~ ### 頁面跳轉的方法 以下方法用來跳轉到某一個頁面。 get():要求瀏覽器跳到某個網址。 ~~~ driver.get("URL"); ~~~ navigate().back():瀏覽器回退。 ~~~ driver.navigate().back(); ~~~ navigate().forward():瀏覽器前進。 ~~~ driver.navigate().forward(); ~~~ navigate().to():跳轉到瀏覽器歷史中的某個頁面。 ~~~ driver.navigate().to("URL"); ~~~ navigate().refresh():刷新當前頁面。 ~~~ driver.navigate().refresh(); // 等同于 driver.navigate() .to(driver.getCurrentUrl()); // 等同于 driver.findElement(By.locatorType("path")) .sendKeys(Keys.F5); ~~~ ### cookie的方法 getCookies():獲取cookie ~~~ driver.get("https://www.google.com"); driver.manage().getCookies(); ~~~ getCookieNamed() :返回指定名稱的cookie。 ~~~ driver.get("https://www.google.com"); console.log(driver.manage().getCookieNamed("NID")); ~~~ addCookie():將cookie加入當前頁面。 ~~~ driver.get("https://www.google.com"); driver.manage().addCookie(cookie0); ~~~ deleteCookie():刪除指定的cookie。 ~~~ driver.get("https://www.google.co.in"); driver.manage().deleteCookieNamed("NID"); ~~~ ### 瀏覽器窗口的方法 maximize():最大化瀏覽器窗口。 ~~~ var driver = new FirefoxDriver(); driver.manage().window().maximize(); ~~~ getSize():返回瀏覽器窗口、圖像、網頁元素的寬和高。 ~~~ driver.manage().window().getSize(); ~~~ getPosition():返回瀏覽器窗口左上角的x坐標和y坐標。 ~~~ console.log("Position X: " + driver.manage().window().getPosition().x); console.log("Position Y: " + driver.manage().window().getPosition().y); console.log("Position X: " + driver.manage().window().getPosition().getX()); console.log("Position Y: " + driver.manage().window().getPosition().getY()); ~~~ setSize():定制瀏覽器窗口的大小。 ~~~ var d = new Dimension(320, 480); driver.manage().window().setSize(d); driver.manage().window().setSize(new Dimension(320, 480)); ~~~ setPosition():移動瀏覽器左上角到指定位置。 ~~~ var p = new Point(200, 200); driver.manage().window().setPosition(p); driver.manage().window().setPosition(new Point(300, 150)); ~~~ getWindowHandle():返回當前瀏覽器窗口。 ~~~ var parentwindow = driver.getWindowHandle(); driver.switchTo().window(parentwindow); ~~~ getWindowHandles():返回所有瀏覽器窗口。 ~~~ var childwindows =? driver.getWindowHandles(); driver.switchTo().window(childwindow); ~~~ switchTo.window():在瀏覽器窗口之間切換。 ~~~ driver.SwitchTo().Window(childwindow); driver.close(); driver.SwitchTo().Window(parentWindow); ~~~ ### 彈出窗口 以下方法處理瀏覽器的彈出窗口。 dismiss() :關閉彈出窗口。 ~~~ var alert = driver.switchTo().alert(); alert.dismiss(); ~~~ accept():接受彈出窗口,相當于按下接受OK按鈕。 ~~~ var alert = driver.switchTo().alert(); alert.accept(); ~~~ getText():返回彈出窗口的文本值。 ~~~ var alert = driver.switchTo().alert(); alert.getText(); ~~~ sendKeys():向彈出窗口發送文本字符串。 ~~~ var alert = driver.switchTo().alert(); alert.sendKeys("Text to be passed"); ~~~ authenticateUsing():處理HTTP認證。 ~~~ var user = new UserAndPassword("USERNAME", "PASSWORD"); alert.authenticateUsing(user); ~~~ ### 鼠標和鍵盤的方法 以下方法模擬鼠標和鍵盤的動作。 * click():鼠標在當前位置點擊。 * clickAndHold():按下鼠標不放 * contextClick():右擊鼠標 * doubleClick():雙擊鼠標 * dragAndDrop():鼠標拖放到目標元素 * dragAndDropBy():鼠標拖放到目標坐標 * keyDown():按下某個鍵 * keyUp():從按下狀態釋放某個鍵 * moveByOffset():移動鼠標到另一個坐標位置 * moveToElement():移動鼠標到另一個網頁元素 * release():釋放拖拉的元素 * sendKeys():控制鍵盤輸出
                  <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>

                              哎呀哎呀视频在线观看