現代化測試開發技巧
劉艾霖 (Alin)
2017 Testing Day
@alincode
- 創科資訊
- 技術顧問 / 企業內訓講師
- 講者
- Modern Web 2016
- JSDC.tw 2016
- 全端開發者 & 測試開發
1. 選擇框架
2. Tips
3. 快速入門 & demo
選擇前端測試框架
為什麼我們要採用
前端測試框架?
begin...
Selenium IDE
const {Builder, By, until} = require('webdriver');
var driver = new Builder()
.forBrowser('firefox')
.build();
driver.get('http://www.google.com/ncr')
.then(_ => driver.findElement(By.name('q')).sendKeys('webdriver'))
.then(_ => driver.findElement(By.name('btnG')).click())
.then(_ => driver.wait(until.titleIs('webdriver - Google Search'), 1000))
.then(_ => driver.quit());
Webdriver
但這些都還不夠...
蛤
你說啥...
這樣還不夠...
產出測試報表
與持續整合流程結合
儘可能地減輕寫測試程式的負擔
友善的測試結果訊息
.......
.....
...
支線目標
產出測試報報表
與持續整合流程結合
儘可能地減輕寫測試程式的負擔
Webdriver.IO
driver.get('http://www.google.com');
driver.findElement(webdriver.By.id('q')).sendKeys('webdriver');
driver.findElement(webdriver.By.id('btnG')).click();
client.url('http://google.com')
.setValue('#q', 'webdriver')
.click('#btnG')
Webdriver
注意力放在測試邏輯
而不是實作細節
友善的測試結果訊息
選用測試框架
分辨
測試框架的用途
特性
describe('Protractor Demo App', function() {
it('should add one and two', function() {
browser.get('http://juliemr.github.io/protractor-demo/');
element(by.model('first')).sendKeys(1);
element(by.model('second')).sendKeys(2);
element(by.id('gobutton')).click();
expect(element(by.binding('latest')).getText()).
toEqual('5'); // This is wrong!
});
});
const assert = require('assert');
describe('angularjs', () => {
it('should add one and two ', () => {
browser.url('http://juliemr.github.io/protractor-demo/');
$('[ng-model=first]').setValue(1);
$('[ng-model=second]').setValue(2);
$('#gobutton').click();
browser.pause(7000);
assert.equal($('.ng-binding').getText(), 3);
});
});
WebdriverIO
framework agnostic
整合度
是不是可以一魚多吃
擴充度
命令
報表
格式
外掛
服務
實務上的 Tips
用 ReactJS, AngularJS 寫的網站
可不可以測?
Sure
常常遇到拋出 element
不存在的 error?
多用 waitFor
少用 browser.pause(3000)
測試程式
越來越難維護
Pattern 無所不在
所以...
class Page {
constructor() {
this.title = 'My Page';
}
open(path) {
browser.url('/' + path);
}
}
module.exports = new Page();
var Page = require('./page')
class LoginPage extends Page {
get username() { return browser.element('#username'); }
get password() { return browser.element('#password'); }
get form() { return browser.element('#login'); }
get flash() { return browser.element('#flash'); }
open() { super.open('login'); }
submit() { this.form.submitForm(); }
}
module.exports = new LoginPage();
page.js
loginPage.js
Page Object Pattern
ES6
var expect = require('chai').expect;
var LoginPage = require('../pageobjects/login.page');
describe('login form', function () {
it('登入失敗流程', function () {
LoginPage.open();
LoginPage.username.setValue('alincodeeeeee');
LoginPage.password.setValue('hello');
LoginPage.submit();
expect(LoginPage.flash.getText()).to.contain('這個帳號不存在');
});
it('登入成功流程', function () {
LoginPage.open();
LoginPage.username.setValue('alincode');
LoginPage.password.setValue('hello');
LoginPage.submit();
expect(LoginPage.flash.getText()).to.contain('你登入成功');
});
});
LoginPage.open();
LoginPage.username.setValue('alincode');
LoginPage.password.setValue('hello');
LoginPage.submit();
測試環境好難架設
Selenium Server
Browser Version
Browser Driver
Selenium Hub & Node
Cloud Browser
30 美金
錢能解決的都不是問題
可是瑞凡...
我就是沒有錢
docker-selenium
Selenium node
Selenium Grid Hub
Selenium standalone
VNC server
可是... 可是... 可是...
測試好難寫啊...
REPL
可是... 可是... 可是...
寫測試好花時間啊...
你聽過安麗嗎
你聽過 hot reload 嗎
要怎麼與 CI / CD
流程整合
快速入門前端測試
Live Demo
cloud service
總結
寫測試其實沒這麼難
現在已經 2017 了
如果驗收後
不補個前端測試
你就會發現...
某天你的客戶問你...
或許當時就是時空背景下
定義詭異的流程
他實際上並不是一個 bug
而是一個需求啊...
因為時間有限...
還想知道更多...
現代化測試開發技巧
By alincode
現代化測試開發技巧
- 2,694