用bdd的方式來寫e2e ui自動測試(cucumber.js+protractor)
前言
其實bdd真的是一種很好的測試模式,尤其是在ui測試上,更是適合用寫規格的方式來做自動測試,有些表單式複雜的互動,光是一個頁面測試案例可能有好幾十種,如果我們可以把這種邏輯互動,經由自動測試保護,就可以節省我們之後手動測試時間,不管是避免忘記測試案例,或者是交給別的member維護,或者是要重構程式碼,用bdd的方式都會非常有幫助,但是angular預設並不是使用cucumber,而是使用jasmine的方式,所以我們必須改一些cli的配置,來符合我們使用cucumber的需求。
導覽
安裝用到的package和修改cli的配置
首先就是從npm安裝一下相關需要用到的package了,請在cmd打上如下的指令,安裝必要的package
npm i @types/chai @types/chai-as-promised chai chai-as-promised cucumber cucumber-tsflow protractor-cucumber-framework --D
接著我們需要修改protractor.con.js的一些設定,把原本jasmine改成cucmber,示例如下
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
exports.config = {
allScriptsTimeout: 5000,
specs: [
'./e2e/features/*.feature' //這邊對應了我們在e2e所有的feature檔
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'custom', // set to "custom" instead of cucumber.
frameworkPath: require.resolve('protractor-cucumber-framework'), //這邊則是我們從npm下載的package
cucumberOpts: {
require: ['./e2e/features/*.ts'], //這邊則對應了我們寫的ts測試檔
tags: [], // <string[]> (expression) only execute the features or scenarios with tags matching the expression
strict: true, // <boolean> fail if there are any undefined or pending steps
format: ["pretty"], // <string[]> (type[:path]) specify the output format, optionally supply PATH to redirect formatter output (repeatable)
dryRun: false, // <boolean> invoke formatters without executing steps
compiler: [] // <string[]> ("extension:module") require files with the given EXTENSION after requiring MODULE (repeatable)
},
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
},
onPrepare() {
browser.manage().window().maximize();
}
};
新增e2e的feature並執行測試
接著在e2e的資料夾裡面,新增一個features的資料夾,然後我習慣性的是把要測試的feature和ts是放在同一層底下,比如我新增了test.feature和test.steps.ts,資料夾結構如下圖
其實cucumber.js的文法結構跟specflow都是一樣的,只是specflow是.net版的cucumber,那先看一下我要測試的案例
Feature: This is a demo feature
Scenario Outline: The user go to the sport and seach some value to filter display rows
Given I open the browser
When I focus on txtSearch key the '<searchValue>'
And I click search button
Then The rows is '<result>'
Examples:
| searchValue | result |
| abc | 0 |
| Ba | 4 |
| | 10 |
因為我們已經是寫ts,所以我們的寫法跟原本的js寫法就不太一樣了,但是跟c#的寫法還挺像的
import { before, after } from 'cucumber-tsflow/dist';
import { browser, by, element } from 'protractor/built';
import { binding, given, when, then } from 'cucumber-tsflow';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
const expect = chai.use(chaiAsPromised).expect;
@binding()
class TestSteps {
txtSearch = element(by.id('searchName'));
searchButton = element(by.id('searchButton'));
trSports = element.all(by.id('trSports'));
@before()
private beforeDo() {
// test before do something
}
@after()
private afterDo() {
//test after do something
}
@given(/^I open the browser$/)
private givenIOpenTheBrowser(callback) {
browser.get('/');
callback();
};
@when(/^I focus on txtSearch key the '(.*)'$/)
private whenFocusOnTxtSearchKeyThen(text, callback) {
this.txtSearch.sendKeys(text);
callback();
}
@when(/^I click search button$/)
private whenClickSearchButton(callback) {
this.searchButton.click();
callback();
}
@then(/^The rows is '(.+)'$/)
private thenAssertTitle(text, callback) {
expect(this.trSports.count()).to.eventually.equal(+text).and.notify(callback);
}
}
export = TestSteps;
最後我們只要在command line執行ng e2e就會跑起我們所有的測試了,測試結果如下
cucumber在vs code的extension
因為feature檔預設是沒有辦法格式化的,所以只好用手動排版的方式,這讓我感到蠻苦惱的,後來讓我找到了兩個vs code的extension,可以幫助我們自動format feature檔,還有intellisense和highlight的功能,分別是Cucumber Full Language Support和Table Formatter
cucumber這個工具可以format我們的step的說明,而table format就是example下的表格部份,底下是示例
結論
用人話來描述ui的測試,確實是再適合不過了,也能很大幅度的提升我們開發的品質,希望對需要的人有幫助,有任何更好的想法,也可以再提供給筆者囉