会议讨论结构
- 代码测试用于基础组件库,类似于element
- 业务层的测试可以对部分需要长期维护的代码进行测试
VUE的脚手架本身自带单元测试功能,可以选择karma和jtest两种,本文主要是测试了两种方式的不同。在讲到前端测试的时候我们需要区分以下两种测试概念:
- e2e测试:测试一个应用从头到尾的流程是否和设计时候所想的一样。简而言之,它从一个用户的角度出发,认为整个系统都是一个黑箱,只有UI会暴露给用户。这种测试依赖于我们可以通过代理或者直接控制浏览器本身,来发起用户操作,来检验当前页面的链接,某个元素是否可用。 这个我选择了phantomJS和nightwatchJS来介绍,phantomJS本身是exe文件,不过通过nodejs包装提供了npm包,有npm插件,nightwatchJS是一个通过nodejs链接Selenium和chromedriver
- unit测试:单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。
接下来通过几个demo看看具体的实现是怎么样子的。
phantomJS
这个是提供了针对各个浏览器的API
下载软件,安装环境变量
- 截屏 获取dom元素 检测dom元素的属性
- github.com/ariya/phant…
phantomjs rasterize.js https://www.xinhehui.com "a.png
- 网络测速,网络访问,注入JS运行
phantomjs loadspeed.js https://www.xinhehui.com
var page = require('webpage').create();
page.open('http://example.com', function(status) {
console.log("Status: " + status);
if(status === "success") {
page.render('example.png');
}
phantom.exit();
});
复制代码
Nightwatch
Nightwatch是nodejs驱动的e2e测试框架,自带断言库,可以编写测试脚本
Node.js powered End-to-End testing framework
e2e测试框架,based on Node.js,Web应用E2E(End To End)测试是模拟用户进行页面操作,通过来判断页面状态的变化,从而检查功能是否运行正常的测试方法
- 并行处理
- 使用W3C WebDriver API ,之前基于Selenium API
- 基于Chai断言库
- 部署有点繁琐,需要下载selenium-server-standalone-3.8.1.jar,因为它基于selenium的,chromedriver.exe,这个是根据自己需要测试用的浏览器来选择,然后下载对应的浏览器模块
- 弄好了之后,就是挨个启动,弄个配置
require('babel-register')
var config = require('../../config')
// http://nightwatchjs.org/gettingstarted#settings-file
module.exports = {
src_folders: ['test/e2e/specs'],
output_folder: 'test/e2e/reports',
custom_assertions_path: ['test/e2e/custom-assertions'],
selenium: {
start_process: true,
server_path: require('selenium-server').path,
host: '127.0.0.1',
port: 4444,
cli_args: {
'webdriver.chrome.driver': require('chromedriver').path
}
},
test_settings: {
default: {
selenium_port: 4444,
selenium_host: 'localhost',
silent: true,
globals: {
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
}
},
chrome: {
desiredCapabilities: {
browserName: 'chrome',
javascriptEnabled: true,
acceptSslCerts: true
}
},
firefox: {
desiredCapabilities: {
browserName: 'firefox',
javascriptEnabled: true,
acceptSslCerts: true
}
}
}
}
复制代码
业务代码,
// For authoring Nightwatch tests, see
// http://nightwatchjs.org/guide#usage
//const myAssertion = require('./my_assertion')
//require('nightwatch/bin/runner.js');
module.exports = {
'测试投资页面有数据': function (browser) {
// automatically uses dev Server port from /config.index.js
// default: http://localhost:8080
// see nightwatch.conf.js
//const devServer = 'http://local.xinhehui.com:9080/#/'
const devServer = 'http://wap-test4.xinhehui.com'
browser
.url(devServer)
.waitForElementVisible('#wrap', 5000);
// 跳转到投资页面
browser.waitForElementVisible('.footerbox', 5000);
browser.assert.visible(".footerbox li:nth-child(2) p");
browser.execute(function() {
document.querySelector('.footerbox li:nth-child(2) p').click()
return true;
},[],function(res){
browser.waitForElementVisible('.productList', 5000);
// 测试投资
browser.assert.elementPresent('.productList>ul>li')
})
}
}
复制代码
这是e2e测试,相当于测试的工作了,可以直接自动化测试需求
unit单元测试
- TDD(测试驱动开发)
- BDD(行为驱动开发)
单元测试分为 TDD(测试驱动开发)和 BDD(行为驱动开发)两种类型 Jtest Mocha(发音"摩卡")诞生于2011年,是现在最流行的JavaScript测试框架之一,在浏览器和Node环境都可以使用
// TDD
suite('Array', function() {
setup(function() {
});
test('equal -1 when index beyond array length', function() {
assert.equal(-1, [1,2,3].indexOf(4));
});
});
// BDD
describe('Array', function() {
before(function() {
});
it('should return -1 when no such index', function() {
[1,2,3].indexOf(4).should.equal(-1);
});
});
复制代码
这两种不同的编码方式,这只是断言库的选择,像Jtest会针对这两种都有实现
karma
var alias = require('../../build/alias')
const vueLoaderConfig = require('../../build/vue-loader.conf')
const utils = require('../../build/utils')
var webpack = require('webpack')
var webpackConfig = {
resolve: {
alias: alias
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Less to CSS
}]
},
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}
]
},
plugins: [
new webpack.DefinePlugin({
__WEEX__: false,
'process.env': {
NODE_ENV: '"development"',
TRANSITION_DURATION: process.env.CI ? 100 : 50,
TRANSITION_BUFFER: 10
}
})
],
devtool: '#inline-source-map'
}
// shared config for all unit tests
module.exports = {
frameworks: ['jasmine'],
files: [
'./index.js'
],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
plugins: [
'karma-jasmine',
'karma-mocha-reporter',
'karma-sourcemap-loader',
'karma-webpack'
]
}
复制代码
karma是一个独立的,可以自由加载各种插件,比较有意思的可以通过配置进行实际设备的测试,如果要进行无浏览器的测试需要可以使用puppeteer 安装的东西还包括chrome-win32.exe 放置在文件夹中,指定目录
jest Javascript单元测试工具-Jest
DOM结构测试
- Fast and sandboxed
- Built-in code coverage reports
- Zero configuration (用react的话)
- babel-jest is automatically installed when installing Jest and will automatically transform files if a babel configuration exists in your project
- Snapshot 快照对比UI 实际是html代码对比
https://alexjoverm.github.io/series/Unit-Testing-Vue-js-Components-with-the-Official-Vue-Testing-Tools-and-Jest/
Puppeteer 因为karma需要需要使用浏览器组件来跑,现在的业务需要知识单纯进行单元测试,所以选择使用jest,现在karam的配置是jasmine,jtest的配置默认也是jasmine,所以不管后续是不是切换到karma,都可以直接不改测试代码
http://csbun.github.io/blog/2017/09/puppeteer/
复制代码
jtest 介绍
组件测试
https://github.com/sitepoint-editors/testing-react-with-jest/
- 功能测试; 模拟事件,比如点击,来判定传的参数是否正确;
- 状态测试;组件基于数据流,通过调用暴露的方法作用于初始props来比较state的变化;
- 快照测试;DOM不变的情况下,同样的输入会得到同样的html片段; jtest 和 karma区别
- 相同点,对于具体的测试代码无差别
- jtest 内置jsdom,jasmine2,快照测试,默认不需要webpack,直接对CSS,图片,字体等资源直接过滤处理,而karma需要安装相关的插件,需要使用webpack编译文件
实际情况 复杂的依赖 解决 加入moduleNameMapper,为什么没用webpack,官方推荐不用 请求
- Object.keys 报错 alias的变量名加上更具体的标识符,引用的组件share和corejs组件里的require(./share)冲突,
- localstorage不存在 原因 jsdom环境中不存在 解决 先给jsdom环境加上变量 再延迟加载初始化库,但是由于nodejs不方便加载es6模块,最好是重写一个文件或者利用babel编译,所以使用了setupTestFrameworkScriptFile 来处理,这个会有先后顺序
- 最后的最后
import Vue from 'vue'
process.env.NODE_ENV = 'development'
/*** 给当前的jsom 执行环境 widnow monkeypack ***/
window.localStorage = window.sessionStorage = {
getItem: function (key) {
return this[key]
},
setItem: function (key, value) {
this[key] = value
}
}
var _pluginCtrl = require('@/controllers/pluginCtrl');
var _pluginCtrl2 = _interopRequireDefault(_pluginCtrl);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
Vue.config.productionTip = false
_pluginCtrl2.default.init(Vue)
复制代码
jest api
一些API,比较有趣,在这里做下介绍 https://facebook.github.io/jest/docs/en/timer-mocks.html
- 通过mock直接替换掉require进来的模块
- https://github.com/facebook/jest/blob/master/examples/snapshot/tests/clock.react.test.js 直接替换掉执行代码中某些变量