Maison  >  Article  >  interface Web  >  mocha, chai, sinon et istanbul atteignent une couverture de tests unitaires de 100 %

mocha, chai, sinon et istanbul atteignent une couverture de tests unitaires de 100 %

PHP中文网
PHP中文网original
2017-07-10 18:10:361551parcourir

Dans le développement logiciel agile, la pratique la plus importante est le développement piloté par les tests. Au niveau des tests unitaires, un indicateur important que nous essayons d'atteindre est la couverture des tests. La couverture des tests mesure si tout notre code a été testé.

Mais l'indicateur lui-même n'est pas le but. Avec l'aide de la vérification de la couverture des tests, nous espérons trouver les codes qui ne sont pas couverts par les tests, afin de réfléchir à la manière de tester la logique de ces codes, et ensuite mieux. concevoir et refactoriser le code pour rendre le code plus efficace[1].

En parlant de tests, il m'est arrivé de lire récemment "La beauté des mathématiques", et il y avait un passage sur les informations dans le livre. Il en va de même lorsque nous changeons le comportement du code de non déterministe à déterministe. D'une boîte noire à une boîte blanche, il n'y a pas de pouvoir magique, elle ne peut fournir que suffisamment d'informations. Les assertions du test sont des informations, et la couverture du test est également une information. La couverture du test peut être considérée comme une sorte d'information indirecte. , ce qui peut éliminer une partie de l'incertitude, alors que les assertions complètes fournissent des informations plus directes. Associé aux contrôles de couverture des tests, il peut fournir suffisamment d'informations pour déterminer si le code se comporte comme prévu.

Technologies associées pour les tests

Istanbul est un outil de couverture de code pour le programme JavaScript, du nom d'Istanbul, la plus grande ville de Turquie. Istanbul convertira le code, générera un arbre syntaxique, puis injectera du code statistique à l'emplacement correspondant. Après l'exécution, le nombre d'exécutions de code sera compté en fonction de la valeur de la variable globale injectée une fois la conversion du code terminée. appellera test runner, Par exemple, mocha exécute le test du code converti et génère un rapport de test.

Mocha est un framework de test, qui est un outil pour exécuter des tests, similaire à Jasmine, Karma et Ava. Comme les annotations JUnit, mocha sert d'exécuteur et utilise les méthodes descibe et it pour définir des combinaisons de tests et regrouper différents tests. Mocha lui-même ne fournit pas d'assertions assert, donc pour fournir des assertions plus expressives, vous pouvez l'utiliser avec chai. Bien sûr, vous pouvez également utiliser le assert模块 fourni par nodejs.

Dans notre code, il y aura toujours une logique complexe ou du code asynchrone qui s'appuie sur io et le réseau, ce qui est difficile à tester à l'aide de méthodes directes. Dans ce cas, vous pouvez utiliser sinon pour simplifier le test de code complexe. . Sinon crée Test Double, également connu sous le nom de 测试替身, pour remplacer certaines fonctions ou classes dont dépend notre code par des avatars de test, et nous pouvons définir le comportement des avatars de test pour simuler les résultats requis par notre code, rendant ainsi la tâche difficile. tester La logique du code est exécutée.

Configurer l'environnement de test pour le projet nodejs

1 Installez les packages de dépendances correspondants

Mocha et Istanbul peuvent être installés globalement ou uniquement dans le projet en cours.

<code class="q">npm install --<span class="hljs-built_in">save-<span class="hljs-built_in">dev mocha chai sinon istanbul</span></span></code>

Une fois l'installation terminée, sous les scripts du fichier package.json, ajoutez des commandes pour exécuter des tests et des contrôles de couverture de test

<code class="json">{
  ...
  <span class="hljs-attr">"scripts":{
    <span class="hljs-attr">"coverage": <span class="hljs-string">"istanbul cover _mocha -- -R spec --timeout 5000 --recursive",
    <span class="hljs-attr">"coverage:check": <span class="hljs-string">"istanbul check-coverage",
  }
  ...
}</span></span></span></span></span></code>

Exécutez npm run coverage et npm run coverage:check pour générer un rapport de test, le premier génère un rapport de test et le second vérifie si la couverture du test répond aux exigences.

2 配置Istanbul

istanbul相关的执行参数,可以在命令行下执行时传递参数来制定,也可以在yaml格式的.istanbul.yml文件中配置。简单贴出一些重要的配置项

<code class="yaml"><span class="hljs-attr">instrumentation:
<span class="hljs-attr">  root: .   <span class="hljs-comment"># 执行的根目录
<span class="hljs-attr">  extensions:
<span class="hljs-bullet">    - .js   <span class="hljs-comment"># 检查覆盖率的文件扩张名
<span class="hljs-attr">  excludes: [<span class="hljs-string">'**/benchmark/**']

  ... ...

<span class="hljs-attr">reporting:
<span class="hljs-attr">  print: summary
<span class="hljs-attr">  reports: [lcov, text, html, text-summary] <span class="hljs-comment"># 生成报告的格式
<span class="hljs-attr">  dir: ./coverage   <span class="hljs-comment"># 生成报告保存的目录
<span class="hljs-attr">  watermarks:       <span class="hljs-comment"># 在不同覆盖率下会显示使用不同颜色
<span class="hljs-attr">    statements: [<span class="hljs-number">80, <span class="hljs-number">95]
    ... ...
<span class="hljs-attr">check:
<span class="hljs-attr">  global:
<span class="hljs-attr">    statements: <span class="hljs-number">100
<span class="hljs-attr">    branches: <span class="hljs-number">100
<span class="hljs-attr">    lines: <span class="hljs-number">100
<span class="hljs-attr">    functions: <span class="hljs-number">100</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

最后的check是项目要通过覆盖率检查需要达到的测试覆盖率,测试覆盖率包括四个维度,分别是语句覆盖率、分支覆盖率、行覆盖率和函数覆盖率。如果达不到设定的指标,在执行的时候会报错,项目的测试就无法通过自动化的持续集成。

编写测试代码

敏捷软件开发中的测试驱动开发,意在通过先写测试,根据调用者的契约,设计如何实现代码,从而写出更加容易测试的代码,提高代码的质量。也是我们练习测试的应该考虑的方向。

1 一段简单的mocha测试代码

利用chai提供的expect断言,我们可以用BDD的方式,写出更加符合代码预期行为的测试用例。

<code class="javascript"><span class="hljs-keyword">var chai = <span class="hljs-built_in">require(<span class="hljs-string">'chai')

chai.should()
<span class="hljs-keyword">var expect = chai.expect
<span class="hljs-keyword">var assert = chai.assert

describe(<span class="hljs-string">'basic test', <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">) {
  describe(<span class="hljs-string">'simple', <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">) {
    it(<span class="hljs-string">'data check', <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">) {
      <span class="hljs-keyword">var data = { <span class="hljs-attr">name: <span class="hljs-string">"test" }

      assert.isNotNull(data, <span class="hljs-string">'data should not be null')
      expect(data).to.be.an(<span class="hljs-string">'object')
      expect(data).to.have.all.keys([<span class="hljs-string">'name'])
      expect(data).to.deep.include({<span class="hljs-attr">name: <span class="hljs-string">'test'});
    });
  });
});</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

2 用Sinon模拟文件读写

<code class="javascript">... 同上 ...
var sinon = <span class="hljs-built_in">require(<span class="hljs-string">'sinon')
<span class="hljs-keyword">var fs = <span class="hljs-built_in">require(<span class="hljs-string">'fs')

describe(<span class="hljs-string">'sinon', <span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">) {
  it(<span class="hljs-string">"should mock readFile", <span class="hljs-function"><span class="hljs-keyword">function(<span class="hljs-params">done){
    sinon.stub(fs, <span class="hljs-string">'readFile').callsFake(<span class="hljs-function"><span class="hljs-keyword">function (<span class="hljs-params">path, callback) { callback(<span class="hljs-keyword">new <span class="hljs-built_in">Error(<span class="hljs-string">'read error')) })

    fs.readFile(<span class="hljs-string">"any file path", <span class="hljs-function"><span class="hljs-keyword">function(<span class="hljs-params">err,data){
      assert.isNotNull(err)
      done()
    })
    assert(fs.readFile.calledOnce)
  });
});</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code>

在mocha测试框架中,如果我们调用的是异步的代码,那么需要显示的调用it回调函数的done方法,告诉mocha异步调用什么时候结束。否则的话,测试会挂起,直到设置的超时时间结束。

Sinon将测试替身分为spy、stub和mock,其中:

  • Spy, 可以提供函数调用的信息,但不会改变函数的行为
  • Stub, 提供函数的调用信息,并且可以像示例代码中一样,让被stubbed的函数返回任何我们需要的行为。
  • Mock, 通过组合spies和stubs,使替换一个完整对象更容易。

本文的讨论篇幅有限,暂时不详细介绍各种sinon的使用方法,以后再通过其他文章专门介绍。

持续集成

完成所有代码之后,我们可以将代码发布到github,然后使用持续集成工具travis检查代码,将生成的测试报告上传到coverall上,这样就可以在项目中显示项目状态和测试覆盖率的badges。

具体使用方法,可以参看官方网站,使用coveralls需要在项目中安装依赖包npm i -D coveralls。并且添加package.json执行脚本istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

通常的nodejs项目.travis.yml配置如下:

<code class="yaml"><span class="hljs-attr">language: node_js
<span class="hljs-attr">node_js:
<span class="hljs-bullet">  - <span class="hljs-string">"7.6.0"
<span class="hljs-attr">install:
<span class="hljs-bullet">  - npm install
<span class="hljs-attr">script:
<span class="hljs-bullet">  - npm test
<span class="hljs-attr">after_script:
<span class="hljs-bullet">  - npm run coverall</span></span></span></span></span></span></span></span></span></span></code>

 

 

原文地址:http://www.51test.space/archives/2543

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