<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Hải Nguyễn - ARROW Technologies Blog]]></title><description><![CDATA[Trang tổng hợp các kiến thức về lập trình]]></description><link>https://blog.arrow-tech.vn/</link><image><url>https://blog.arrow-tech.vn/favicon.png</url><title>Hải Nguyễn - ARROW Technologies Blog</title><link>https://blog.arrow-tech.vn/</link></image><generator>Ghost 5.81</generator><lastBuildDate>Thu, 12 Mar 2026 04:54:50 GMT</lastBuildDate><atom:link href="https://blog.arrow-tech.vn/author/hai/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Unit Testing trong project Ionic2]]></title><description><![CDATA[Việc UnitTest trong project Ionic2 sử dung karma và framework jasmine để thực hiện. Chúng ta sẽ tìm hiểu 1 số khái niệm cũng nhưng từng bước xây dựng môi trường UnitTest.]]></description><link>https://blog.arrow-tech.vn/unit-testing-trong-project-ionic2/</link><guid isPermaLink="false">63915acd7a2f410001205d98</guid><category><![CDATA[Testing]]></category><dc:creator><![CDATA[Hải Nguyễn]]></dc:creator><pubDate>Thu, 21 Jul 2016 03:16:58 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Vi&#x1EC7;c UnitTest trong project Ionic2 s&#x1EED; dung karma v&#xE0; framework jasmine &#x111;&#x1EC3; th&#x1EF1;c hi&#x1EC7;n. Ch&#xFA;ng ta s&#x1EBD; t&#xEC;m hi&#x1EC3;u 1 s&#x1ED1; kh&#xE1;i ni&#x1EC7;m c&#x169;ng nh&#x1B0;ng t&#x1EEB;ng b&#x1B0;&#x1EDB;c x&#xE2;y d&#x1EF1;ng m&#xF4;i tr&#x1B0;&#x1EDD;ng UnitTest.</p>
<h3 id="icckhinim">I. C&#xE1;c kh&#xE1;i ni&#x1EC7;m</h3>
<h6 id="karma">Karma</h6>
<p>L&#xE0; c&#xF4;ng c&#x1EE5; th&#x1EF1;c thi &#x111;o&#x1EA1;n m&#xE3; ki&#x1EC3;m ch&#x1EE9;ng (test code) C&#xF3; th&#x1EC3; hi&#x1EC3;u nh&#x1B0; l&#xE0; m&#xF4;i tr&#x1B0;&#x1EDD;ng m&#xE0; c&#xE1;c test code s&#x1EBD; ch&#x1EA1;y tr&#x1EC7;n &#x111;&#xF3;. &#x110;&#x1B0;a ra k&#x1EBF;t qu&#x1EA3;, th&#x1ED1;ng k&#xEA; c&#xE1;c ch&#x1EC9; s&#x1ED1; sau khi th&#x1EF1;c thi test code.</p>
<h6 id="jasmine">Jasmine</h6>
<p>L&#xE0; m&#x1ED9;t framework vi&#x1EBF;t test code javascript theo m&#xF4; h&#xEC;nh BDD (Behavior-Driven Development)</p>
<h6 id="gulp">Gulp</h6>
<p>L&#xE0; c&#xF4;ng c&#x1EE5; h&#x1ED7; tr&#x1EE3; t&#x1EF1; &#x111;&#x1ED9;ng h&#xF3;a c&#xE1;c task trong qu&#xE1; tr&#xEC;nh ph&#xE1;t tri&#x1EC3;n nh&#x1B0;: build code, run code, copy files,... Ch&#xFA;ng ta s&#x1EBD; s&#x1EED; d&#x1EE5;ng gulp &#x111;&#x1EC3; s&#x1EAF;p x&#x1EBF;p c&#xE1;c lu&#x1ED3;ng ki&#x1EC3;m ch&#x1EE9;ng.</p>
<h6 id="browserify">Browserify</h6>
<p>L&#xE0; c&#xF4;ng c&#x1EE5; d&#x1EF1;a tr&#xEA;n n&#x1EC1;n t&#x1EA3;ng nodejs, h&#x1B0;&#x1EDB;ng &#x111;&#x1EBF;n gi&#x1EA3;i quy&#x1EBF;t v&#x1EA5;n &#x111;&#x1EC1; resolve dependencies trong nodejs (th&#x1B0;&#x1EDD;ng s&#x1EED; d&#x1EE5;ng <code>require()</code> &#x111;&#x1EC3; g&#x1ECD;i &#x111;&#x1EBF;n c&#xE1;c th&#x1B0; vi&#x1EC7;n). C&#xF3; th&#x1EC3; hi&#x1EC3;u l&#xE0; Browserify s&#x1EBD; t&#xEC;m c&#xE1;c l&#x1EC7;nh <code>require()</code> trong code v&#xE0; t&#x1EF1; &#x111;&#x1ED9;ng t&#xEC;m c&#xE1;c module n&#xE0;y, sau &#x111;&#xF3; &#x111;&#xF3;ng g&#xF3;i c&#xF9;ng v&#x1EDB;i m&#xE3; ngu&#x1ED3;n &#x111;&#x1EC3; &#x111;&#x1EA3;m b&#x1EA3;o m&#xE3; ngu&#x1ED3;n lu&#xF4;n c&#xF3; th&#x1EC3; ch&#x1EA1;y &#x111;&#x1B0;&#x1EE3;c.</p>
<h6 id="commonjsmodule">CommonJs module</h6>
<p>L&#xE0; c&#xE1;c module th&#x1ECF;a m&#xE3;n c&#xE1;c &#x111;i&#x1EC1;u ki&#x1EC7;n sau:</p>
<ul>
<li>
<p>Khi t&#x1EA1;o ra module th&#xEC; d&#xF9;ng module.exports ho&#x1EB7;c exports</p>
</li>
<li>
<p>CommonJS module, s&#x1EED; d&#x1EE5;ng h&#xE0;m require</p>
</li>
</ul>
<h6 id="tslint">Tslint</h6>
<p>Linting tool c&#xF3; th&#x1EC3; gi&#xFA;p developer t&#x1ED1;i &#x1B0;u h&#xF3;a code v&#xE0; vi&#x1EBF;t code ch&#x1EA5;t l&#x1B0;&#x1EE3;ng cao. Linting l&#xE0; m&#x1ED9;t quy tr&#xEC;nh ki&#x1EC3;m tra code t&#xEC;m l&#x1ED7;i trong code ngu&#x1ED3;n, v&#xE0; &#x111;&#xE1;nh d&#x1EA5;u c&#xE1;c bug ti&#x1EC1;m n&#x103;ng. C&#xF3; th&#x1EC3; hi&#x1EC3;u &#x111;&#x1A1;n gi&#x1EA3;n th&#xEC; tslint nh&#x1B0; m&#x1ED9;t b&#x1ED9; coding convetion. linting (linter) s&#x1EED; d&#x1EE5;ng k&#x1EF9; thu&#x1EAD;t ph&#xE2;n t&#xED;ch code t&#x129;nh. N&#xF3;i c&#xE1;ch kh&#xE1;c, code &#x111;&#x1B0;&#x1EE3;c ki&#x1EC3;m tra m&#xE0; kh&#xF4;ng c&#x1EA7;n ph&#x1EA3;i ch&#x1EA1;y.</p>
<h3 id="iicuhnhmitrngunittest">II. C&#x1EA5;u h&#xEC;nh m&#xF4;i tr&#x1B0;&#x1EDD;ng Unit Test</h3>
<h6 id="citdependencyvtypings">C&#xE0;i &#x111;&#x1EB7;t dependency v&#xE0; typings</h6>
<p>`* browserify</p>
<ul>
<li>browserify-istanbul</li>
<li>codecov.io</li>
<li>gulp-tslint</li>
<li>gulp-typescript</li>
<li>isparta</li>
<li>jasmine-core</li>
<li>jasmine-spec-reporter</li>
<li>karma</li>
<li>karma-browserify</li>
<li>karma-chrome-launcher</li>
<li>karma-coverage</li>
<li>karma-jasmine</li>
<li>karma-mocha-reporter</li>
<li>karma-phantomjs-launcher</li>
<li>phantomjs-prebuilt</li>
<li>protractor</li>
<li>tsify</li>
<li>ts-node</li>
<li>tslint</li>
<li>tslint-eslint-rules</li>
<li>typescript</li>
<li>typings`</li>
</ul>
<p>Chi ti&#x1EBF;t n&#x1ED9;i dung c&#x1EE7;a dependency th&#xEC; c&#xE1;c b&#x1EA1;n t&#x1EF1; t&#xEC;m hi&#x1EC3;u th&#xEA;m nh&#xE9;. Trong n&#x1ED9;i dung l&#x1EA7;n n&#xE0;y t&#xF4;i ch&#x1EC9; h&#x1B0;&#x1EDB;ng d&#x1EAB;n c&#xE1;ch c&#x1EA5;u h&#xEC;nh th&#xF4;i.<br>
B&#x1EA1;n c&#xF3; th&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t th&#xF4;ng qua t&#x1EEB;ng d&#xF2;ng l&#x1EC7;nh</p>
<pre><code>npm install -g typings

npm install --save-dev browserify-istanbul codecov.io gulp-tslint gulp-typescript isparta jasmine-core karma karma-browserify karma-chrome-launcher karma-coverage karma-jasmine karma-mocha-reporter karma-phantomjs-launcher phantomjs-prebuilt traceur tsify ts-node tslint

typings install --save --global registry:dt/jasmine registry:dt/node
</code></pre>
<p>Ho&#x1EB7;c h&#xE3;y c&#x1EA5;u h&#xEC;nh v&#xE0;o <code>package.json</code>. V&#xE0; s&#x1EED; d&#x1EE5;ng npm &#x111;&#x1EC3; install l&#x1EA1;i. Ch&#x1EB3;ng h&#x1EA1;n nh&#x1B0; th&#x1EBF; n&#xE0;y.</p>
<pre><code class="language-json">&quot;devDependencies&quot;: {
    &quot;browserify&quot;: &quot;13.0.1&quot;,
    &quot;browserify-istanbul&quot;: &quot;2.0.0&quot;,
    &quot;codecov.io&quot;: &quot;0.1.6&quot;,
    &quot;del&quot;: &quot;2.2.1&quot;,
    &quot;gulp&quot;: &quot;3.9.1&quot;,
    &quot;gulp-tslint&quot;: &quot;5.0.0&quot;,
    &quot;gulp-typescript&quot;: &quot;2.13.6&quot;,
    &quot;gulp-watch&quot;: &quot;4.3.8&quot;,
    &quot;ionic-gulp-browserify-typescript&quot;: &quot;2.0.0&quot;,
    &quot;ionic-gulp-fonts-copy&quot;: &quot;1.0.0&quot;,
    &quot;ionic-gulp-html-copy&quot;: &quot;1.0.0&quot;,
    &quot;ionic-gulp-sass-build&quot;: &quot;1.0.0&quot;,
    &quot;ionic-gulp-scripts-copy&quot;: &quot;2.0.1&quot;,
    &quot;isparta&quot;: &quot;4.0.0&quot;,
    &quot;jasmine-core&quot;: &quot;2.4.1&quot;,
    &quot;jasmine-spec-reporter&quot;: &quot;2.5.0&quot;,
    &quot;karma&quot;: &quot;1.1.0&quot;,
    &quot;karma-browserify&quot;: &quot;5.0.5&quot;,
    &quot;karma-chrome-launcher&quot;: &quot;1.0.1&quot;,
    &quot;karma-coverage&quot;: &quot;1.0.0&quot;,
    &quot;karma-jasmine&quot;: &quot;1.0.2&quot;,
    &quot;karma-mocha-reporter&quot;: &quot;2.0.4&quot;,
    &quot;karma-phantomjs-launcher&quot;: &quot;1.0.1&quot;,
    &quot;phantomjs-prebuilt&quot;: &quot;2.1.7&quot;,
    &quot;protractor&quot;: &quot;3.3.0&quot;,
    &quot;run-sequence&quot;: &quot;1.2.1&quot;,
    &quot;ts-node&quot;: &quot;0.9.3&quot;,
    &quot;tsify&quot;: &quot;0.16.0&quot;,
    &quot;tslint&quot;: &quot;3.12.1&quot;,
    &quot;tslint-eslint-rules&quot;: &quot;1.3.0&quot;,
    &quot;typings&quot;: &quot;1.3.1&quot;
  },
</code></pre>
<pre><code>$ npm install
</code></pre>
<h6 id="cuhnhgulp">C&#x1EA5;u h&#xEC;nh gulp</h6>
<p>&#x110;&#x1EB7;t file c&#x1EA5;u h&#xEC;nh<code>./test/gulpfile.ts</code>. C&#x1EA5;p &#x111;&#x1ED9; b&#x1EB1;ng v&#x1EDB;i c&#x1EA5;p &#x111;&#x1ED9; root c&#x1EE7;a d&#x1EF1; &#xE1;n. &#x110;&#xE2;y l&#xE0; m&#x1ED9;t ph&#x1EA7;n c&#x1EE7;a trong quy &#x111;inh c&#x1EE7;a <a href="https://angular.io/styleguide?ref=blog.arrow-tech.vn">Angular 2 Style Guide</a> . Tuy nhi&#xEA;n b&#x1EA1;n c&#xF3; th&#x1EC3; &#x111;&#x1EC3; &#x1EDF; b&#x1EA5;t k&#x1EF3; th&#x1B0; m&#x1EE5;c n&#xE0;o m&#xE0; b&#x1EA1;n mu&#x1ED1;n. Nh&#x1B0;ng h&#xE3;y nh&#x1EDB; r&#x1EB1;ng, khi b&#x1EA1;n s&#x1EED; d&#x1EE5;ng l&#x1EC7;nh gulp th&#xEC; h&#xE3;y c&#x1EA5;u h&#xEC;nh &#x111;&#x1EC3; tr&#x1ECF; &#x111;&#x1EBF;n file n&#xE0;y.</p>
<pre><code>gulp --gulpfile test/gulpfile.ts --cwd ./ unit-test
</code></pre>
<h6 id="sakarmasstatic">S&#x1EED;a Karma&#x2019;s static</h6>
<p>&#x110;&#x1EC3; c&#xF3; th&#x1EC3; output ra vi&#x1EC7;c ch&#x1EA1;y test th&#xF4;ng qua html h&#xE3;y copy t&#x1EA1;o th&#xEA;m th&#x1B0; 2 file context.html v&#xE0; debug.html v&#xE0;o node_modules/karma/static. N&#x1EBF;u kh&#xF4;ng thi&#x1EBF;t l&#x1EAD;p 2 file n&#xE0;y th&#xEC; kh&#xF4;ng th&#x1EC3; ch&#x1EA1;y &#x111;&#x1B0;&#x1EE3;c PhantomJS.</p>
<p><code>context.html</code></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;!--
This is the execution context.
Loaded within the iframe.
Reloaded before every execution run.
--&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;&lt;/title&gt;
  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;ion-app&gt;&lt;/ion-app&gt;
  &lt;!-- The scripts need to be in the body DOM element, as some test running frameworks need the body
       to have already been created so they can insert their magic into it. For example, if loaded
       before body, Angular Scenario test framework fails to find the body and crashes and burns in
       an epic manner. --&gt;
  &lt;script src=&quot;context.js&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;text/javascript&quot;&gt;
    // Configure our Karma and set up bindings
    %CLIENT_CONFIG%
    window.__karma__.setupContext(window);

    // All served files with the latest timestamps
    %MAPPINGS%
  &lt;/script&gt;
  &lt;!-- Dynamically replaced with &lt;script&gt; tags --&gt;
  %SCRIPTS%
  &lt;script type=&quot;text/javascript&quot;&gt;
    window.__karma__.loaded();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p><code>debug.html</code></p>
<pre><code class="language-html">&lt;!doctype html&gt;
&lt;!--
This file is almost the same as context.html - loads all source files,
but its purpose is to be loaded in the main frame (not within an iframe),
just for immediate execution, without reporting to Karma server.
--&gt;
&lt;html&gt;
&lt;head&gt;
%X_UA_COMPATIBLE%
  &lt;title&gt;Karma DEBUG RUNNER&lt;/title&gt;
  &lt;link href=&quot;favicon.ico&quot; rel=&quot;icon&quot; type=&quot;image/x-icon&quot; /&gt;
  &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;ion-app&gt;&lt;/ion-app&gt;
  &lt;!-- The scripts need to be at the end of body, so that some test running frameworks
   (Angular Scenario, for example) need the body to be loaded so that it can insert its magic
   into it. If it is before body, then it fails to find the body and crashes and burns in an epic
   manner. --&gt;
  &lt;script src=&quot;context.js&quot;&gt;&lt;/script&gt;
  &lt;script src=&quot;debug.js&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;text/javascript&quot;&gt;
    // Configure our Karma
    %CLIENT_CONFIG%

    // All served files with the latest timestamps
    %MAPPINGS%
  &lt;/script&gt;
  &lt;!-- Dynamically replaced with &lt;script&gt; tags --&gt;
  %SCRIPTS%
  &lt;script type=&quot;text/javascript&quot;&gt;
    window.__karma__.loaded();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h6 id="linting">Linting</h6>
<p>M&#x1EB7;c &#x111;&#x1ECB;nh linting &#x111;&#x1B0;&#x1EE3;c c&#x1EA5;u h&#xEC;nh trong khi ch&#x1EA1;y unit test. Khi qu&#xE1; tr&#xEC;nh ph&#xE2;n t&#xED;ch ch&#x1B0;a &#x111;&#x1EA1;t th&#xEC; s&#x1EBD; kh&#xF4;ng th&#x1EF1;c thi c&#xE1;c test code.<br>
File C&#x1EA5;u h&#xEC;nh c&#x1EE7;a lint &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1EB7;t trong <code>tslint.json</code>. B&#x1EA1;n c&#xF3; th&#x1EC3; tham kh&#x1EA3;o 1 s&#x1ED1; c&#xFA; ph&#xE1;p quy &#x111;&#x1ECB;nh c&#x1EE7;a lint</p>
<pre><code>&quot;rules&quot;: {
    &quot;align&quot;: [
      true,
      &quot;parameters&quot;,
      &quot;arguments&quot;,
      &quot;statements&quot;
    ],
    &quot;ban&quot;: false,
    &quot;class-name&quot;: true,
    &quot;comment-format&quot;: [
      true,
      &quot;check-space&quot;
    ],
    &quot;curly&quot;: false,
    &quot;eofline&quot;: true,
    &quot;forin&quot;: false,
    &quot;indent&quot;: [
      true,
      &quot;spaces&quot;
    ],
    &quot;interface-name&quot;: false,
    &quot;jsdoc-format&quot;: true,
    &quot;label-position&quot;: true,
    &quot;label-undefined&quot;: true,
    &quot;max-line-length&quot;: [
      true,
      180
    ]
</code></pre>
<p>&#x110;&#x1EC3; t&#x1EAF;t ch&#x1EE9;c n&#x103;ng linting th&#xEC; ch&#x1EC9; c&#x1EA7;n x&#xF3;a b&#x1ECF; lint trong <code>gulpfile.ts</code></p>
<pre><code class="language-typescript">// build unit tests, run unit tests, remap and report coverage
gulp.task(&apos;unit-test&apos;, (done: Function) =&gt; {
  runSequence(
    [&apos;clean&apos;], // Ionic&apos;s clean task, nukes the whole of www/build
    [&apos;lint&apos;, &apos;html&apos;],
    &apos;karma&apos;,
    (&lt;any&gt;done)
  );
});
</code></pre>
<h6 id="lnhunittest">L&#x1EC7;nh unit test</h6>
<pre><code>node_modules/gulp/bin/gulp.js --gulpfile test/gulpfile.ts --cwd ./ unit-test
</code></pre>
<p>&#x110;&#x1EC3; &#x111;&#x1A1;n gi&#x1EA3;n h&#x1A1;n th&#xEC; c&#xF3; th&#x1EC3; c&#xE0;i &#x111;&#x1EB7;t v&#xE0;o <code>package.json</code></p>
<pre><code>&quot;scripts&quot;: {
    &quot;karma&quot;: &quot;gulp --gulpfile test/gulpfile.ts --cwd ./ karma-debug&quot;
    &quot;test&quot;: &quot;gulp --gulpfile test/gulpfile.ts --cwd ./ unit-test&quot;
}
</code></pre>
<p>L&#x1EA7;n sau khi ch&#x1EC9; c&#x1EA7;n th&#x1EF1;c thi <code>npm test</code> l&#xE0; &#x111;&#xE3; c&#xF3; th&#x1EC3; th&#x1EF1;c thi unit test.</p>
<h3 id="iiithcthiunittest">III) Th&#x1EF1;c thi Unit Test</h3>
<p>C&#x1EA5;u tr&#xFA;c th&#x1B0; m&#x1EE5;c</p>
<pre><code>app/
&#x251C;&#x2500;&#x2500; app.html
&#x251C;&#x2500;&#x2500; app.spec.ts
&#x251C;&#x2500;&#x2500; app.ts
&#x251C;&#x2500;&#x2500; components
&#x2502;   &#x251C;&#x2500;&#x2500; clickerButton
&#x2502;   &#x2502;   &#x251C;&#x2500;&#x2500; clickerButton.html
&#x2502;   &#x2502;   &#x251C;&#x2500;&#x2500; clickerButton.spec.ts
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; clickerButton.ts
&#x2502;   &#x2514;&#x2500;&#x2500; clickerForm
&#x2502;       &#x251C;&#x2500;&#x2500; clickerForm.html
&#x2502;       &#x251C;&#x2500;&#x2500; clickerForm.spec.ts
&#x2502;       &#x2514;&#x2500;&#x2500; clickerForm.ts
&#x251C;&#x2500;&#x2500; models
&#x2502;   &#x251C;&#x2500;&#x2500; clicker.spec.ts
&#x2502;   &#x251C;&#x2500;&#x2500; clicker.ts
&#x2502;   &#x251C;&#x2500;&#x2500; click.spec.ts
&#x2502;   &#x2514;&#x2500;&#x2500; click.ts
&#x251C;&#x2500;&#x2500; pages
&#x2502;   &#x251C;&#x2500;&#x2500; clickerList
&#x2502;   &#x2502;   &#x251C;&#x2500;&#x2500; clickerList.html
&#x2502;   &#x2502;   &#x251C;&#x2500;&#x2500; clickerList.scss
&#x2502;   &#x2502;   &#x251C;&#x2500;&#x2500; clickerList.spec.ts
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; clickerList.ts
&#x2502;   &#x2514;&#x2500;&#x2500; page2
&#x2502;       &#x251C;&#x2500;&#x2500; page2.html
&#x2502;       &#x251C;&#x2500;&#x2500; page2.scss
&#x2502;       &#x2514;&#x2500;&#x2500; page2.ts
&#x2514;&#x2500;&#x2500; services
    &#x251C;&#x2500;&#x2500; clickers.spec.ts
    &#x251C;&#x2500;&#x2500; clickers.ts
    &#x251C;&#x2500;&#x2500; utils.spec.ts
    &#x2514;&#x2500;&#x2500; utils.ts

test
&#x251C;&#x2500;&#x2500; gulpfile.ts
&#x251C;&#x2500;&#x2500; karma.config.js
&#x251C;&#x2500;&#x2500; testUtils.ts
&#x2514;&#x2500;&#x2500; karma-static
    &#x251C;&#x2500;&#x2500; context.html
    &#x2514;&#x2500;&#x2500; debug.html
</code></pre>
<h6 id="baophcodetestcoverage">&#x110;&#x1ED9; bao ph&#x1EE7; code (Test Coverage)</h6>
<p>B&#x1EA1;n c&#xF3; th&#x1EC3; xem m&#x1EE9;c &#x111;&#x1ED9; coverage tr&#xEA;n tr&#xEC;nh duy&#x1EC7;t b&#x1EB1;ng c&#xE1;ch access v&#xE0;o th&#x1B0; m&#x1EE5;c /path/to/[appname]/coverage/lcov-report/<br>
<img src="https://blog.arrow-tech.vn/content/images/2016/07/Selection_022-2.jpg" alt loading="lazy"></p>
<h6 id="testdebug">Test debug</h6>
<p>N&#x1EBF;u b&#x1EA1;n &#x111;&#xE3; c&#x1EA5;u h&#xEC;nh script &#x1EDF; b&#x1B0;&#x1EDB;c tr&#xEA;n h&#xE3;y s&#x1EED; d&#x1EE5;ng npm run karma &#x111;&#x1EC3; th&#x1EF1;c thi ch&#x1EBF; &#x111;&#x1ED9; debug.</p>
<h6 id="mtskhinimvtontcajasmine">M&#x1ED9;t s&#x1ED1; kh&#xE1;i ni&#x1EC7;m v&#xE0; to&#xE1;n t&#x1EED; c&#x1EE7;a jasmine</h6>
<ul>
<li>
<p>Spec Suite</p>
<ul>
<li>L&#xE0; m&#x1ED9;t b&#x1ED9; k&#x1ECB;ch b&#x1EA3;n test, bao g&#x1ED3;m nhi&#x1EC1;u h&#xE0;m, m&#x1ED7;i h&#xE0;m test t&#x1EAD;p trung v&#xE0;o m&#x1ED9;t n&#x1ED9;i dung c&#x1EA7;n ki&#x1EC3;m tra c&#x1EE7;a ch&#x1B0;&#x1A1;ng tr&#xEC;nh. Spec Suite &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ECB;nh ngh&#x129;a b&#x1EDF;i h&#xE0;m describe().</li>
</ul>
</li>
<li>
<p>Khai b&#xE1;o h&#xE0;m test (Spec)</p>
<ul>
<li>Trong Jasmine, m&#x1ED7;i h&#xE0;m ki&#x1EC3;m th&#x1EED; &#x111;&#x1B0;&#x1EE3;c g&#x1ECD;i l&#xE0; m&#x1ED9;t Spec. Jasmine cung c&#x1EA5;p h&#xE0;m it() &#x111;&#x1EC3; &#x111;&#x1ECB;nh ngh&#x129;a Spec.</li>
<li>Ch&#xFA;ng ta c&#xF3; th&#x1EC3; ph&#xE2;n nh&#x1ECF; c&#xE1;c Spec Suite b&#x1EB1;ng c&#xE1;ch &#x111;&#x1ECB;nh ngh&#x129;a c&#xE1;c Spec Suite l&#x1ED3;ng nhau.</li>
</ul>
</li>
<li>
<p>To&#xE1;n t&#x1EED; so s&#xE1;nh</p>
</li>
</ul>
<ul>
<li><code>berforeEach</code> v&#xE0; <code>afterEach</code> &#x111;&#x1EC3; khai b&#xE1;o, x&#xF3;a nh&#x1EEF;ng bi&#x1EBF;n, h&#xE0;m s&#x1EBD; &#x111;&#x1B0;&#x1EE3;c ch&#x1EA1;y tr&#x1B0;&#x1EDB;c (sau) khi ch&#x1EA1;y t&#x1EEB;ng spec</li>
<li><code>expect(x).toEqual(val)</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh gi&#xE1; tr&#x1ECB; c&#x1EE7;a &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng x b&#x1EB1;ng v&#x1EDB;i val (nh&#x1B0;ng kh&#xF4;ng nh&#x1EA5;t thi&#x1EBF;t &#x111;&#x1ED3;ng nh&#x1EA5;t nhau).</li>
<li><code>expect(x).toBe(obj)</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng x &#x111;&#x1ED3;ng nh&#x1EA5;t v&#x1EDB;i obj (2 &#x111;&#x1ED1;i t&#x1B0;&#x1EE3;ng n&#xE0;y l&#xE0; m&#x1ED9;t).</li>
<li><code>expect(x).toMatch(regexp)</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh chu&#x1ED7;i x kh&#x1EDB;p v&#x1EDB;i bi&#x1EC3;u th&#x1EE9;c ch&#xED;nh quy regexp.</li>
<li><code>expect(x).toBeNull()</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng bi&#x1EBF;n x ch&#x1EE9;a gi&#xE1; tr&#x1ECB; l&#xE0; null.</li>
<li><code>expect(x).toBeTruthy()</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng gi&#xE1; tr&#x1ECB; x l&#xE0; true ho&#x1EB7;c &#x1B0;&#x1EDB;c l&#x1B0;&#x1EE3;ng b&#x1EB1;ng true.</li>
<li><code>expect(x).toBeFalsy()</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng gi&#xE1; tr&#x1ECB; x l&#xE0; false ho&#x1EB7;c &#x1B0;&#x1EDB;c l&#x1B0;&#x1EE3;ng b&#x1EB1;ng false.</li>
<li><code>(x).toContain(y)</code>: Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng x l&#xE0; m&#x1ED9;t chu&#x1ED7;i k&#xFD; t&#x1EF1; v&#xE0; x ch&#x1EE9;a gi&#xE1; tr&#x1ECB; y (chu&#x1ED7;i y l&#xE0; m&#x1ED9;t ph&#x1EA7;n c&#x1EE7;a chu&#x1ED7;i x).</li>
<li><code>expect(x)</code>.toBeGreaterThan(y): Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng x l&#x1EDB;n h&#x1A1;n y.</li>
<li><code>expect(x)</code>toBeDefined(): Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng bi&#x1EBF;n x &#x111;&#xE3; &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ECB;nh ngh&#x129;a.</li>
<li><code>expect(x)</code>.toBeUndefined(): Kh&#x1EB3;ng &#x111;&#x1ECB;nh r&#x1EB1;ng bi&#x1EBF;n x ch&#x1B0;a &#x111;&#x1B0;&#x1EE3;c &#x111;&#x1ECB;nh ngh&#x129;a. `</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>