最受歡迎的 5 款 Node.js 端到端測試框架

7717 字,讀完需 10 分鐘,速讀需 5 分鐘, 適合中高級前端工程師,本文對主流的 E2E 測試框架作了簡單對比,指望對你們的技術選型有幫助。

測試,尤爲是自動化測試在現代 WEB 工程中有着很是重要的角色,與交付過程集成良好的自動化測試流程能夠在新版發佈時幫你快速回歸產品功能,也能夠充當產品文檔。測試因粒度不一樣又能夠分爲單元測試、接口測試、功能測試。在 WEB 領域,功能測試亦稱爲端到端測試(End to End Test,簡稱 E2E 測試),筆者在本文中會結合自身實踐和 GitHub 趨勢對比最受歡迎的 Node.js E2E 測試解決方案,首先咱們按 GitHub 的 star 總數量排序,取前 5 名列舉以下(注意:你閱讀本文時 star 的數量可能已經不是最新的)。javascript

  • CasperJS — 6460 個 star,官網代碼,最近更新於 7 天前;
  • Protractor — 6408 個 star,官網代碼,最近更新於 10 天前;
  • Nightwatch.js — 6121 個 star,官網代碼,最近更新於 6 天前;
  • TestCafe — 2268 個 star,官網代碼,最近更新於 1 天前;
  • CodeceptJS — 1087 個 star,官網代碼,最近更新於 7 天前;

而後分別從環境搭建、測試編寫、測試報告等方面來直觀展現這 5 個 E2E 測試框架,指望可以對作測試框架選型的同窗有幫助。爲了更客觀的體現各測試框架的特色,筆者設計了一些包含 E2E 測試中經常使用操做的測試用例,分別使用不一樣的框架來編寫。E2E 測試的經常使用操做以下:css

  • 打開網頁,跳轉網頁:打開 Github 的首頁;
  • 填寫輸入框,提交表單:鍵入搜索詞,提交搜索表單;
  • 元素單擊等操做:單擊搜索結果的第一項;
  • 元素數量、屬性檢視:確認搜索結果展現了 10 條;
  • 頁面運行環境檢視:確認頁面的地址是正確的;

CasperJS

CasperJS 是 star 數最高的測試框架,也是筆者最先開始採用的 E2E 測試框架,使用 Python 編寫,雖不算是嚴格意義上的原生 Node.js 解決方案,但由於可以使用 npm 安裝,且可以很好的與 Node.js 工具鏈組合使用,筆者仍是把它列在了這裏。其特別之處在於只能與無界面瀏覽器(Headless Browser)組合使用,好比 PhantomJSSlimerJS,這也讓 CasperJS 的優點顯而易見:測試運行速度比真實瀏覽器快很多,且你不須要在持續集成系統中安裝各類瀏覽器或者某個瀏覽器的不一樣版本;潛在的坑在於,無界面瀏覽器的表現有時和真實瀏覽器不徹底相同,會帶來某些難以排查解決的瀏覽器兼容問題。html

安裝步驟

  • 安裝 Python 2.6 或更高版本
  • 安裝 PhantomJS:npm install -g phantomjs
  • 安裝 CasperJS:npm install -g casperjs

編寫測試

若是使用 ES6 以前的風格來編寫 CasperJS 測試,代碼看起來會顯得很是臃腫,而實際上 CasperJS 也不支持任何 ES6/ES7 的新語法,除非你在運行測試以前本身對代碼進行預編譯,實際代碼以下:前端

casper.test.begin('Github Search', function suite(test) {
    casper.start('https://github.com', function () {    // 打開首頁
        test.assertVisible('.js-site-search-form', 'should search input visible');
        this.fill('.js-site-search-form', { q: 'casperjs' }, true); // 鍵入搜索詞、並提交
    });

    casper.then(function () {
        test.assertEval(function() {    // 確認搜索結果是 10
            return __utils__.findAll('.repo-list-item').length >= 10;
        }, 'should show 10 results');
    });

    casper.then(function () {
        this.click('.repo-list-item h3 a'); // 點擊第1條結果
    });

    var location = null;

    casper.then(function () {   // 這裏是取環境變量
        test.assertVisible('.repository-content', 'should repo detail visible');
        location = this.evaluate(function () {
            return window.location;
        });
    });

    casper.then(function () {   // 確認目前跳轉到了 casperjs 官方倉庫
        test.assertEquals(location.pathname, '/casperjs/casperjs', 'should casperjs repo found');
    });

    casper.run(function () {
        test.done();
    });
});複製代碼

由於 CasperJS 對 CoffeeScript 有自然的支持,熟悉 CoffeeScript 的同窗能夠嘗試使用 CoffeeScript 編寫測試,或者使用這個工具轉換爲 CoffeScript。java

運行測試

casperjs test casperjs/test.js

查看報告

測試經過node

測試失敗git

Protractor

ProtractorAngular 官方正在使用的 E2E 測試框架,能夠說是專門爲 Angular 定製,內置了各類能夠選擇、操做 Angular 元素的便捷方法,若是你的應用基於 Angular 開發,使用它能夠減小不少重複代碼(顯然相似的便利在其餘框架中也有支持)。對於 Angular 的重度使用者,Protractor 會是很是明智的選擇,不一樣於 CasperJS 的是 Protractor 在真實瀏覽器中運行測試代碼。此外,Protractor 內置的頁面加載等待的功能,在 CasperJS 中須要本身設置合理的超時。相比於本文列出的其餘框架,Protractor 的明顯優點是測試用例的組織方式能夠自由使用 Jasmine 或者 Mochaangularjs

安裝步驟

  • 安裝 JDK
  • 安裝 Protractor:npm install –g protractor
  • 初始化 WebDriver Manager:webdriver-manager update
  • 建立配置文件

編寫測試

Protractor 默認開啓了等待 Angular 加載並初始化完成的功能,若是你測試的不是 Angular 應用,則須要關閉這個功能,測試代碼示例以下:github

describe('angularjs homepage todo list', function () {
    browser.ignoreSynchronization = true;   // 不啓用智能等待,由於 github 不是用 angluar 編寫的
    browser.get('https://github.com');

    it('should search input visible', function () {
        var searchInput = element(by.className('js-site-search-focus'));
        var searchForm = element(by.className('js-site-search-form'));
        expect(searchInput.isDisplayed()).toEqual(true);
        searchInput.sendKeys('protractor');
        searchForm.submit();
    });

    it('should show 10 results', function () {
        var searchList = element.all(by.className('repo-list-item'));
        expect(searchList.count()).toEqual(10);
        element(by.css('.repo-list-item h3 a')).click();
    });

    it('should repo detail visible', function () {
        var repoContent = element.all(by.className('repository-content'));
        expect(repoContent.isDisplayed()).toEqual([true]);
    });

    it('should protractor repo found', function (done) {
        browser.executeScript(function () {
            return window.location;
        }).then(function (location) {
            expect(location.pathname).toEqual('/angular/protractor');
            done();
        });
    });
});複製代碼

運行測試

  • 運行 WebDriver Manager: webdriver-manager start
  • 運行測試:protractor protractor.config.js

查看報告

測試經過web

測試失敗

Nightwatch

一樣流行的 Nightwatch,能夠認爲是 Protractor 的主要競爭對手,使用 Nigthwatch 編寫的代碼很是簡潔,可是你須要手動在測試代碼中添加合適的等待來保障測試的穩定,而 Protractor 和 TestCafe 則提供了內置的支持;Nightwatch 的主要劣勢在於繁瑣的安裝步驟,可能部分同窗看到這個安裝文檔或者下面的安裝步驟就知難而退了。

安裝步驟

編寫測試

module.exports = {
    'Github Search': function (browser) {
        browser // 打開首頁、填寫搜索詞、提交搜索表單
            .url('https://github.com')
            .assert.visible('.js-site-search-focus', 'should search input visible')
            .setValue('.js-site-search-focus', 'nightwatch')
            .submitForm('.js-site-search-form')
            .pause(1000);

        browser.execute(function () {   // 確認展現 10 條搜索結果
            return document.querySelectorAll('.repo-list-item').length;
        }, function (args) {
            browser.assert.equal(args.value, 10, 'should show 10 results');
        });

        browser.click('.repo-list-item h3 a').pause(1000);

        browser.assert.visible('.repository-content', 'should repo detail visible');

        browser.execute(function () {
            return window.location;
        }, function (args) {    // 確認打開了 nightwatch 官網
            browser.assert.equal(args.value.pathname, '/nightwatchjs/nightwatch', 'should nightwatch repo found');
        });

        browser.end();
    }
};複製代碼

運行測試

  • 運行 Selenium:java -jar selenium-server-standalone-3.0.0.jar
  • nightwatch test.js

查看報告

測試經過

測試失敗

TestCafe

TestCafe 是很是年輕但很受開發者歡迎的測試框架,由於不須要依賴 WebDriver 之類的東西,TestCafe 環境只需一鍵便可完成,這也意味着,你能夠在任何安裝了瀏覽器應用的物理設備上運行測試。TestCafe 對 ES6/ES7 語法的自然支持讓它更具前瞻性,命令行工具產生的測試報告簡潔但不失完整。因爲開源的時間較短,相比於其餘測試框架 TestCafe 的社區和生態還不夠成熟。儘管如此,不斷出現的各類 TestCafe 功能擴展也證實了它的社區和生態在不斷壯大。對於站在 WEB 技術風口浪尖的同窗,TestCafe 無疑是很是值得留意的 E2E 測試解決方案,開箱即用的特性極大的下降了使用者的成本。

安裝步驟

npm install testcafe -g複製代碼

編寫測試

TestCafe 的測試組織方式詳見這裏選擇符支持也很是強大,支持相似於 jQuery 的靈活異步的選擇符,斷言風格很是相似 Chai,下面是測試代碼:

import { Selector } from 'testcafe';

fixture `Github Search`
    .page `https://github.com`;

test('should github search work as expected', async t => {
    const searchInput = Selector('.js-site-search-focus');
    const searchList = Selector('.repo-list-item');
    const resultItem = Selector('.repo-list-item h3 a');
    const repoContent = Selector('.repository-content');

    await t.setTestSpeed(0.8);
    await t.expect(searchInput.exists).eql(true, 'should search input visible');
    await t.typeText(searchInput, 'testcafe');
    await t.pressKey('enter');

    await t.expect(searchList.count).eql(10, 'should show 10 results');
    await t.click(resultItem);

    await t.expect(repoContent.exists).eql(true, 'should repo detail visible');

    const location = await t.eval(() => window.location);
    await t.expect(location.pathname).eql('/DevExpress/testcafe', 'should testcafe repo found');
});複製代碼

運行測試

testcafe chrome testcafe/test.js複製代碼

查看報告

測試經過

測試失敗

CodeceptJs

CodeceptJs 可能並不算是嚴格意義的 E2E 測試框架,它對各類測試運行工具作了一層封裝,旨在提供更簡潔的 API,你能夠自由選擇下面這些測試運行工具:

  • WebDriverIO
  • Protractor
  • Selenium WebDriver JS
  • NightmareJS

CodeceptJs 讓筆者比較欣賞的地方在於測試用例的組織,基於 Feature 和 Scenario 兩個粒度來組織測試讓它看起來更有 E2E 測試的樣子,它支持最新的 ES6 語法,同時也屏蔽各類複雜的回調細節,全部的測試用例都是以第一人稱來作,讓測試代碼閱讀起來更像是天然語言,而讓筆者擔心的地方在於,過多的封裝可能致使出問題時排查比較困難。

安裝步驟

  • 安裝 CodeceptJs npm install -g codeceptjs
  • 用命令行工具初始化配置 codecept.json:codeceptjs init
  • 使用命令行工具生成測試:codeceptjs gt
  • 此外,你須要安裝你所選擇的底層測試工具,好比 WebDriver、Protractor

編寫測試

Feature('Github Search');

Scenario('search codecept repo', (I) => {
    I.amOnPage('https://github.com');
    I.seeElement('.js-site-search-focus');
    I.fillField('.js-site-search-focus', 'codeceptjs');
    I.pressKey('Enter');

    I.seeElement('.repo-list-item');
    I.click('.repo-list-item h3 a');
    I.seeElement('.repository-content');
    I.seeInCurrentUrl('/Codeception/CodeceptJS');
});複製代碼
複製代碼Feature('Github Search'); Scenario('search codecept repo', (I) => { I.amOnPage('https://github.com'); I.seeElement('.js-site-search-focus'); I.fillField('.js-site-search-focus', 'codeceptjs'); I.pressKey('Enter'); I.seeElement('.repo-list-item'); I.click('.repo-list-item h3 a'); I.seeElement('.repository-content'); I.seeInCurrentUrl('/Codeception/CodeceptJS'); });複製代碼

運行測試

codeceptjs run複製代碼
查看報告

測試經過

測試失敗

總結對比

本文中的全部代碼能夠在 GitHub 倉庫上看到。任何開發工具的演化都是朝着更快捷、高效的目標。本文介紹的幾個 E2E 測試框架能夠說各有所長,在作框架選型的時候該考慮哪些因子呢?這些因子的優先級如何?下面是筆者的考慮:

  • 上手簡單:P0,環境搭建步驟?出錯的機率?是否須要繁瑣的配置?TestCafe 很是簡單;
  • 文檔支持:P0,是否包含入門文檔?API 參考?開發者文檔?本文中的五款都還不錯;
  • 過程透明:P0,測試運行過程是不是透明的,可否觀察到頁面行爲?CasperJS 就像個黑盒;
  • 運行速度:P0,測試運行速度能決定你 CI 流程的好壞;
  • 測試報告:P0,是否支持多種報告?是否方便與 CI 流程集成?好比要支持 XML、JUnit 等格式輸出;
  • 調試功能:P0,出錯時提供的信息是否清晰?是否支持截圖?TestCafe 作的很好;
  • 測試組織:P1,是否能與現有的技術棧很好的組合起來?不能結合首創的方式是否直觀?若是是大型項目能夠提升優先級,Protractor 和 CodeCeptJs 佔優;
  • 代碼風格:P1,簡潔的代碼意味的更高的可讀性、更低的維護成本;TestCafe、CodeCeptJs 不錯;
  • 社區支持:P2,圍繞這個工具是否有成熟的社區?能夠用來提問、貢獻代碼;
  • 可擴展性:P3,是否支持 API 擴展?擴展成本如何?

若是你的項目中須要添加 E2E 測試,作決定的時候沒有標準答案,由於還須要結合項目自身的特色,好比規模大小、對上面各因子的要求。

備註:本文的初始版原本源於 Medium 上的文章,可是筆者在原文基礎上從新設計了測試用例,每一個測試框架的介紹也參與了筆者自身的使用經驗,框架選型上也融入了本身的思考,有興趣的能夠去看原文。

One More Thing

本文做者王仕軍,商業轉載請聯繫做者得到受權,非商業轉載請註明出處。若是對文中的內容有任何疑問,歡迎留言討論。想知道我接下來會寫些什麼?歡迎訂閱個人專欄,點擊文章下方的關注便可。

相關文章
相關標籤/搜索