Angular e2e-test Protractor Jasmine

使用 Protractor 進行基本 Angular e2e Test

張家瑄 2020/02/20 20:25:08
166

端對端測試

端對端測試是指以使用者的角度,自動化對應用程式進行操作,可以視為模擬人工測試;在實務上,由於使用者可以進行的操作、操作順序非常多元,完全覆蓋是相當困難也較無效益的,因此端對端測試通常針對商業價值較高、不容許出錯的部分。

Protractor

Protractor 是 Angular 常用的測試框架,提供許多實用的 API 供我們使用 ( Protractor API ),對於端對端測試的新手相當友善;而目前在建立 Angular 專案時,ng-cli 會一併幫我們建立最基礎的 e2e 架構,只要在終端機輸入指令 npm run e2e 即可執行。
(下圖左為 e2e 初始檔案,下圖右為測試結果)

e2e folder  

Angular e2e test (GitHub)

範例專案是一個簡易的購物網站,將商品加入至右上方購物車,在點擊購物車時顯示彈窗,在確認結帳時導頁至結帳頁完成訂單 (請見: 操作)。

撰寫測試

E2e 測試通常由兩個檔案組成,目的是將搜尋 DOM 和測試邏輯分離 :

  • Page ( *.po.ts ) 視為 page object,撰寫取得頁面物件及其屬性、內容等。

  • Spec ( *.e2e-spec.ts ) 叫用對應的 Page Object,撰寫測試。

在 Page 檔中,可使用 Protractor 搜尋 DOM 中的元素並進行操作 ( 詳見 : Locators  )

import { browser, by, element, $, $$ } from 'protractor';

/** e2e\src\home\home.po.ts */
export class HomePage {
    /** 導至 Home 頁 */
    navigateTo() {
        return browser.get(browser.baseUrl) as Promise<any>;
    }
    /** 取得產品列表數量 */
    getProductCount() {
        return $$('app-shelf .card').count();

        // 下方寫法亦可
        // return element.all(by.css('app-shelf .card')).count();
    }
    /** 取得 header 購物車 */
    getCartIcon() {
        return $('app-cart-icon .shopping-cart-icon');

        // 下方寫法亦可
        // return element(by.css('app-cart-icon .shopping-cart-icon'));
    }
    /** 取得彈窗 */
    isModalDisplayed() {
        return $('modal-container').isDisplayed();
    }
    /** 取得彈窗文字 */
    getModalBodyText() {
        return $('modal-container .modal-body').getText();
    }
}

在 e2e-spec 檔中,主要由 describe 包裹一組測試 (亦稱為 suite),每一個項目測試以 it 語法包住,beforeEach、afterEach 在每一個 it 執行前後執行。下方基本範例測試 HomePage :

  • 應顯示大於 0 筆的產品

  • 點擊購物車 icon 時應彈窗顯示"購物車暫無商品!"

import { HomePage } from './home.po';

/** e2e\src\home\home.e2e-spec.ts */
describe('MyApp Home', () => {
    let page: HomePage;

    beforeEach(() => {
        page = new HomePage();
        page.navigateTo();
    });

    it('should display product list', async () => {
        expect(await page.getProductCount()).toBeGreaterThan(0);
    });

    it(`should show 'cart is empty' on cart-icon click`, async () => {
        await page.getCartIcon().click();
        expect(await page.isModalDisplayed()).toBeTruthy();
        expect(await page.getModalBodyText()).toEqual('購物車暫無商品!');
    });
});

上述 Home Page 測試執行結果 : 

Protractor configuration

在 protractor.conf.js 中,可設定 protractor 如何進行測試、如何連結 browser 等 ( 請詳見 : config );由於預設指令 ng e2e 會執行所有 *.e2e-spex.ts (設定於 specs ),執行順序會以檔案路徑字典排序。若需要執行個別測試,亦可以定義 suites,並執行指令 ng e2e --suite <suite-name> 來進行該組測試。

/**
 * @type { import("protractor").Config }
 */
exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './src/**/*.e2e-spec.ts'
  ],
  suites: {
    home: './src/home/home.e2e-spec.ts',
    purchase: ['./src/home/home.e2e-spec.ts', './src/checkout/checkout.e2e-spec.ts']
  },

...

後記

本文詳細範例請見程式庫原始碼,若有錯誤請不吝指教,謝謝。

專案版本 : 

    Angular CLI: 9.0.0-rc.4

    Node: 10.15.3

參考資料

https://www.protractortest.org/#/

https://www.protractortest.org/#/locators

https://www.protractortest.org/#/api

https://angular.io/guide/testing

張家瑄