Upgrade to Pro — share decks privately, control downloads, hide ads and more …

一から始めるJavaScriptユニットテスト/js-unit-test-from-scratch

shibayu36
December 03, 2016

 一から始めるJavaScriptユニットテスト/js-unit-test-from-scratch

buiderscon tokyo 2016で発表した資料です

shibayu36

December 03, 2016
Tweet

More Decks by shibayu36

Other Decks in Technology

Transcript

  1. Ұ͔Β࢝ΊΔ
    JavaScriptϢχοτςετ
    2016/12/03 builderscon
    shiba_yu36

    View Slide

  2. ࣗݾ঺հ
    • @shiba_yu36
    • ΋͘͠͸shibayu36
    • גࣜձࣾ͸ͯͳ
    • খઆ౤ߘαΠτʮΧΫϤϜʯ

    View Slide

  3. ͷJS؀ڥ

    View Slide

  4. ΧΫϤϜͷJS؀ڥ
    • MVPΞʔΩςΫνϟ
    • ίϯϙʔωϯτ͝ͱʹϑΝΠϧΛࡉ͔͘෼ׂ
    • ϑϨʔϜϫʔΫ͸ͳ͠ɻDOMૢ࡞͸jQuery
    • ReactͳͲʹ௅ઓ͸͠ͳ͔ͬͨ

    View Slide

  5. ࠷ॳʹ৺ʹܾΊͨ͜ͱ
    • શJSϑΝΠϧʹϢχοτςετΛॻ͘։ൃΛ͍ͨ͠
    • ࣮ࡍͷΞϓϦέʔγϣϯαʔόͳ͠Ͱͷςετ
    • ϑϩϯτΤϯυͰ΋ఘΊͨ͘ͳ͍

    View Slide

  6. ࠷ॳʹ৺ʹܾΊͨ͜ͱ
    • શJSϑΝΠϧʹϢχοτςετΛॻ͘։ൃΛ͍ͨ͠
    • ࣮ࡍͷΞϓϦέʔγϣϯαʔόͳ͠Ͱͷςετ
    • ϑϩϯτΤϯυͰ΋ఘΊͨ͘ͳ͍
    ୭Ͱ΋؆୯ʹςετͰ͖Δ
    ؀ڥ࡞ΓΛ࢝Ίͨ

    View Slide

  7. ݱࡏͲ͏ͳ͔ͬͨ
    • શͯͷϑΝΠϧʹϢχοτςετ͕ଘࡏ
    • ௨ৗͷؔ਺͔ΒɺDOMૢ࡞ͷ͋Δػೳ·Ͱ
    • timerɾajaxɾlocalStorageͳͲʹؔΘΔػೳʹ΋

    View Slide

  8. ϢχοτςετͰಘΒΕͨޮೳ
    ҆৺ײ ։ൃ଎౓
    ݁߹࣌Ҏ֎
    ϒϥ΢βݟͳ͍ͷͰ

    View Slide

  9. ͔͠͠…
    • ؀ڥ༻ҙͷͨΊɺ࠷ॳʹௐ΂Δ͜ͱɾ΍Δ͜ͱ
    ͕ଟ͔ͬͨ
    • πʔϧ͸ἧ͍ͬͯΔ͕ɺͲ͏࢖͑͹Α͍͔Θ͔
    Γʹ͍͘

    View Slide

  10. ͔͠͠…
    • ؀ڥ༻ҙͷͨΊɺ࠷ॳʹௐ΂Δ͜ͱɾ΍Δ͜ͱ
    ͕ଟ͔ͬͨ
    • πʔϧ͸ἧ͍ͬͯΔ͕ɺͲ͏࢖͑͹Α͍͔Θ͔
    Γʹ͍͘
    ಋೖͷෑډ͕ߴ͍ʂʂʂʂ

    View Slide

  11. ࠓ೔࿩͍ͨ͜͠ͱ
    • Ϣχοτςετ؀ڥΛ࡞ͬͨํ๏Λɺγϯϓϧͳ
    ྫΛ࢖ͬͯ঺հ
    • JSςετͷಋೖͷෑډΛԼ͛ΒΕͨΒ

    View Slide

  12. ࠓ೔࿩͞ͳ͍͜ͱ
    • E2Eςετ
    • ಛఆϑϨʔϜϫʔΫʹґଘͨ͠ςετํ๏
    • ReactɺAngular
    • ࠓճͷํ๏Ͱ΋Ͱ͖Δ͔΋ʁ

    View Slide

  13. ΞδΣϯμ
    •JSͷςετπʔϧΛ੔ཧ͢Δ
    •௨ৗͷؔ਺ͷϢχοτςετ
    •DOMૢ࡞͢ΔػೳͷϢχοτςετ
    •ͦͷଞ༷ʑͳػೳͷςετ

    View Slide

  14. ΞδΣϯμ
    •JSͷςετπʔϧΛ੔ཧ͢Δ
    •௨ৗͷؔ਺ͷϢχοτςετ
    •DOMૢ࡞͢ΔػೳͷϢχοτςετ
    •ͦͷଞ༷ʑͳػೳͷςετ

    View Slide

  15. ΞδΣϯμ
    •JSͷςετπʔϧΛ੔ཧ͢Δ
    •௨ৗͷؔ਺ͷϢχοτςετ
    •DOMૢ࡞͢ΔػೳͷϢχοτςετ

    View Slide

  16. JSͷςετπʔϧΛ
    ੔ཧ͢Δ

    View Slide

  17. JSͷϢχοτςετ
    ؀ڥΛ࡞Δͧʂʂ

    View Slide

  18. ʮJavaScript ςετʯ

    View Slide

  19. assert chai
    Mocha
    Karma
    power-assert
    Jasmine
    Sinon.js

    View Slide

  20. assert chai
    Mocha
    Karma
    power-assert
    Jasmine
    Sinon.js
    ʁʁʁʁ

    View Slide

  21. ໾ׂ͝ͱʹ੔ཧ͠Α͏

    View Slide

  22. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc

    View Slide

  23. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
    ಉҰ໾ׂͷ΋ͷ͸࠷େ̍ͭͣͭ

    View Slide

  24. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
    πʔϧ͸ඞཁͳ΋ͷΛਵ࣌

    View Slide

  25. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc

    View Slide

  26. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc

    View Slide

  27. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc

    View Slide

  28. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
    ຊൃදͰ͸͜ͷࡾͭΛબ୒

    View Slide

  29. ΞδΣϯμ
    •JSͷςετπʔϧΛ੔ཧ͢Δ
    •௨ৗͷؔ਺ͷϢχοτςετ
    •DOMૢ࡞͢ΔػೳͷϢχοτςετ

    View Slide

  30. ͔͜͜Β͸ίʔυΛ࢖͍·͢
    • Github: shibayu36/bcon-js-unit-test
    • src/js/ʹ࣮૷ɺsrc/js/test/ʹςετ
    • ޙͰࢀরͯ͠Έ͍ͯͩ͘͞

    View Slide

  31. ௨ৗͷؔ਺ͷϢχοτςετ
    branch: assert-mocha
    PR#1

    View Slide

  32. ςετ͍࣮ͨ͠૷
    function addNumber(num1, num2) {
    return num1 + num2;
    }
    export { addNumber }
    src/js/number-util.js

    View Slide

  33. addNumberͷϢχοτςετΛ
    ࡞ΕΔΑ͏ʹ͠·͠ΐ͏

    View Slide

  34. Ξαʔγϣϯ ʮ˓˓ʯ͸ʮxxʯͰ͋Δ
    assert, chai,
    power-assert
    ϑϨʔϜϫʔΫ
    ςετ࣮ߦ&
    ศརΩοτҰࣜ
    Mocha, Jasmine
    ςετϥϯφʔ ϒϥ΢βΛհͨ͠ςετ Karma
    ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
    ؔ਺ͷςετ -> ΞαʔγϣϯͱϑϨʔϜϫʔΫ

    View Slide

  35. assert
    • ΞαʔγϣϯϥΠϒϥϦͷதͰҰ൪γϯϓϧ
    • assert.equal(num, 3, ‘਺ࣈ͕ਖ਼͍͠’)
    • deepEqual, throws
    • https://www.npmjs.com/package/assert

    View Slide

  36. Mocha
    • ςετ࣮ߦίϚϯυmocha
    • ग़ྗܗࣜ੾Γସ͑(ਓ༻, CI༻, etc)
    • describe, itʹΑΔςετͷάϧʔϐϯά
    • ͦͷଞςετศརΩοτҰࣜ

    View Slide

  37. Πϯετʔϧ
    $ npm install assert
    $ npm install mocha

    View Slide

  38. babelͷढറ
    $ npm install babel-preset-es2015
    $ npm install babel-register
    {
    "presets": ["es2015"]
    }
    .babelrc

    View Slide

  39. import assert from 'assert';
    import { addNumber } from "../number-util";
    describe('addNumber', function () {
    it('଍͠ࢉͰ͖Δ', function () {
    assert.equal(addNumber(1, 2), 3, '1 + 2 = 3');
    });
    });
    ςετΛॻ͘
    src/js/test/number-util.js

    View Slide

  40. ςετΛ࣮ߦ͢Δ
    $(npm bin)/mocha --require babel-register src/js/test/*.js

    View Slide

  41. σϞ

    View Slide

  42. ςετ੒ޭ

    View Slide

  43. ςετࣦഊ

    View Slide

  44. assert
    ςετJS
    ࣮૷JS
    mochaίϚϯυ ݁Ռग़ྗ
    ݱࡏͷςετ؀ڥ
    mocha src/js/test/*.js

    View Slide

  45. ௨ৗͷؔ਺ͷϢχοτ
    ςετ؀ڥΛ࡞੒Ͱ͖ͨ

    View Slide

  46. ͍ΘΏΔModel૚ͷςετ͸
    ͜͜·Ͱͷ؀ڥͰςετͰ͖Δ

    View Slide

  47. ΞδΣϯμ
    •JSͷςετπʔϧΛ੔ཧ͢Δ
    •௨ৗͷؔ਺ͷϢχοτςετ
    •DOMૢ࡞͢ΔػೳͷϢχοτςετ

    View Slide

  48. DOMૢ࡞͢Δػೳͷ
    Ϣχοτςετ

    View Slide

  49. DOMૢ࡞͢Δػೳ
    • Web։ൃΛ΍͍ͬͯΔͱDOMૢ࡞͸ආ͚ΒΕͳ͍
    • શϑΝΠϧςετͷͨΊɺ͜ͷΑ͏ͳ࣌΋ςετ͸
    ͍ͨ͠

    View Slide

  50. ୯७ͳྫ: Ϧετʹ௥Ճ͢Δػೳ


    ul = document.querySelector(‘.list’);
    appendList(ul, ‘ཁૉ1’);

    ཁૉ1

    View Slide

  51. appendList(ul, ‘ཁૉ2’);

    ཁૉ1
    ཁૉ2


    ཁૉ1

    ୯७ͳྫ: Ϧετʹ௥Ճ͢Δػೳ

    View Slide

  52. src/js/append-list.js
    function appendList(ul, text) {
    let li = document.createElement('li');
    li.textContent = text;
    ul.appendChild(li);
    }
    export { appendList }

    View Slide

  53. 2ͭͷ՝୊
    • Ͳ͏΍ͬͯDOMૢ࡞Ͱ͖Δϒϥ΢βͰςετ
    Λಈ͔͔͢
    • Ͳ͏΍ͬͯػೳΛ୯ମͰςετ͢Δ͔
    • ࣮ࡍͷHTMLΛ഑৴͢ΔαʔόʔΛ࢖Θͣʹ

    View Slide

  54. 2ͭͷ՝୊
    • Ͳ͏΍ͬͯDOMૢ࡞Ͱ͖Δϒϥ΢βͰςετ
    Λಈ͔͔͢
    • Ͳ͏΍ͬͯػೳΛ୯ମͰςετ͢Δ͔
    • ࣮ࡍͷHTMLΛ഑৴͢ΔαʔόʔΛ࢖Θͣʹ

    View Slide

  55. Ͳ͏΍ͬͯDOMૢ࡞Ͱ͖Δ
    ϒϥ΢βͰςετΛಈ͔͔͢
    ςετϥϯφʔͷKarmaͰղܾ

    View Slide

  56. Karma
    • CUIίϚϯυ͚ͩͰɺDOM APIͷ͋Δϒϥ΢β
    Λհͯ͠ςετ࣮ߦ
    • ϒϥ΢βͰςετΛ͢ΔͨΊʹɺલॲཧͳͲͷ
    ػೳ΋ఏڙͯ͘͠ΕΔ

    View Slide

  57. ग़ྗ
    ग़ྗ
    ग़ྗ
    લॲཧ
    ςετJS ίϚϯυ
    ࣮ߦ

    View Slide

  58. KarmaΛ࢖ͬͯaddNumberͷ
    ςετΛϒϥ΢βͰಈ͔͠·͠ΐ͏
    branch: karma
    PR#2

    View Slide

  59. ࠓճ͸ChromeͰ
    ग़ྗ
    ग़ྗ
    ग़ྗ
    લॲཧ
    ςετJS ίϚϯυ
    ࣮ߦ

    View Slide

  60. Πϯετʔϧ
    $ npm install karma
    $ npm install karma-browserify browserify babelify watchify
    $ npm install karma-chrome-launcher
    $ npm install karma-mocha

    View Slide

  61. Πϯετʔϧ
    $ npm install karma
    $ npm install karma-browserify browserify babelify watchify
    $ npm install karma-chrome-launcher
    $ npm install karma-mocha
    લॲཧ༻
    ϒϥ΢βͭͳ͗ࠐΈ
    ςετϑϨʔϜϫʔΫͭͳ͗ࠐΈ

    View Slide

  62. ॳظઃఆ
    • $(npm bin)/karma init
    • ࣭໰ʹ౴͍͑ͯ͘ͱɺkarma.conf.js͕Ͱ͖Δ
    • karma.conf.jsΛฤू
    • ϑϨʔϜϫʔΫɺલॲཧɺϒϥ΢βઃఆ

    View Slide

  63. // ϑϨʔϜϫʔΫઃఆ
    frameworks: ['mocha', 'browserify'],
    // ςετϑΝΠϧ৔ॴ
    files: [
    'src/js/test/*.js'
    ],
    karma.conf.js

    View Slide

  64. // લॲཧઃఆ
    preprocessors: {
    'src/js/test/*.js': ['browserify']
    },
    browserify: {
    transform: ['babelify'],
    },
    // ར༻͢Δϒϥ΢βઃఆ
    browsers: ['Chrome'],

    View Slide

  65. ࣮ߦ͢Δ
    $(npm bin)/karma start

    View Slide

  66. ςετΛϒϥ΢βܦ༝Ͱ
    ಈ͔ͤͨ

    View Slide

  67. 2ͭͷ՝୊
    • Ͳ͏΍ͬͯDOM APIͷ͋Δϒϥ΢βͰςετΛ
    ಈ͔͔͢
    • Ͳ͏΍ͬͯػೳΛ୯ମͰςετ͢Δ͔
    • ࣮ࡍͷαʔόʔΛ࢖Θͣʹ

    View Slide

  68. Ͳ͏΍ͬͯػೳΛ
    ୯ମͰςετ͢Δ͔
    branch: dom-api-unit-test
    PR#3

    View Slide

  69. ΞΠσΞ
    • ػೳʹඞཁͳ࠷খݶͷHTMLஅยΛಡΈࠐΉ
    • JSΛ࣮ߦ͠ͳ͕ΒɺHTMLߏ଄ͷมԽ͕ҙਤ
    ௨Γ͔͔֬ΊΔ

    View Slide

  70. ςετલʹ࠷খݶͷHTMLΛ༻ҙ



    View Slide

  71. JSΛ࣮ߦͯ͠ςετ



    ul = document.querySelector(‘.list’);
    appendList(ul, ‘ཁૉ1’);


    ཁૉ1


    View Slide

  72. import assert from 'assert';
    import { appendList } from '../append-list';
    document.body.innerHTML = '';
    let ul = document.querySelector('.list');
    assert.equal(ul.children.length, 0, '࠷ॳ͸0݅');
    appendList(ul, 'ཁૉ1');
    assert.equal(ul.children.length, 1, '݅਺͕1݅ʹ');
    assert.equal(ul.children[0].textContent, 'ཁૉ1');
    src/js/test/append-list.js

    View Slide

  73. import assert from 'assert';
    import { appendList } from '../append-list';
    document.body.innerHTML = '';
    let ul = document.querySelector('.list');
    assert.equal(ul.children.length, 0, '࠷ॳ͸0݅');
    appendList(ul, 'ཁૉ1');
    assert.equal(ul.children.length, 1, '݅਺͕1݅ʹ');
    assert.equal(ul.children[0].textContent, 'ཁૉ1');
    src/js/test/append-list.js
    ςετલʹHTMLΛೖΕΔ

    View Slide

  74. import assert from 'assert';
    import { appendList } from '../append-list';
    document.body.innerHTML = '';
    let ul = document.querySelector('.list');
    assert.equal(ul.children.length, 0, '࠷ॳ͸0݅');
    appendList(ul, 'ཁૉ1');
    assert.equal(ul.children.length, 1, '݅਺͕1݅ʹ');
    assert.equal(ul.children[0].textContent, 'ཁૉ1');
    src/js/test/append-list.js
    JSΛ࣮ߦ͠ཁૉΛ͔֬ΊΔ

    View Slide

  75. import assert from 'assert';
    import { appendList } from '../append-list';
    document.body.innerHTML = '';
    let ul = document.querySelector('.list');
    assert.equal(ul.children.length, 0, '࠷ॳ͸0݅');
    appendList(ul, 'ཁૉ1');
    assert.equal(ul.children.length, 1, '݅਺͕1݅ʹ');
    assert.equal(ul.children[0].textContent, 'ཁૉ1');
    src/js/test/append-list.js

    View Slide

  76. ࣮ߦ͢Δ
    $(npm bin)/karma start

    View Slide

  77. DOMૢ࡞͢Δػೳ΋
    ςετͰ͖ͨ

    View Slide

  78. HTMLஅย͕ڊେͩͱςετ͕Ԛ͘…
    Ұ͚ͭͩ໰୊

    View Slide

  79. document.body.innerHTML = 'id="modal-panel-open-buton">ϞʔμϧදࣔϘ
    λϯϞʔμ
    ϧͷ಺༰Ϟʔμϧด͡ΔϘλϯ
    button>';

    View Slide

  80. document.body.innerHTML = 'id="modal-panel-open-buton">ϞʔμϧදࣔϘ
    λϯϞʔμ
    ϧͷ಺༰Ϟʔμϧด͡ΔϘλϯ
    button>';

    View Slide

  81. HTMLஅย͕ڊେͩͱςετ͕Ԛ͘…
    karma-html2js-preprocessor
    Ұ͚ͭͩ໰୊

    View Slide

  82. karma-html2js-preprocessor
    • karmaͷલॲཧϓϥάΠϯ
    • HTMLஅยΛϑΝΠϧͰஔ͍͓ͯ͘ͱɺ
    ؆୯ʹಡΈࠐΈͰ͖Δπʔϧ

    View Slide

  83. Πϯετʔϧ
    $ npm install karma-html2js-preprocessor

    View Slide

  84. // html΋௥Ճ
    files: [
    'src/js/test/*.js',
    'src/js/test/*.html'
    ],
    // લॲཧઃఆʹϓϥάΠϯ௥Ճ
    preprocessors: {
    'src/js/test/*.js': ['browserify'],
    'src/js/test/*.html': ['html2js']
    },
    karma.conf.js

    View Slide



  85. src/js/test/append-list.html

    View Slide

  86. document.body.innerHTML =
    __html__['src/js/test/append-list.html'];
    __html__[‘ϑΝΠϧ໊’]ͰಡΈࠐΊΔΑ͏ʹ

    View Slide

  87. HTMLஅย͕େ͖ͯ͘΋
    ςετ͕Ԛ͘ͳΔ͜ͱ͕ͳ͘ͳͬͨ

    View Slide

  88. σϞ

    View Slide

  89. ௨ৗͷؔ਺΋ɺDOMૢ࡞ͷ͋Δػೳ΋
    ςετΛ࡞ΕΔ؀ڥ͕׬੒ʂ
    ࣮ߦ͸karma start͚ͩ

    View Slide

  90. CIͰಈ͔͍ͨ͠
    • ϒϥ΢βʹphantomjs΍jsdomΛ࢖͏
    • jsdom͸node͚ͩͰಈ͘ϔουϨεϒϥ΢β
    • --reportersͷࢦఆͰCI༻ͷग़ྗ͕Ͱ͖Δ

    View Slide

  91. ςετJS
    ࣮૷JS
    ςετHTML
    html2js
    ࠷ऴߏ੒
    karma start

    View Slide

  92. ࠷ऴߏ੒
    ग़ྗ
    ग़ྗ
    ग़ྗ
    html2js

    View Slide

  93. ·ͱΊ
    • Ϣχοτςετ؀ڥΛҰ͔Βಋೖ͢Δํ๏
    • ௨ৗͷؔ਺ͷςετͳΒassert + MochaͰ

    View Slide

  94. ·ͱΊ
    • DOMૢ࡞͢ΔػೳͷςετͳΒɺKarma +
    HTMLஅยಡΈࠐΈͰ
    • timerɺajaxɺlocalStorageͳͲͷςετ͸ผͷػ
    ձʹ
    • 12/5ͷ͸ͯͳΤϯδχΞΞυϕϯτΧϨϯμʔͰॻ͖·͢

    View Slide

  95. JSͷϢχοτςετ؀ڥ͸
    Ұ௨ΓἧͬͨͷͰ͋ͱ͸΍͍͖ͬͯ·͠ΐ͏ʂ

    View Slide