有沒有那么一刻,看到自動(dòng)模擬用戶操作界面感覺好神奇。

關(guān)于什么叫 UI 自動(dòng)化測試就不解釋了,基本上是你剛才腦海里想到什么就是什么。
在分層自動(dòng)化測試中包括:UI 測試、集成/接口測試、單元測試。大神告訴我:UI 自動(dòng)化測試在自動(dòng)化測試中占比只有10%。先不用在乎具體這個(gè)比例是什么,我們關(guān)注的是實(shí)際價(jià)值,這個(gè)需要根據(jù)實(shí)際項(xiàng)目來判斷。不過對于UI自動(dòng)化,基本上做冒煙測試用例的自動(dòng)化就差不多了,從 UI 上來驗(yàn)證主業(yè)務(wù)流程的穩(wěn)定性,同時(shí)降低一些維護(hù)成本。
今天我們來聊聊WebdriverIO,WebdriverIO是Webdriver Node.js模塊,API非常豐富,同時(shí)支持Mobile,不過說到Webdriver那就需要先了解一下Selenuim的發(fā)展過程,這里就不裝逼了,有興趣的可以到官方網(wǎng)站瞅瞅。
WebdriverIO 有兩種使用模式,一種是 Standalone Mode,一種是 WDIO。官方其實(shí)是推薦使用 WDIO,大概幾個(gè)原因:
調(diào)試方便
多模塊并行測試
命令的執(zhí)行都是同步的,直接通過變量接收結(jié)果,不用像Standalone Mode執(zhí)行一個(gè)異步操作然后then...then...
提供配置文件,使測試參數(shù)的配置更簡單
下面開始我們的項(xiàng)目:
項(xiàng)目搭建條件:
- 安裝 JDK
- 安裝 Node.js
- 安裝 webdriverio
- 安裝 selenium-standalone
- 安裝 wdio
- 安裝 mocha,測試框架
- 安裝 chai,診斷庫
目錄結(jié)構(gòu):

package.json:
"devDependencies": {
"webdriverio": "^4.6.2", // webdriverio 庫
"selenium-standalone": "^6.2.0", // selenium standalone server、瀏覽器driver安裝
"wdio": "^0.3.3", // wdio測試運(yùn)行器
"wdio-mocha-framework": "^0.5.9", // 摩卡測試框架
"chai": "^3.5.0", // 診斷庫
"wdio-spec-reporter": "^0.1.0", // 控制臺輸出測試報(bào)告
"allure-commandline": "^1.5.0", // 根據(jù)測試結(jié)果生成測試報(bào)告
"wdio-allure-reporter": "^0.1.2" // 根據(jù)測試報(bào)告展現(xiàn)更直觀的UI界面
},
"scripts": {
"selenium": "selenium-standalone start", // 啟動(dòng)selenium
"test": ".\\node_modules\\.bin\\wdio", // 執(zhí)行test
"allure": "allure generate allure-results && allure report open" //生成測試報(bào)告
}
關(guān)于 wdio-spec-reporter、allure-commandline、wdio-allure-reporter 不一定全需要安裝。
selenium-standalone 包安裝成功后需要執(zhí)行以下命令來安裝各瀏覽器 driver,詳細(xì)說明戳這里: selenium-standalone,install 的過程中可能會(huì)遇到問題,建議翻墻試試
selenium-standalone install
安裝成功后,執(zhí)行以下命令就可以啟動(dòng) selenium-server:
selenium-standalone start
wdio 配置文件:
var config = require('./config');
var common = require('./common');
exports.config = {
// selenium-server 啟動(dòng)的IP和端口,默認(rèn)是4444
host: '127.0.0.1',
port: 4444,
// 哪些文件執(zhí)行測試
specs: [
'./modules/*.js'
],
// 哪些文件不執(zhí)行測試
exclude: [
'./modules/function.js',
'./modules/register.js',
'./modules/invite.js'
],
// 使用什么瀏覽器來執(zhí)行測試
capabilities: [{
browserName: 'chrome',
maxInstances: 1, // 最多啟動(dòng)多少個(gè)瀏覽器窗口并行執(zhí)行
chromeOptions: {
args: ['disable-extensions']
}
}],
logLevel: 'silent',
coloredLogs: true,
baseUrl: config.webUrl,
waitforTimeout: 100000, // 100s
framework: 'mocha',
reporters: ['spec', 'allure'], // 兩種測試報(bào)告方式
reporterOptions: {
allure: {
outputDir: 'allure-results' // allure測試結(jié)果上傳目錄
}
},
mochaOpts: {
ui: 'bdd',
timeout: 99999999 // 整個(gè)測試執(zhí)行的超時(shí)時(shí)間,長就對了
},
// 每次執(zhí)行測試前把之前allure保留的測試結(jié)果清空
onPrepare: function (config, capabilities) {
common.deleteFile('./allure-report');
common.deleteFile('./allure-results');
}
};
登錄測試用例:
describe('login-test', function () {
it('login', function () {
return browser
.deleteCookie() // 刪除所有cookie
.url(config.webUrl + '/login.htm') // 打開登錄頁面
.setValue('#txtMobilePhone', config.loginInfo.mobilePhone) // 設(shè)置手機(jī)號
.setValue('#txtPassword', config.loginInfo.password) // 設(shè)置密碼
.click('#btnLogin') // 點(diǎn)擊登錄按鈕
.waitForExist('#topBarContent', config.waitMS); // 如果這樣元素存在代表成功
});
});
方法注冊與調(diào)用說明:
// 可以通過 browser.checkInviteSuccess()調(diào)用
browser.addCommand('checkInviteSuccess', function (inboxType) {
$('.sessionList .sessionItem[id="' + inboxType + '"]').click();
browser.waitForExist('.messageItem', config.waitMS);
var result = browser
.execute(function () {
var text = null;
$('.inboxBox .messageItem .textMsg').each(function () {
text += $(this).text();
});
return text;
});
// 斷言正則表達(dá)式方法
assert.match(result.value, /已經(jīng)成為好友|成功加入|已經(jīng)申請|成功申請/, '判斷收到的消息是否包含指定的內(nèi)容');
});
執(zhí)行測試:
控制臺A
npm run selenium //啟動(dòng)selenium-server
控制臺B
npm run test //執(zhí)行test
生成測試報(bào)告:
npm run allure

總結(jié):
WebdriverIO 的命令上面提到的只是很小一部分,有興趣趕快玩起來;
describe、it 都是 Mocha 內(nèi)提供的方法,單條用例的調(diào)試可以使用 it.only,單個(gè) describe 可以 describe.only,關(guān)于 Mocha 介紹戳這里 Mocha;
Chai 提供 BDD(行為驅(qū)動(dòng)開發(fā)) 斷言風(fēng)格和 TDD(測試驅(qū)動(dòng)開發(fā)) 斷言風(fēng)格,關(guān)于 Chai 介紹戳這里 Chai;
有時(shí)候不用非要斷言來驗(yàn)證用例是否正確執(zhí)行,像上面的登錄的用例中,waitForExist 的元素是登錄成功后才可以看見,所以這樣也是可以代表成功的;