Maison  >  Article  >  interface Web  >  Explication détaillée de Karma+Mocha dans les tests unitaires Vue

Explication détaillée de Karma+Mocha dans les tests unitaires Vue

亚连
亚连original
2018-06-08 16:56:331929parcourir

Cet article présente principalement l'explication détaillée des notes d'étude des tests unitaires Vue Karma+Mocha. Maintenant, je la partage avec vous et la donne comme référence.

Lorsque vous utilisez vue-cli pour créer un projet, il vous sera demandé si vous souhaitez installer les tests unitaires et les tests e2e. Puisqu'il nous est officiellement recommandé d'utiliser ces deux frameworks de test, apprenons-les et pratiquons-les.

Introduction

Karma

Karma est un outil de gestion de processus d'exécution de tests JavaScript (Test Runner) basé sur Node.js . La fonction principale de cet outil dans Vue est d'exécuter le projet dans divers navigateurs Web grand public à des fins de test.

En d'autres termes, il s'agit d'un outil de test qui permet de tester votre code dans un environnement de navigateur. La raison pour laquelle cela est nécessaire est que votre code peut être conçu pour être exécuté du côté du navigateur et que certains bogues peuvent ne pas être exposés lorsqu'ils sont testés dans l'environnement du nœud. De plus, si le navigateur a des problèmes de compatibilité, karma fournit un moyen de le faire. exécutez automatiquement votre code sur plusieurs navigateurs. Exécutez dans un environnement de navigateur (chrome, firefox, c'est-à-dire, etc.). Si votre code ne s'exécute que côté nœud, vous n'avez pas besoin d'utiliser le karma.

Mocha

Mocha est un framework de test qui implémente les tests unitaires dans vue-cli avec la bibliothèque d'assertions chai.

Quant à la bibliothèque d'assertions Chai, vous pouvez consulter la documentation chinoise de l'API de la bibliothèque d'assertions Chai.js. Elle est très simple. Vous pouvez la maîtriser rapidement en la vérifiant et en l'utilisant.

Ma compréhension du cadre de test

Processus d'exécution de l'unité d'exécution npm

  1. Exécuter npm run commande unitaire

  2. Démarrez l'environnement d'exécution Karma

  3. Utilisez Mocha pour tester les cas de test écrits avec des assertions Chai un par un

  4. Afficher les résultats du test dans le terminal

  5. Si le test réussit, karma-coverage générera une page Web avec les résultats de la couverture du test dans le ./test/unit/ dossier de couverture.

Karma

Pour Karma, je viens de prendre connaissance de ses options de configuration.

Ce qui suit est la configuration du karma de Vue, brièvement commentée :

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

Moka et chai

Jetons un coup d'œil aux exemples officiels (les deux Utilisez des commentaires pour expliquer la signification du code) :

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

Ce que vous devez savoir :

  1. Les scripts de test doivent être placés dans le fichier test/unit/ specs/ répertoire .

  2. La méthode de dénomination du script est [nom du composant].spec.js.

  3. La soi-disant assertion consiste à effectuer certaines opérations sur le composant et à prédire le résultat. Le test réussit si le résultat du test est le même que l’assertion.

  4. Le test unitaire teste par défaut tous les fichiers du répertoire src à l'exception de main.js, qui peut être modifié dans le fichier test/unit/index.js.

  5. Dans la bibliothèque d'assertions Chai, être est ce qui et a eu en même temps. Ces chaînes de langage n'ont aucun sens et sont juste pour faciliter la compréhension.

  6. Le script de test se compose de plusieurs descriptions, et chaque description se compose de plusieurs descriptions.

  7. En savoir plus sur les tests asynchrones

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

En savoir plus sur le hook de description (cycle de vie)

describe('hooks', function() {

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

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

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

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

 // test cases
});

Pratique

Ce qui précède a brièvement présenté l'utilisation des tests unitaires. Commençons les tests unitaires dans Vue !

util.js

Comme le montre la démo officielle de Vue, pour les tests unitaires de Vue, nous devons instancier le composant dans une instance de Vue, et parfois nous devons le suspendre Chargé dans DOM.

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

La méthode d'écriture ci-dessus sert simplement à obtenir le composant. Parfois, nous devons transmettre des attributs d'accessoires, des méthodes personnalisées, etc., et peut-être devons-nous utiliser un framework d'interface utilisateur tiers. La méthode d’écriture ci-dessus est donc très gênante.

Nous recommandons ici le script de l'outil de test unitaire d'Element, Util.js, qui encapsule les méthodes couramment utilisées dans les tests unitaires Vue. La démo suivante est également écrite sur la base de Util.js.
Voici une brève explication du but de chaque méthode.

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

Exemple 1

Dans l'exemple 1, nous avons testé les données de divers éléments du composant Hello et appris l'utilisation des méthodes destroyVM et createTest de util.js et Comment obtenir l'élément cible à tester. Pour savoir comment obtenir des éléments DOM, consultez le didacticiel sur les objets DOM.

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

Résultat de sortie

Hello.vue
√ Test pour obtenir l'élément Contenu
√ Test pour obtenir les données dans l'objet Vue
√ Test pour savoir si une certaine classe existe dans le DOM

Exemple 2

Dans l'exemple 2, nous utilisons createTest Créez un composant de test pour tester l'événement click et utilisons createVue pour créer un exemple d'objet Vue afin de tester l'utilisation du composant Click. Ici, vous pouvez principalement voir l'utilisation de la méthode createVue.

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

Résultat de sortie

click.vue
√ Clic sur le bouton Test Événements
√ Test de création d'objets Vue

Autres

Tous les exemples de codes sont placés dans le référentiel Github pour une visualisation facile. Si vous souhaitez voir plus de bons cas de test, il est recommandé d'utiliser Util.js pour découvrir comment écrire les scripts de tests unitaires d'Element. Il existe de nombreux scripts de test à apprendre. En tant que bibliothèque de composants d'interface utilisateur utilisée par la majorité des utilisateurs de Vue, les scripts de test doivent être très bien écrits. Vous pouvez même copier ces scripts. Je pense que cela sera d'une grande aide pour apprendre les tests unitaires des composants Vue.

Voici mes notes de lecture du test unitaire Element pour référence.

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实现分页组件

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn