Heim  >  Artikel  >  Web-Frontend  >  Ausführliche Erklärung von Karma+Mocha im Vue-Unit-Test

Ausführliche Erklärung von Karma+Mocha im Vue-Unit-Test

亚连
亚连Original
2018-06-08 16:56:331929Durchsuche

Dieser Artikel stellt hauptsächlich die ausführliche Erklärung der Karma+Mocha-Studiennotizen für Vue-Einheiten vor. Jetzt teile ich sie mit Ihnen und gebe sie als Referenz.

Wenn Sie vue-cli zum Erstellen eines Projekts verwenden, werden Sie gefragt, ob Sie Unit-Tests und E2E-Tests installieren möchten. Da uns die Verwendung dieser beiden Test-Frameworks offiziell empfohlen wird, lernen und üben wir sie.

Einführung

Karma

Karma ist ein JavaScript-Tool zur Verwaltung von Testausführungsprozessen (Test Runner), das auf Node.js basiert . Die Hauptfunktion dieses Tools in Vue besteht darin, das Projekt zum Testen in verschiedenen gängigen Webbrowsern auszuführen.

Mit anderen Worten handelt es sich um ein Testtool, mit dem Ihr Code in einer Browserumgebung getestet werden kann. Der Grund dafür ist, dass Ihr Code möglicherweise für die Ausführung auf der Browserseite konzipiert ist und einige Fehler beim Testen in der Knotenumgebung möglicherweise nicht aufgedeckt werden. Wenn der Browser außerdem Kompatibilitätsprobleme aufweist, bietet Karma eine Möglichkeit, dies zu tun Führen Sie Ihren Code automatisch in mehreren Browsern aus (Chrome, Firefox usw.). Wenn Ihr Code nur auf der Knotenseite ausgeführt wird, müssen Sie kein Karma verwenden.

Mocha

Mocha ist ein Test-Framework, das Unit-Tests in Vue-Cli mit der Chai-Assertion-Bibliothek implementiert.

Was die Chai-Assertionsbibliothek betrifft, können Sie sich die chinesische Dokumentation der Chai.js-Assertionsbibliothek ansehen. Sie ist sehr einfach, indem Sie sie überprüfen und verwenden.

Mein Verständnis des Test-Frameworks

NPM-Laufeinheit-Ausführungsprozess

  1. NPM-Lauf ausführen Unit-Befehl

  2. Starten Sie die Karma-Laufumgebung

  3. Verwenden Sie Mocha, um mit Chai-Behauptungen geschriebene Testfälle nacheinander zu testen

  4. Testergebnisse im Terminal anzeigen

  5. Wenn der Test erfolgreich ist, generiert Karma-Coverage eine Webseite mit Testabdeckungsergebnissen im ./test/unit/ Abdeckungsordner.

Karma

Für Karma habe ich gerade etwas über die Konfigurationsoptionen erfahren.

Das Folgende ist Vues Karma-Konfiguration, kurz kommentiert:

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' }
   ]
  }
 })
}

Mokka und Chai

Werfen wir einen Blick auf die offiziellen Beispiele (alle kommentiert). Erklären Sie die Bedeutung des Codes):

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') 
 })
})

Was Sie wissen müssen:

  1. Die Testskripte müssen im Verzeichnis test/unit/specs/ abgelegt werden.

  2. Die Skriptbenennungsmethode ist [Komponentenname].spec.js.

  3. Die sogenannte Behauptung besteht darin, einige Operationen an der Komponente auszuführen und das Ergebnis vorherzusagen. Der Test ist erfolgreich, wenn das Testergebnis mit der Behauptung übereinstimmt.

  4. Der Unit-Test testet standardmäßig alle Dateien im src-Verzeichnis mit Ausnahme von main.js, das in der Datei test/unit/index.js geändert werden kann.

  5. In der Chai-Behauptungsbibliothek ist „be been“ das, was und „hat“ mit at of same. Diese Sprachketten sind bedeutungslos und dienen nur dem leichteren Verständnis.

  6. Das Testskript besteht aus mehreren Beschreibungen, und jede Beschreibung besteht aus mehreren Beschreibungen.

  7. Asynchrone Tests verstehen

it('异步请求应该返回一个对象', done => {
  request
  .get('https://api.github.com')
  .end(function(err, res){
   expect(res).to.be.an('object');
   done();
  });
});

Den Beschreibungs-Hook (Lebenszyklus) verstehen

describe('hooks', function() {

 before(function() {
  // 在本区块的所有测试用例之前执行
 });

 after(function() {
  // 在本区块的所有测试用例之后执行
 });

 beforeEach(function() {
  // 在本区块的每个测试用例之前执行
 });

 afterEach(function() {
  // 在本区块的每个测试用例之后执行
 });

 // test cases
});

Üben

Das Obige stellt kurz die Verwendung von Unit-Tests vor!

util.js

Wie aus der offiziellen Demo von Vue hervorgeht, müssen wir für Vue-Unit-Tests die Komponente in einer Vue-Instanz instanziieren und manchmal hängen bleiben In DOM geladen.

 const Constructor = Vue.extend(Hello) // 获得Hello组件实例
 const vm = new Constructor().$mount() // 将组件挂载到DOM上

Die obige Schreibmethode dient nur zum Abrufen der Komponente. Manchmal müssen wir Requisitenattribute, benutzerdefinierte Methoden usw. übergeben und möglicherweise auch ein UI-Framework eines Drittanbieters verwenden. Daher ist die obige Schreibmethode sehr problematisch.

Hier empfehlen wir das Unit-Testing-Tool-Skript Util.js von Element, das häufig verwendete Methoden beim Vue-Unit-Testen kapselt. Die folgende Demo ist ebenfalls auf Basis von Util.js geschrieben.
Hier finden Sie eine kurze Erläuterung des Zwecks jeder Methode.

/**
 * 回收 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) {}

Beispiel 1

In Beispiel 1 haben wir die Daten verschiedener Elemente der Hello-Komponente getestet und die Verwendung der destroyVM- und createTest-Methoden von util.js und gelernt wie man sie erhält Das Zielelement wird getestet. Informationen zum Abrufen von DOM-Elementen finden Sie im DOM-Objekt-Tutorial.

Hello.vue

<template>
 <p class="hello">
  <h1 class="hello-title">{{ msg }}</h1>
  <h2 class="hello-content">{{ content }}</h2>
 </p>
</template>

<script>
export default {
 name: &#39;hello&#39;,
 props: {
  content: String
 },
 data () {
  return {
   msg: &#39;Welcome!&#39;
  }
 }
}
</script>

Hello.spec.js

import { destroyVM, createTest } from &#39;../util&#39;
import Hello from &#39;@/components/Hello&#39;

describe(&#39;Hello.vue&#39;, () => {
 let vm

 afterEach(() => {
  destroyVM(vm)
 })

 it(&#39;测试获取元素内容&#39;, () => {
  vm = createTest(Hello, { content: &#39;Hello World&#39; }, true)
  expect(vm.$el.querySelector(&#39;.hello h1&#39;).textContent).to.equal(&#39;Welcome!&#39;)
  expect(vm.$el.querySelector(&#39;.hello h2&#39;).textContent).to.have.be.equal(&#39;Hello World&#39;)
 })

 it(&#39;测试获取Vue对象中数据&#39;, () => {
  vm = createTest(Hello, { content: &#39;Hello World&#39; }, true)
  expect(vm.msg).to.equal(&#39;Welcome!&#39;)
  // Chai的语言链是无意义的,可以随便写。如下:
  expect(vm.content).which.have.to.be.that.equal(&#39;Hello World&#39;) 
 })

 it(&#39;测试获取DOM中是否存在某个class&#39;, () => {
  vm = createTest(Hello, { content: &#39;Hello World&#39; }, true)
  expect(vm.$el.classList.contains(&#39;hello&#39;)).to.be.true
  const title = vm.$el.querySelector(&#39;.hello h1&#39;)
  expect(title.classList.contains(&#39;hello-title&#39;)).to.be.true
  const content = vm.$el.querySelector(&#39;.hello-content&#39;)
  expect(content.classList.contains(&#39;hello-content&#39;)).to.be.true
 })
})

Ausgabeergebnis

Hello.vue
√ Test, um den Elementinhalt zu erhalten
√ Testen Sie, um die Daten im Vue-Objekt abzurufen
√ Testen Sie, um zu ermitteln, ob eine bestimmte Klasse im DOM vorhanden ist

Beispiel 2

In Beispiel 2 Wir verwenden createTest, um einen Testkomponententest zu erstellen. Für Click-Ereignisse verwenden wir createVue, um ein Vue-Beispielobjekt zu erstellen, um die Verwendung der Click-Komponente zu testen. Hier können Sie hauptsächlich die Verwendung der Methode createVue sehen.

Click.vue

<template>
 <p>
  <span class="init-num">初始值为{{ InitNum }}</span><br>
  <span class="click-num">点击了{{ ClickNum }}次</span><br>
  <span class="result-num">最终结果为{{ ResultNum }}</span><br>
  <button @click="add">累加{{ AddNum }}</button>
 </p>
</template>

<script>
export default {
 name: &#39;Click&#39;,
 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(&#39;result&#39;, {
    ClickNum: this.ClickNum,
    ResultNum: this.ResultNum
   })
  }
 }
}
</script>

Click.spec.js

import { destroyVM, createTest, createVue } from &#39;../util&#39;
import Click from &#39;@/components/Click&#39;

describe(&#39;click.vue&#39;, () => {
 let vm

 afterEach(() => {
  destroyVM(vm)
 })

 it(&#39;测试按钮点击事件&#39;, () => {
  vm = createTest(Click, {
   AddNum: 10,
   InitNum: 11
  }, true)
  let buttonElm = vm.$el.querySelector(&#39;button&#39;)
  buttonElm.click()
  buttonElm.click()
  buttonElm.click()
  // setTimeout 的原因
  // 在数据改变之后,界面的变化会有一定延时。不用timeout有时候会发现界面没有变化
  setTimeout(done => {
   expect(vm.ResultNum).to.equal(41)
   expect(vm.$el.querySelector(&#39;.init-num&#39;).textContent).to.equal(&#39;初始值为11&#39;)
   expect(vm.$el.querySelector(&#39;.click-num&#39;).textContent).to.equal(&#39;点击了3次&#39;)
   expect(vm.$el.querySelector(&#39;.result-num&#39;).textContent).to.equal(&#39;最终结果为41&#39;)
   done()
  }, 100)
 })

 it(&#39;测试创建Vue对象&#39;, () => {
  let result
  vm = createVue({
   template: `
    <click @click="handleClick"></click>
   `,
   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()
  })
})

Ergebnisse ausgeben

click.vue
√ Schaltflächenklickereignis testen
√ Testen Sie die Erstellung von Vue-Objekten

Andere

Alle Beispielcodes werden zur einfachen Anzeige im Github-Repository abgelegt. Wenn Sie weitere gute Testfälle sehen möchten, wird empfohlen, Util.js zu verwenden, um einen Blick darauf zu werfen, wie die Unit-Test-Skripte von Element geschrieben werden. Es gibt viele Testskripte, die wir lernen können. Da es sich um eine UI-Komponentenbibliothek handelt, die von der Mehrheit der Vue-Benutzer verwendet wird, müssen die Testskripte sehr gut geschrieben sein. Ich glaube, dass dies beim Erlernen des Komponententests von Vue-Komponenten eine große Hilfe sein wird.

Das Folgende sind meine Notizen aus der Lektüre des Element-Unit-Tests als Referenz.

Util.js 方法包含了大多数Vue组件化的测试需求。

vm.$el vm.$nextTick 和 vm.$ref 都是在测试过程中比较常用的一些Vue语法糖。

需要注意: vm.$nextTick 方法是异步的,所以需要在里面使用done方法。

异步断言,方法参数需要是 _ 或者 done

大多数时候查询元素通过 querySelector 方法查询class获得

vm.$el.querySelector(&#39;.el-breadcrumb&#39;).innerText

大多数情况下查询是否存在某个Class通过 classList.contains 方法获得,查找的结果为 true 或 false

vm.$el .classList.contains(&#39;el-button--primary&#39;)

异步测试必须以 done() 方法结尾。setTimeout 和 vm.$nextTick 是常用的异步测试。

实现按钮点击:通过获取按钮元素 btn,执行 btn.click() 方法实现。

由于 Vue 进行异步更新DOM 的情况,一些依赖DOM更新结果的断言必须在 Vue.nextTick 回调中进行。

triggerEvent(vm.$refs.cascader.$el, &#39;mouseenter&#39;);
vm.$nextTick(_ => {
   vm.$refs.cascader.$el.querySelector(&#39;.el-cascader__clearIcon&#39;).click();
   vm.$nextTick(_ => {
    expect(vm.selectedOptions.length).to.be.equal(0);
    done();
   });
});

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在mint-ui中使用时间插件及获取选择值

VUE2实现二级省市联动选择

使用react实现分页组件

Das obige ist der detaillierte Inhalt vonAusführliche Erklärung von Karma+Mocha im Vue-Unit-Test. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn