darkti UI—自动化单元测试和npm包发布

一、使用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"
 },
image.png

⑤运行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就成功了

image.png

引icon.png

image.png

npm run test整个步骤就是先用parcel打包button.vue,然后再用Karma打开浏览器进行测试,测试完毕后关闭浏览器;
⑥karma.conf.js中
files.png

browsers.png

3、测试用例怎么写? describeit,它是BDD(行为驱动开发);
describeit是属于Mocha,这个不用引入,它会自动引入;具体的断言expect是由chai.js引入的,chai.js是需要安装引入的;

describe('要测得组件',()=>{
      it('此次测试的名字', ()=>{
            expect(xx).to.equal(yyy)   // expect(xx).to.eq(yyy)   equal可写成eq
       })
})
点击事件的测试.png

image.png

二、持续集成(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会自动去检测,每当检测结果状态发生变化时,它会发邮件通知你;
可以参考阮一峰这篇文章;

登录.png

添加项目.png

寻找项目.png

运行通过.png

三、用npm发布自己的包

0、首先确保你的代码通过了测试;
1、更改package.json里的版本号为“0.0.1”(一般还未正式发布的包版本号都为0.0.x);
2、创建 index.js,在 index.js 里将你想要导出的内容全部导出;
3、去https://www.npmjs.com/注册一个账户;

npm注册.png

4、注册完一定要去邮箱里确认一下!!!!
5、在 gulu 项目根目录运行 npm adduser;
①你需要注意的是npm adduser必须要更换为 npm 官方源;
image.png

查找文件.png

进入文件.png

注释.png

npm adduser.png

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)

image.png

③在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装一下,如果一直装不上最新的,直接指定版本号来装


    image.png

    image.png

    image.png

    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啦~~~

image.png

image.png

六、总结

image.png

你可能感兴趣的:(darkti UI—自动化单元测试和npm包发布)