一、使用Karma做自动化测试
1、Karma([ˈkɑrmə] 卡玛)是一个测试运行器,它可以呼起浏览器(打开浏览器),加载测试脚本,然后运行测试用例;
Mocha([ˈmoʊkə] 摩卡)是一个单元测试框架/库,它可以用来写测试用例;
Sinon(西农)是一个 spy / stub / mock 库,用以辅助测试(使用后才能理解);
以上这些都是工具,只要会使用即可;
2、步骤
①安装各种工具,npm i -D karma karma-chrome-launcher karma-mocha karma-sinon-chai mocha sinon sinon-chai karma-chai karma-chai-spies
②创建 karma 配置,新建 karma.conf.js
// karma.conf.js
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', 'sinon-chai'],
client: {
chai: {
includeStack: true
}
},
// list of files / patterns to load in the browser
files: [
'dist/**/*.test.js',
'dist/**/*.test.css'
],
// list of files / patterns 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: ['ChromeHeadless'],
// 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
})
}
③创建 test/button.test.js 文件
const expect = chai.expect;
import Vue from 'vue'
import Button from '../src/button'
Vue.config.productionTip = false
Vue.config.devtools = false
describe('Button', () => {
it('存在.', () => {
expect(Button).to.be.ok
})
it('可以设置icon.', () => {
const Constructor = Vue.extend(Button)
const vm = new Constructor({
propsData: {
icon: 'settings'
}
}).$mount()
const useElement = vm.$el.querySelector('use')
expect(useElement.getAttribute('xlink:href')).to.equal('#i-settings')
vm.$destroy()
})
it('可以设置loading.', () => {
const Constructor = Vue.extend(Button)
const vm = new Constructor({
propsData: {
icon: 'settings',
loading: true
}
}).$mount()
const useElements = vm.$el.querySelectorAll('use')
expect(useElements.length).to.equal(1)
expect(useElements[0].getAttribute('xlink:href')).to.equal('#i-loading')
vm.$destroy()
})
it('icon 默认的 order 是 1', () => {
const div = document.createElement('div')
document.body.appendChild(div)
const Constructor = Vue.extend(Button)
const vm = new Constructor({
propsData: {
icon: 'settings',
}
}).$mount(div)
const icon = vm.$el.querySelector('svg')
expect(getComputedStyle(icon).order).to.eq('1')
vm.$el.remove()
vm.$destroy()
})
it('设置 iconPosition 可以改变 order', () => {
const div = document.createElement('div')
document.body.appendChild(div)
const Constructor = Vue.extend(Button)
const vm = new Constructor({
propsData: {
icon: 'settings',
iconPosition: 'right'
}
}).$mount(div)
const icon = vm.$el.querySelector('svg')
expect(getComputedStyle(icon).order).to.eq('2')
vm.$el.remove()
vm.$destroy()
})
it('点击 button 触发 click 事件', () => {
const Constructor = Vue.extend(Button)
const vm = new Constructor({
propsData: {
icon: 'settings',
}
}).$mount()
const callback = sinon.fake();
vm.$on('click', callback)
vm.$el.click()
expect(callback).to.have.been.called
})
})
④创建测试脚本,在 package.json 里面找到 scripts 并改写 scripts;
"scripts": {
"dev-test": "parcel watch test/* --no-cache & karma start",
"test": "parcel build test/* --no-minify && karma start --single-run"
},
⑤运行npm run test
,报错了,那是因为你每次运行时没有清除缓存,需要改一下package.json的scripts,加上--no-cache,"test": "parcel build test/* --no-cache --no-minify && karma start --single-run"
( --no-minify是不要压缩),还有一个原因是需要在button.vue中引入一下icon组件才可以,之后再运行npm run test就成功了
npm run test
整个步骤就是先用parcel打包button.vue,然后再用Karma打开浏览器进行测试,测试完毕后关闭浏览器;
⑥karma.conf.js中
3、测试用例怎么写?
describe
和it
,它是BDD(行为驱动开发);
describe
和it
是属于Mocha,这个不用引入,它会自动引入;具体的断言expect
是由chai.js引入的,chai.js是需要安装引入的;
describe('要测得组件',()=>{
it('此次测试的名字', ()=>{
expect(xx).to.equal(yyy) // expect(xx).to.eq(yyy) equal可写成eq
})
})
二、持续集成(travis ci )
1、根目录下创建“.travis.yml”文件
language: node_js
node_js:
- "8"
addons:
chrome: stable
sudo: required
before_script:
- "sudo chown root /opt/google/chrome/chrome-sandbox"
- "sudo chmod 4755 /opt/google/chrome/chrome-sandbox"
2、打开https://www.travis-ci.org/,使用GitHub登录;添加项目后返回首页,每次push后travis会自动去检测,每当检测结果状态发生变化时,它会发邮件通知你;
可以参考阮一峰这篇文章;
三、用npm发布自己的包
0、首先确保你的代码通过了测试;
1、更改package.json里的版本号为“0.0.1”(一般还未正式发布的包版本号都为0.0.x);
2、创建 index.js,在 index.js 里将你想要导出的内容全部导出;
3、去https://www.npmjs.com/注册一个账户;
4、注册完一定要去邮箱里确认一下!!!!
5、在 gulu 项目根目录运行 npm adduser;
①你需要注意的是npm adduser必须要更换为 npm 官方源;
6、运行 npm publish;
7、别忘了把淘宝源改回来!!!
四、下载安装使用自己的包来检查还有哪些错误
1、首先你要自己预测用户会怎样使用你的包
①使用vue-cli;
②使用webpack;
③使用parcel;
2、这里我们以vue-cli为例来运行走一遍(实际中应该每种方式都运行一遍)
①根据文档使用vue-cli创建一个文件(需要注意的是如果一开始用npm安装,就自始至终都用npm,不要一会npm一会yarn,会出错的)
②创建好,我们就开始安装我们的轮子npm i darkti-gulu
(darkti-gulu,就是package.json里的name)
③在main.js中引用我们的轮子,发现有报错Failed to resolve loader: sass-loader
,原因就是我们在写轮子的时候直接用的import和export,node目前不支持import,不应该直接把import暴露给用户,我们需要把它转换成用户那边能看懂的语法,用babel把import变成可执行的js,那么有两种选择:
a. 一是你让用户自己使用babel去转译
b. 二是你转译好了,让用户直接去用
-
npx parcel build index.js --no-minify
(本来不应该加 --no-minify 的,奈何不加会有 bug,HTML 压缩把 slot 标签全删了) - 将 package.json 的 main 改为 dist/index.js
- 还要把版本号改一下,npm不允许发布相同的版本号,然后push一下,push完了就
npm publish
发布一下(注意啦!!!发布的时候要把npm源改一下,不能是淘宝的源,发布完成后再把源改回来) -
发布完成后,再npm装一下,如果一直装不上最新的,直接指定版本号来装
3、引用进去你发现按钮没有样式!!!这里就只能让用户先把css自己引进去,后面再进行优化
import 'darkti-gulu/dist/index.css'
五、使用npm link
来快速运行自己的轮子
1、为了不要上传发布再下载这一系列繁琐的步骤,所以使用npm link
来快速在自己的机子上模拟用户操作自己的包;
2、你改动了轮子后,先npx parcel build index.js --no-cache --no-minify
打一下包,只需要第一次npm link
一下,成功后,在用户测试的目录下npm link darkti-gulu
,你就得到了最新版的包了;
3、之后每次更新过轮子后,只需打一下包,在用户包那边npm link darkti-gulu
就OK啦~~~