使用Selenium
操作headless chrome 推薦
簡(jiǎn)介
WebDriver
是一個(gè)W3C標(biāo)準(zhǔn), 定義了一套檢查和控制用戶代理(比如瀏覽器)的遠(yuǎn)程控制接口,各大主流瀏覽器來實(shí)現(xiàn)這些接口以便調(diào)用控制接口來操作瀏覽器。
Selenium
是一整套的Web自動(dòng)化測(cè)試解決方案罗售,配合WebDrive規(guī)范宠页,實(shí)現(xiàn)了對(duì)各種用戶代理的適配(比如瀏覽器,PhantomJS等)贾虽,通過操作瀏覽器的WebDriver
接口來實(shí)現(xiàn)帶瀏覽器的Web自動(dòng)化杆怕。
使用selenium-webdriver
-
selenium
相關(guān)的API文檔 -
selenium-webdriver
的JavaScriptAPI文檔
const webdriver = require('selenium-webdriver'),
By = webdriver.By;
const driver = new webdriver.Builder()
.forBrowser('chrome')
.build();
driver.get('https://www.baidu.com').then((args) => {
// 獲取百度搜索按鈕的 文本
driver.findElement(By.id('su')).then((element) => {
return element.getAttribute('value')
}).then((btnName) => {
console.log(btnName)
});
// 獲取百度首頁 title
driver.getTitle().then((title) => {
console.log(title);
});
});
driver.quit();
使用browserstack-webdriver
只是獲取driver的方式不一樣糠溜,其他調(diào)用完全一樣
const webdriver = require('browserstack-webdriver'),
By = webdriver.By;
// Input capabilities
const capabilities = {
'browserName' : 'firefox',
'browserstack.user' : BROWSERSTACK_USERNAME,
'browserstack.key' : BROWSERSTACK_KEY
}
const driver = new webdriver.Builder().
usingServer('http://hub.browserstack.com/wd/hub').
withCapabilities(capabilities).
build();
driver.get('https://www.baidu.com').then((args) => {
// 獲取百度搜索按鈕的 文本
driver.findElement(By.id('su')).then((element) => {
return element.getAttribute('value')
}).then((btnName) => {
console.log(btnName)
});
// 獲取百度首頁 title
driver.getTitle().then((title) => {
console.log(title);
});
});
driver.quit();
使用 chromedriver
chromedriver
是一個(gè)編碼輔助笤虫,自動(dòng)配置環(huán)境變量旁瘫,不需要手動(dòng)下載和配置環(huán)境變量,通過安裝chromedriver
同時(shí)在代碼中引入
require('chromedriver')
更換獲取源的URL(使用如下任意一種就行)
-
安裝過程添加參數(shù)琼蚯,默認(rèn)下載地址為
http://chromedriver.storage.googleapis.com
npm install chromedriver --chromedriver_cdnurl=https://npm.taobao.org/mirrors/chromedriver
添加如下內(nèi)容到
.npmrc
文件
chromedriver_cdnurl=https://npm.taobao.org/mirrors/chromedriver
- 添加環(huán)境變量
CHROMEDRIVER_CDNURL
CHROMEDRIVER_CDNURL=https://npm.taobao.org/mirrors/chromedriver npm install chromedriver
更換安裝的chromedriver
文件路徑
- 安裝過程使用配置參數(shù)
npm install chromedriver --chromedriver_filepath=/path/to/chromedriver_mac64.zip
- 添加如下內(nèi)容到
.npmrc
文件
chromedriver_filepath=/path/to/chromedriver_mac64.zip
- 添加環(huán)境變量
CHROMEDRIVER_FILEPATH=/path/to/chromedriver_mac64.zip
使用mocha + chai
簡(jiǎn)介
mocha
是一個(gè)可以運(yùn)行在瀏覽器端和NodeJS環(huán)境的JavaScript測(cè)試框架酬凳,區(qū)別于類庫,框架定義好了流程凌停,并調(diào)用你的代碼粱年。
chai
是一個(gè)斷言庫,判斷結(jié)果是否符合預(yù)期罚拟。
實(shí)例代碼
const chai = require('chai');
const chromeDriver = require('selenium-webdriver/chrome')
const webdriver = require('selenium-webdriver'),
By = webdriver.By;
const driver = new webdriver.Builder()
.forBrowser('chrome')
.setChromeOptions(new chromeDriver.Options().addArguments(['headless']))
.build();
describe('首頁加載測(cè)試',function(){
// 獲取百度搜索按鈕的 文本
describe('按鈕文本',function(){
it('按鈕文本必須等于',function(done){
driver.get('https://www.baidu.com').then(function(){
driver.findElement(By.id('su')).then((element) => {
return element.getAttribute('value')
}).then((btnName) => {
console.log(btnName);
chai.expect(btnName).to.equal('百度一下');
done();
});
});
})
});
// 獲取百度首頁 title
describe('首頁標(biāo)題',function(){
it('首頁標(biāo)題應(yīng)該為',function(done){
driver.get('https://www.baidu.com').then(function(){
driver.getTitle().then((title) => {
console.log(title);
chai.expect(title).to.equal('百度一下台诗,你就知道');
done();
});
});
});
});
after(function(){
driver.quit();
})
});
使用Karma + mocha + chai
簡(jiǎn)介
Karma
是一個(gè)用JavaScript實(shí)現(xiàn)的測(cè)試執(zhí)行器,實(shí)現(xiàn)了如下內(nèi)容
- 對(duì)各種常見框架赐俗、庫的適配參考
- 各種常見代碼預(yù)處理或轉(zhuǎn)譯參考
- 各種執(zhí)行的測(cè)試報(bào)告方案參考
- 各種瀏覽器或類瀏覽器的適配參考
- 各種編輯器的適配拉队,內(nèi)容變更,立即重新執(zhí)行
- 覆蓋率統(tǒng)計(jì)
安裝相應(yīng)的依賴庫
npm i --save-dev karma karma-chrome-launcher karma-mocha karma-chai
npm i --save-dev mocha chai
生成配置文件
在工程目錄下執(zhí)行如下命令
./node_modules/.bin/karma init
一路按照提示操作即可阻逮,生成的配置文件在工程目錄下karma.conf.js
粱快,內(nèi)容大致如下:
// Karma configuration
// Generated on Mon Jul 10 2017 19:49:48 GMT+0800 (CST)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
// list of files / patterns to load in the browser
files: [
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
調(diào)整配置支持headless chrome
可以到這里,查看chrome相關(guān)的karma-launcher,有ChromeHeadless
和ChromeCanaryHeadless
這兩個(gè)headless驅(qū)動(dòng)可以選擇叔扼。
調(diào)整配置支持ES6事哭,添加webpack
npm i webpack karma-webpack babel-core babel-loader babel-preset-es2015
調(diào)整配置增加測(cè)試覆蓋度
npm i babel-plugin-istanbul
最終的到的Karma配置文件
karma.conf.js
// Karma configuration
// Generated on Mon Jul 10 2017 19:49:48 GMT+0800 (CST)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha','chai'],
// list of files / patterns to load in the browser
files: [
'test/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/**/*.js': ['webpack']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],
coverageReporter: {
type: 'html',
dir: 'coverage/'
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['ChromeHeadless'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
webpack: {
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015'],
plugins: ['istanbul']
}
}]
}
}
})
}
編寫代碼
src/index.js
const isType = (data, type) => {
return ['[object ', type, ']'].join('') === Object.prototype.toString.call(data)
};
const isFunction = (data) => {
return isType(data, 'Function')
};
const isArray = (data) => {
return isType(data, 'Array')
};
module.exports = {
isType,
isFunction,
isArray
}
編寫測(cè)試用例
test/index.js
const typeUtil = require('../src/index')
describe('index.js: ', () => {
it('isFunction() should work fine.', () => {
expect(typeUtil.isFunction(function(){})).to.equal(true)
expect(typeUtil.isFunction(Object.prototype.toString)).to.equal(true)
});
it('isArray() should work file.', () => {
expect(typeUtil.isArray([])).to.equal(true)
expect(typeUtil.isArray({})).to.equal(false)
})
});
運(yùn)行測(cè)試
- 在當(dāng)前目錄下運(yùn)行
./node_modules/.bin/karma start
- 或者添加如下代碼到
package.json
"scripts": {
"test": "karma start"
}
? 然后運(yùn)行npm run test
查看結(jié)果
- 命令行能看到運(yùn)行結(jié)果
- 在工程目錄下的
coverage
目錄能看到相應(yīng)的覆蓋率報(bào)告
存在的問題
Karma是將測(cè)試Case在瀏覽器中運(yùn)行并查看結(jié)果,當(dāng)頁面的url 改變的時(shí)候瓜富,會(huì)影響到整個(gè)Karma的執(zhí)行鳍咱,會(huì)有類似Some of your tests did a full page reload!
這樣的提示。上面打開百度首頁檢查按鈕和title的例子在Karma中還沒有找到合適的方式寫出來与柑。