使用前端技術對後端做驗收測試

驗收測試是以使用者角度對網站做測試,屬於黑箱測試,既然是黑箱測試,原本使用 PHP/Laravel 所開發的網站,就不一定要使用 PHP/Laravel 後端技術來做驗收測試,也可以使用前端的技術來做;透過 Angular CLI,我們可使用 TypeScript + Protractor + Jasmine + Webpack 對 PHP/Laravel 做驗收測試。

Version


PHP 7.0.15
Laravel 5.4.27
Angular CLI 1.1.2
Angular 4.2.3
TypeScript 2.3.3
Protractor 5.1.2
Jasmine 2.6.2

建立 Laravel 專案


1
$ composer create-project laravel/laravel Laravel54 --prefer-dist

使用 Composer 建立 Laravel 專案。

執行 Laravel


laravel000

執行 php artisan serve 啟動內建的 PHP web server,預設執行在 http://127.0.0.1:8000

laravel001

http://127.0.0.1:8000,我們看到了首頁有斗大的 Laravel

安裝 Angular CLI


我們即將使用 Protractor 對 Laravel 做驗收測試,在 Angular CLI 中,已經將 TypeScript + Protractor + Jasmine + Webpack 都整合好了,因此我們要安裝 Angular CLI,由 Angular CLI 建立 Angular 專案後,再修改專案內的 e2e 目錄的測試程式,由 Protractor 對 Laravel 做驗收測試。

安裝 Node.js

(略)

1
$ npm install -g @angular/cli

由 NPM 安裝 Angular CLI。

  • -g : 表 global,將 Angular CLI 安裝在系統全域環境,整個 macOS 都能用。

建立 Angular 專案


1
$ ng new NG4Protractor

使用 Angular CLI 建立 Angular 專案。

修改 Page Object


e2e/app.po.ts

1
2
3
4
5
6
7
8
9
10
11
12
import { browser, by, element } from 'protractor';

export class NG4ProtractorPage {
navigateTo() {
browser.waitForAngularEnabled(false);
return browser.get('http://127.0.0.1:8000/');
}

getParagraphText() {
return element(by.className('title m-b-md')).getText();
}
}

app.po.ts 為 page object,目的讓我們的驗收測試不用直接面對容易變動的 HTML 與 CSS,若將來 HTML 與 CSS 有任何修改,只要統一的修改 app.po.ts 檔案即可,不用修改驗收測試。

第 4 行

1
2
3
4
navigateTo() {
browser.waitForAngularEnabled(false);
return browser.get('http://127.0.0.1:8000/');
}

Angular 的 Protractor,預設會判斷網頁是否由 Angular 開發,但目前我們要測的不是 Angular,而是 Laravel,因此必須加上 browser.waitForAngularEnabled(false),避免測試失敗。

由於 Laravel 預設的網址為 http://127.0.0.1:8000/,因此在 browser.get() 加上網址。

第 9 行

1
2
3
 getParagraphText() {
return element(by.className('title m-b-md')).getText();
}

我們想要測試的首頁是否有 Laravel

laravel002

根據 welcome.blade.php,我們發現 Laravel<div> 的 CSS class 是 title m-b-md,因此使用 Protractor 的 by.className('title m-b-md') 抓到該 element,再由 getText() 抓到 Laravel

修改驗收測試


e2e/app.e2e-spec.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { NG4ProtractorPage } from './app.po';

describe('ng4-protractor App', () => {
let page: NG4ProtractorPage;

beforeEach(() => {
page = new NG4ProtractorPage();
});

it('should display Laravel', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Laravel');
});
});

app.e2e-spec.ts 才是真正的驗收測試,如同使用 Jasmine 寫單元測試一樣。

第 6 行

1
2
3
beforeEach(() => {
page = new NG4ProtractorPage();
});

在每個驗收測試執行之前,先建立 page object 物件。

第 10 行

1
2
3
4
it('should display Laravel', () => {
page.navigateTo();
expect(page.getParagraphText()).toEqual('Laravel');
});

測試案例,想要測試是否在首頁看到 Laravel ,使用 page object 的 getParagraphText() 抓到值,再由 expect().toEqual('Laravel') 判斷是否為 Laravel

執行驗收測試


1
$ ng e2e --serve=false

預設 ng e2e 會重新編譯整個 Angular,但目前我們並沒有寫 Angular,只是想藉由 Angular CLI 的 Protractor 環境測試 Laravel 而已,因此要加上 —serve=false,則 Angular CLI 將只會編譯 Protractor 部分的驗收測試而已,速度會快很多。

laravel003

綠燈 通過 Protractor 驗收測試。

若在公司的 proxy 內,Protractor 將無法正常執行,必須自行設定 NPM proxy。

1
2
$ npm config -g set proxy http://xxx.xxx.xxx.xxx.xxx:80
$ npm config -g set https-proxy http://xxx.xxx.xxx.xxx.xxx:80

Conclusion


  • Protractor 原本是 Google 為 Angular 量身定做的 E2E testing framework,專門用來測試 Angular 所開發的網站,但也能用來測試任何以後端為主的網站,不侷限於 Laravel。
  • 藉由 Angular CLI 所建立的 Angular 專案,我們將不用再手動整理 TypeScript + Protractor + Jasmine + Webpack 環境,Angular CLI 已經幫我們搞定了。
  • 若將來想將 MVC 專案重構成前後端分離的專案,可藉由此方式先將 MVC 的驗收測試先用 Protractor 寫好,然後重構 MVC 專案,達到商業邏輯與後端 framework 解耦合後,將來再將後端的商業邏輯移植到前後端分離的後端 framework,下一步再使用 Angular 接後端 API,最後再使用同一份 Protractor 驗收測試來測試 Angular,由於驗收測試是同一份,更能確保從 MVC 重構成前後端分離後,功能是否完全正常。

Sample Code


完整的範例可以在我的 GitHub 上找到

Reference


Cory Rylan, Introduction to E2E Testing with the Angular CLI and Protractor