In der agilen Softwareentwicklung ist die testgetriebene Entwicklung die wichtigste Praxis. Auf der Unit-Test-Ebene versuchen wir, die Testabdeckung zu erreichen. Die Testabdeckung misst, ob unser gesamter Code getestet wurde.
Aber der Indikator selbst ist nicht der Zweck. Mithilfe der Testabdeckungsprüfung hoffen wir, die Codes zu finden, die nicht durch Tests abgedeckt werden, um darüber nachzudenken, wie wir die Logik dieser Codes testen können, und zwar besser Entwerfen und überarbeiten Sie den Code, um die Qualität des Codes zu verbessern.
Apropos Testen: Ich habe kürzlich „The Beauty of Mathematics“ gelesen und es gab eine Passage über Informationen in dem Buch. Dasselbe gilt für die Änderung des Codeverhaltens von nichtdeterministisch zu deterministisch. Von einer Black Box zu einer White Box gibt es keine magische Kraft. Die Behauptungen im Test sind auch Informationen. Die Testabdeckung kann als eine Art indirekte Information betrachtet werden , wodurch einige der Informationen beseitigt werden können, während vollständige Aussagen direktere Informationen liefern. In Verbindung mit Testabdeckungsprüfungen kann es genügend Informationen liefern, um festzustellen, ob sich der Code wie erwartet verhält.
Istanbul
ist ein Code-Coverage-Tool für das JavaScript
-Programm, benannt nach Istanbul, der größten Stadt in der Türkei. Istanbul konvertiert den Code, generiert einen Syntaxbaum und fügt dann statistischen Code an der entsprechenden Stelle ein. Nach Abschluss der Codekonvertierung wird die Anzahl der Codeausführungen basierend auf dem Wert der injizierten globalen Variablen gezählt ruft test runner
auf. Beispielsweise führt mocha
den Test des konvertierten Codes aus und generiert einen Testbericht.
Mocha
ist ein Test-Framework, ein Tool zum Ausführen von Tests, ähnlich wie Jasmine, Karma und Ava. Wie JUnit-Annotationen fungiert Mocha als Ausführender und verwendet die Methoden descibe
und it
, um Testanzüge zu definieren und verschiedene Tests zu gruppieren. Mocha selbst stellt keine assert
-Behauptungen bereit. Um ausdrucksstärkere Behauptungen bereitzustellen, können Sie es mit chai
verwenden. Natürlich können Sie auch die von nodejs bereitgestellten assert模块
verwenden.
In unserem Code wird es immer komplexe Logik oder asynchronen Code geben, der auf IO und Netzwerk basiert und mit direkten Methoden schwer zu testen ist. In diesem Fall können Sie sinon
verwenden, um das Testen von komplexem Code zu vereinfachen . Sinon erstellt Test Double, auch bekannt als 测试替身
, um einige Funktionen oder Klassen, von denen unser Code abhängt, durch Testavatare zu ersetzen, und wir können das Verhalten der Testavatare so einstellen, dass die von unserem Code geforderten Ergebnisse simuliert werden, was es schwierig macht zum Testen Die Codelogik wird ausgeführt.
Mocha und Istanbul können global oder nur im aktuellen Projekt installiert werden.
<code class="q">npm install --<span class="hljs-built_in">save-<span class="hljs-built_in">dev mocha chai sinon istanbul</span></span></code>
Fügen Sie nach Abschluss der Installation unter den Skripten der package.json
-Datei Befehle zum Ausführen von Tests und Testabdeckungsprüfungen hinzu
<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>
Führen Sie npm run coverage
und npm run coverage:check
aus, um einen Testbericht zu erstellen. Ersteres generiert einen Testbericht, und letzteres prüft, ob die Testabdeckung den Anforderungen entspricht.
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是项目要通过覆盖率检查需要达到的测试覆盖率,测试覆盖率包括四个维度,分别是语句覆盖率、分支覆盖率、行覆盖率和函数覆盖率。如果达不到设定的指标,在执行的时候会报错,项目的测试就无法通过自动化的持续集成。
敏捷软件开发中的测试驱动开发,意在通过先写测试,根据调用者的契约,设计如何实现代码,从而写出更加容易测试的代码,提高代码的质量。也是我们练习测试的应该考虑的方向。
利用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>
<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,其中:
本文的讨论篇幅有限,暂时不详细介绍各种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
Das obige ist der detaillierte Inhalt vonMocha, Chai, Sinon und Istanbul erreichen eine Unit-Test-Abdeckung von 100 %. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!