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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  17. ʮJavaScript ςετʯ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  38. 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 full-size slide

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

    View full-size slide

  40. ςετࣦഊ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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


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

    ཁૉ1

    View full-size slide

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

    ཁૉ1
    ཁૉ2


    ཁૉ1

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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



    View full-size slide

  68. JSΛ࣮ߦͯ͠ςετ



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


    ཁૉ1


    View full-size slide

  69. 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 full-size slide

  70. 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 full-size slide

  71. 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  81. // 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 full-size slide



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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide