Vue.js学習シリーズ6-VueユニットテストKarma+Mocha学習ノート

12517 ワード

vue-cliを使用してプロジェクトを作成すると、ユニットテストとe 2 eテストをインストールするかどうかをプロンプトされます.この2つのテストフレームワークを公式に推奨している以上、彼らを実践することを学びましょう.
概要
Karma
KarmaはNode.jsベースのJavaScriptテスト実行プロセス管理ツール(Test Runner)である.このツールのVueでの主な役割は、さまざまな主流のWebブラウザでプロジェクトを実行してテストすることです.つまり、ブラウザ環境でコードをテストできるテストツールです.必要なのは、あなたのコードがブラウザ側で実行されるように設計されている可能性があり、node環境でテストするとバグが露出しない可能性があります.また、ブラウザの互換性に問題があり、karmaはコードを複数のブラウザ(chrome、firefox、ieなど)環境で自動的に実行する手段を提供しています.コードがnode側でしか実行されない場合は、karmaを使用する必要はありません.
Mocha
Mochaは、vue-cliでchaiブレークスルーライブラリと連携してユニットテストを実現するテストフレームワークです.Mochaの常用命令と使い方はあまり多くありませんが、チェン一峰先生のテストフレームワークMocha実例チュートリアルを見れば大体理解できます.一方,Chai断言ライブラリはChai.js断言ライブラリAPIの中国語ドキュメントを見ることができ,簡単で,多く調べるとすぐに把握できる.
テストフレームワークの理解
npm run unit実行プロセス
  • npm run unit命令
  • を実行する.
  • Karma運転環境
  • をオン
  • Mochaを用いて個々の試験用Chai断言で書かれた試験用例
  • を行う.
  • 端末にテスト結果
  • を表示する.
  • テストに成功すると、karma-coverageは./test/unit/coverageフォルダにテストオーバーライド結果のページを生成します.

  • Karma
    Karmaについては、その構成オプションを理解しただけです.以下はVueのkarma構成です.簡単に説明します.
    var webpackConfig = require('../../build/webpack.test.conf')
    
    module.exports = function (config) {
      config.set({
        //    
        browsers: ['PhantomJS'],
        //     
        frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
        //     
        reporters: ['spec', 'coverage'],
        //       
        files: ['./index.js'],
        //      karma-webpack
        preprocessors: {
          './index.js': ['webpack', 'sourcemap']
        },
        // Webpack  
        webpack: webpackConfig,
        // Webpack   
        webpackMiddleware: {
          noInfo: true
        },
        //        
        // https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md
        coverageReporter: {
          dir: './coverage',
          reporters: [
            { type: 'lcov', subdir: '.' },
            { type: 'text-summary' }
          ]
        }
      })
    }
    
    

    Mochaとchai
    公式の例を見てみましょう(コードの意味を注釈で説明しました):
    import Vue from 'vue' //   Vue    Vue  
    import Hello from '@/components/Hello' //     
    //                describe ,      (test suite)
    describe('Hello.vue', () => {
      //   describe          it ,      (test case)
      it('should render correct contents', () => {
        const Constructor = Vue.extend(Hello) //   Hello    
        const vm = new Constructor().$mount() //       DOM 
        //  :DOM class hello     h1        Welcome to Your Vue.js App
        expect(vm.$el.querySelector('.hello h1').textContent)
          .to.equal('Welcome to Your Vue.js App')  
      })
    })
    
    

    必要な知識点:
  • テストスクリプトは、test/unit/specs/ディレクトリの下に配置されます.
  • スクリプトの名前は[ ].spec.jsです.
  • 断言とは、コンポーネントをいくつか操作し、結果を予言することである.テスト結果が断言と同じ場合、テストは合格します.
  • ユニットテストデフォルトテストsrcディレクトリの下にあるmain.jsを除くすべてのファイルは、test/unit/index.jsファイルで変更できます.
  • Chai断言ライブラリでは、to be been is that which and has have with at of sameという言語チェーンは意味がなく、理解しやすいだけです.
  • テストスクリプトは、複数のdescibeから構成され、各describeは、複数のitから構成される.
  • 非同期テスト
  • について
    it('            ', done => {
        request
        .get('https://api.github.com')
        .end(function(err, res){
          expect(res).to.be.an('object');
          done();
        });
    });
    
  • describeのフック(ライフサイクル)
  • について説明します.
    describe('hooks', function() {
    
      before(function() {
        //                
      });
    
      after(function() {
        //                
      });
    
      beforeEach(function() {
        //                
      });
    
      afterEach(function() {
        //                
      });
    
      // test cases
    });
    

    じっこう
    ユニットテストの使い方を簡単に紹介しましたが、Vueでユニットテストを行います!
    util.js
    Vueの公式demoから,VueのユニットテストではコンポーネントをVueインスタンスにインスタンス化する必要があり,DOMにマウントする必要がある場合もあることが分かった.
     const Constructor = Vue.extend(Hello) //   Hello    
     const vm = new Constructor().$mount() //       DOM 
    

    上記の書き方は単純にコンポーネントを取得するだけで、propsプロパティ、カスタムメソッドなどを渡す必要がある場合があります.サードパーティのUIフレームワークを使用する必要がある場合もあります.だから上記の書き方はとても面倒です.ここではElementのユニットテストツールスクリプトUtil.jsをお勧めします.Vueユニットテストでよく使われる方法をカプセル化しています.以下demoもこのUtil.jsに基づいて書かれています.ここでは,以下の各手法の用途を簡単に注釈した.
    /**
     *    vm,                  vm。
     * @param  {Object} vm
     */
    exports.destroyVM = function (vm) {}
    
    /**
     *      Vue      
     * @param  {Object|String}  Compo     -     ,     template
     * @param  {Boolean=false}  mounted   -       DOM  
     * @return {Object} vm
     */
    exports.createVue = function (Compo, mounted = false) {}
    
    /**
     *           
     * @param  {Object}  Compo          -     
     * @param  {Object}  propsData      - props   
     * @param  {Boolean=false} mounted  -       DOM  
     * @return {Object} vm
     */
    exports.createTest = function (Compo, propsData = {}, mounted = false) {}
    
    /**
     *       
     *  :            vm.$nextTick           。
     * mouseenter, mouseleave, mouseover, keyup, change, click  
     * @param  {Element} elm      -   
     * @param  {String} name      -     
     * @param  {*} opts           -    
     */
    exports.triggerEvent = function (elm, name, ...opts) {}
    
    /**
     *    “mouseup”   “mousedown”   ,       。
     * @param {Element} elm     -   
     * @param {*} opts          -     
     */
    exports.triggerClick = function (elm, ...opts) {}
    

    例1
    例1では、Helloコンポーネントの様々な要素のデータをテストし、util.jsdestroyVMおよびcreateTestメソッドの使用方法、およびターゲット要素をどのように取得してテストするかを学習した.DOM要素を取得する方法は、DOMオブジェクトチュートリアルを表示します.Hello.vue
    
    
    
    export default {
      name: 'hello',
      props: {
        content: String
      },
      data () {
        return {
          msg: 'Welcome!'
        }
      }
    }
    
    

    Hello.spec.js
    import { destroyVM, createTest } from '../util'
    import Hello from '@/components/Hello'
    
    describe('Hello.vue', () => {
      let vm
    
      afterEach(() => {
        destroyVM(vm)
      })
    
      it('        ', () => {
        vm = createTest(Hello, { content: 'Hello World' }, true)
        expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome!')
        expect(vm.$el.querySelector('.hello h2').textContent).to.have.be.equal('Hello World')
      })
    
      it('    Vue     ', () => {
        vm = createTest(Hello, { content: 'Hello World' }, true)
        expect(vm.msg).to.equal('Welcome!')
        // Chai         ,     。  :
        expect(vm.content).which.have.to.be.that.equal('Hello World') 
      })
    
      it('    DOM       class', () => {
        vm = createTest(Hello, { content: 'Hello World' }, true)
        expect(vm.$el.classList.contains('hello')).to.be.true
        const title = vm.$el.querySelector('.hello h1')
        expect(title.classList.contains('hello-title')).to.be.true
        const content = vm.$el.querySelector('.hello-content')
        expect(content.classList.contains('hello-content')).to.be.true
      })
    })
    

    出力結果
    Hello.vue
      √         
      √     Vue     
      √     DOM       class
    

    例2
    例2では、createTestを使用してテストコンポーネントテストクリックイベントを作成し、createVueを使用してVueサンプルオブジェクトテストコンポーネントClickの使用を作成します.ここでは主にcreateVueの方法の使用が見られる.Click.vue
    
    
    
    export default {
      name: 'Click',
      props: {
        AddNum: {
          type: Number,
          default: 1
        },
        InitNum: {
          type: Number,
          default: 1
        }
      },
      data () {
        return {
          ClickNum: 0,
          ResultNum: 0
        }
      },
      mounted () {
        this.ResultNum = this.InitNum
      },
      methods: {
        add () {
          this.ResultNum += this.AddNum
          this.ClickNum++
          this.$emit('result', {
            ClickNum: this.ClickNum,
            ResultNum: this.ResultNum
          })
        }
      }
    }
    
    
    

    Click.spec.js
    import { destroyVM, createTest, createVue } from '../util'
    import Click from '@/components/Click'
    
    describe('click.vue', () => {
      let vm
    
      afterEach(() => {
        destroyVM(vm)
      })
    
      it('        ', () => {
        vm = createTest(Click, {
          AddNum: 10,
          InitNum: 11
        }, true)
        let buttonElm = vm.$el.querySelector('button')
        buttonElm.click()
        buttonElm.click()
        buttonElm.click()
        // setTimeout    
        //        ,           。  timeout            
        setTimeout(done => {
          expect(vm.ResultNum).to.equal(41)
          expect(vm.$el.querySelector('.init-num').textContent).to.equal('    11')
          expect(vm.$el.querySelector('.click-num').textContent).to.equal('   3 ')
          expect(vm.$el.querySelector('.result-num').textContent).to.equal('     41')
          done()
        }, 100)
      })
    
      it('    Vue  ', () => {
        let result
        vm = createVue({
          template: `
            
          `,
          props: {
            AddNum: 10,
            InitNum: 11
          },
          methods: {
            handleClick (obj) {
              result = obj
            }
          },
          components: {
            Click
          }
        }, true)
        vm.$el.click()
        vm.$nextTick(done => {
          expect(result).to.be.exist
          expect(result.ClickNum).to.equal(1)
          expect(result.ResultNum).to.be.equal(21)
          done()
        })
    })
    

    出力結果
    click.vue
      √         
      √     Vue  
    

    その他
    すべてのサンプルコードはGithubウェアハウスに配置されており、表示が容易です.もっと良いテスト例を見たいなら、Util.jsに合わせてElementのユニットテストスクリプトの書き方を見てみることをお勧めします.中には多くのテストスクリプトがあります.多くのVueユーザーに使用されているUIコンポーネントライブラリとして、テストスクリプトもよく書かれているに違いありません.これらのスクリプトをコピーすることもできます.これはVueコンポーネントのユニットテストを学ぶのに役立つと信じています.
    以下は私がElementユニットのテストを見たノートで、参考にします.
  • Util.jsメソッドには、ほとんどのVueコンポーネント化のテスト要件が含まれています.
  • vm.$el vm.$nextTickおよびvm.$refは、試験中に比較的よく用いられるいくつかのVueシンタックス糖である.
  • vm.$nextTickメソッドは非同期なのでdoneメソッドを使用する必要があります.
  • 非同期断言、方法パラメータは_またはdone
  • である必要がある.
  • ほとんどの場合、クエリー要素はquerySelectorメソッドでclassをクエリーして取得されます.
  • vm.$el.querySelector('.el-breadcrumb').innerText

  • ほとんどの場合、クエリにClassが存在するかどうかはclassList.containsメソッドで取得され、検索結果はtrueまたはfalseです.
  • vm.$el .classList.contains('el-button--primary')

  • 非同期試験は、done()の方法で終了しなければならない.setTimeoutおよびvm.$nextTickは、一般的な非同期試験である.
  • 実装ボタンクリック:ボタン要素btnを取得することによって、btn.click()を実行する方法で実装される.
  • VueがDOMを非同期更新する場合、DOM更新結果に依存するいくつかの断言はVue.nextTickコールバックで行わなければならない.
  • triggerEvent(vm.$refs.cascader.$el, 'mouseenter');
    vm.$nextTick(_ => {
         vm.$refs.cascader.$el.querySelector('.el-cascader__clearIcon').click();
         vm.$nextTick(_ => {
            expect(vm.selectedOptions.length).to.be.equal(0);
            done();
         });
    });
    

    参考資料
  • ユニットテスト
  • Chai.js断言ライブラリAPI中国語ドキュメント
  • Element
  • フロントエンドユニットテストのKarma環境構築
  • フロントエンド自動化テストは何ですか?
  • テストフレームワークMochaインスタンスチュートリアル
  • Karma公式サイト
  • Vue.js学習シリーズ
    先端知識の断片化が深刻であることを考慮して、Vueに関する学習シリーズのブログを系統的に整理したいと思っています.
    Vue.js学習シリーズ1-vue-router 2学習実践ノート(DEMO付)Vue.js学習シリーズ2-vuex学習実践ノート(DEMO付)Vue.js学習シリーズ3-axiosとネットワーク転送に関する知識の学習実践Vue.js学習シリーズ4-Webpackパッケージツールの使用Vue.js学習シリーズ5-VUE-CLIからESLint Vue.js学習シリーズ6-VueユニットテストKarma+Mocha学習ノートVue.js学習シリーズ7-VueサーバレンダリングNuxt学習Vue.js学習シリーズ8-Vueソース学習のState学習
    Vue.jsラーニングシリーズプロジェクトアドレス
    この文書のソースコードはGitHubに収められており、参考にして、もちろんstarを残したほうがいい-.https://github.com/violetjack/VueStudyDemos
    作者について
    VioletJackは、フロントエンドエンジニアを効率的に学習し、効率を高める方法を研究するのが好きで、Vueフロントエンドに関する知識の学習、整理にも専念しています.注目、称賛、コメントコメントコメントを歓迎します~私は引き続きVue関連の良質な内容を産出します.
    新浪微博:http://weibo.com/u/2640909603 掘金:https://gold.xitu.io/user/571d953d39b0570068145cd1 CSDN: http://blog.csdn.net/violetjack0808 : http://www.jianshu.com/users/54ae4af3a98d/latest_articles Github: https://github.com/violetjack