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'

<style>
:root {
    --button-height: 32px;
    --font-size: 14px;
    --button-bg: white;
    --button-active-bg: #eee;
    --border-radius: 4px;
    --color: #333;
    --border-color: #999;
    --border-color-hover: #666;
}
</style>

五、使用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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349