Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
一から始めるJavaScriptユニットテスト/js-unit-test-from-scratch
Search
shibayu36
December 03, 2016
Technology
33k
8
Share
一から始めるJavaScriptユニットテスト/js-unit-test-from-scratch
buiderscon tokyo 2016で発表した資料です
shibayu36
December 03, 2016
More Decks by shibayu36
See All by shibayu36
顧客との商談議事録をみんなで読んで顧客解像度を上げよう
shibayu36
0
1k
QAフローを最適化し、品質水準を満たしながらリリースまでの期間を最短化する #RSGT2026
shibayu36
2
5.3k
EMこそClaude Codeでコード調査しよう
shibayu36
0
1.2k
詳しくない分野でのVibe Codingで困ったことと学び/vibe-coding-in-unfamiliar-area
shibayu36
3
5.9k
個人CLAUDE.md紹介と設定から学んだこと/introduce-my-claude-md
shibayu36
0
2k
今の生産性改善活動で大切にしている考え方
shibayu36
8
8.8k
エンジニアメンター制度の効果的な運用を目指して/improve-mentor-system
shibayu36
27
10k
グレードイメージ具体化のため昇格理由を公開する
shibayu36
8
6k
新機能作成時に開発ブランチに細かくmergeしていく戦略/merge-strategy-for-new-feature
shibayu36
6
18k
Other Decks in Technology
See All in Technology
なぜハノーバーメッセに行くべきなのか 〜初参加だから語れること〜
tanakaseiya
0
190
Kiro CLI v2.0.0がやってきた!
kentapapa
0
230
AIが変えた"品質の守り方"
kkakizaki
13
5.5k
エンジニアは生成AIと どのように向き合うべきか? ことばの意味という観点から
verypluming
3
300
GitHub Copilot CLIでWebアクセシビリティを改善した話
tomokusaba
0
140
AI Adaptable なテストを整える工夫 / Ways to Make Your Tests AI-Adaptable
bitkey
PRO
2
180
テストコードのないプロジェクトにテストを根付かせる
tttol
0
230
AI時代の私の技術インプットとアウトプット術
tonkotsuboy_com
15
8k
React、まだ楽しくて草
uhyo
4
580
大学生が本気でDatabricksを活用してDiscordサークルをデータ駆動させてみた
phantomjuju
1
300
OpenID Connectによるサービス間連携
takesection
0
150
脅威をエンジニアリングの糧にして:恐怖を乗り越えた先にあったもの / Turn threats into fuel for engineering: what lay beyond overcoming fear
nrslib
1
360
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
A designer walks into a library…
pauljervisheath
211
24k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
390
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
Bash Introduction
62gerente
615
210k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.5k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How GitHub (no longer) Works
holman
316
150k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
580
Transcript
Ұ͔Β࢝ΊΔ JavaScriptϢχοτςετ 2016/12/03 builderscon shiba_yu36
ࣗݾհ • @shiba_yu36 • ͘͠shibayu36 • גࣜձࣾͯͳ • খઆߘαΠτʮΧΫϤϜʯ
ͷJSڥ
ΧΫϤϜͷJSڥ • MVPΞʔΩςΫνϟ • ίϯϙʔωϯτ͝ͱʹϑΝΠϧΛࡉׂ͔͘ • ϑϨʔϜϫʔΫͳ͠ɻDOMૢ࡞jQuery • ReactͳͲʹઓ͠ͳ͔ͬͨ
࠷ॳʹ৺ʹܾΊͨ͜ͱ • શJSϑΝΠϧʹϢχοτςετΛॻ͘։ൃΛ͍ͨ͠ • ࣮ࡍͷΞϓϦέʔγϣϯαʔόͳ͠Ͱͷςετ • ϑϩϯτΤϯυͰఘΊͨ͘ͳ͍
࠷ॳʹ৺ʹܾΊͨ͜ͱ • શJSϑΝΠϧʹϢχοτςετΛॻ͘։ൃΛ͍ͨ͠ • ࣮ࡍͷΞϓϦέʔγϣϯαʔόͳ͠Ͱͷςετ • ϑϩϯτΤϯυͰఘΊͨ͘ͳ͍ ୭Ͱ؆୯ʹςετͰ͖Δ ڥ࡞ΓΛ࢝Ίͨ
ݱࡏͲ͏ͳ͔ͬͨ • શͯͷϑΝΠϧʹϢχοτςετ͕ଘࡏ • ௨ৗͷ͔ؔΒɺDOMૢ࡞ͷ͋Δػೳ·Ͱ • timerɾajaxɾlocalStorageͳͲʹؔΘΔػೳʹ
ϢχοτςετͰಘΒΕͨޮೳ ҆৺ײ ։ൃ ݁߹࣌Ҏ֎ ϒϥβݟͳ͍ͷͰ
͔͠͠… • ڥ༻ҙͷͨΊɺ࠷ॳʹௐΔ͜ͱɾΔ͜ͱ ͕ଟ͔ͬͨ • πʔϧἧ͍ͬͯΔ͕ɺͲ͏͑Α͍͔Θ͔ Γʹ͍͘
͔͠͠… • ڥ༻ҙͷͨΊɺ࠷ॳʹௐΔ͜ͱɾΔ͜ͱ ͕ଟ͔ͬͨ • πʔϧἧ͍ͬͯΔ͕ɺͲ͏͑Α͍͔Θ͔ Γʹ͍͘ ಋೖͷෑډ͕ߴ͍ʂʂʂʂ
ࠓ͍ͨ͜͠ͱ • ϢχοτςετڥΛ࡞ͬͨํ๏Λɺγϯϓϧͳ ྫΛͬͯհ • JSςετͷಋೖͷෑډΛԼ͛ΒΕͨΒ
ࠓ͞ͳ͍͜ͱ • E2Eςετ • ಛఆϑϨʔϜϫʔΫʹґଘͨ͠ςετํ๏ • ReactɺAngular • ࠓճͷํ๏ͰͰ͖Δ͔ʁ
ΞδΣϯμ •JSͷςετπʔϧΛཧ͢Δ •௨ৗͷؔͷϢχοτςετ •DOMૢ࡞͢ΔػೳͷϢχοτςετ •ͦͷଞ༷ʑͳػೳͷςετ
ΞδΣϯμ •JSͷςετπʔϧΛཧ͢Δ •௨ৗͷؔͷϢχοτςετ •DOMૢ࡞͢ΔػೳͷϢχοτςετ •ͦͷଞ༷ʑͳػೳͷςετ
ΞδΣϯμ •JSͷςετπʔϧΛཧ͢Δ •௨ৗͷؔͷϢχοτςετ •DOMૢ࡞͢ΔػೳͷϢχοτςετ
JSͷςετπʔϧΛ ཧ͢Δ
JSͷϢχοτςετ ڥΛ࡞Δͧʂʂ
ʮJavaScript ςετʯ
assert chai Mocha Karma power-assert Jasmine Sinon.js
assert chai Mocha Karma power-assert Jasmine Sinon.js ʁʁʁʁ
ׂ͝ͱʹཧ͠Α͏
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc ಉҰׂͷͷ࠷େ̍ͭͣͭ
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc πʔϧඞཁͳͷΛਵ࣌
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc ຊൃදͰ͜ͷࡾͭΛબ
ΞδΣϯμ •JSͷςετπʔϧΛཧ͢Δ •௨ৗͷؔͷϢχοτςετ •DOMૢ࡞͢ΔػೳͷϢχοτςετ
͔͜͜ΒίʔυΛ͍·͢ • Github: shibayu36/bcon-js-unit-test • src/js/ʹ࣮ɺsrc/js/test/ʹςετ • ޙͰࢀরͯ͠Έ͍ͯͩ͘͞
௨ৗͷؔͷϢχοτςετ branch: assert-mocha PR#1
ςετ͍࣮ͨ͠ function addNumber(num1, num2) { return num1 + num2; }
export { addNumber } src/js/number-util.js
addNumberͷϢχοτςετΛ ࡞ΕΔΑ͏ʹ͠·͠ΐ͏
Ξαʔγϣϯ ʮ˓˓ʯʮxxʯͰ͋Δ assert, chai, power-assert ϑϨʔϜϫʔΫ ςετ࣮ߦ& ศརΩοτҰࣜ Mocha, Jasmine
ςετϥϯφʔ ϒϥβΛհͨ͠ςετ Karma ςετπʔϧ ༻్ʹԠͯ͡ Sinon.js, etc ؔͷςετ -> ΞαʔγϣϯͱϑϨʔϜϫʔΫ
assert • ΞαʔγϣϯϥΠϒϥϦͷதͰҰ൪γϯϓϧ • assert.equal(num, 3, ‘ࣈ͕ਖ਼͍͠’) • deepEqual, throws
• https://www.npmjs.com/package/assert
Mocha • ςετ࣮ߦίϚϯυmocha • ग़ྗܗࣜΓସ͑(ਓ༻, CI༻, etc) • describe, itʹΑΔςετͷάϧʔϐϯά
• ͦͷଞςετศརΩοτҰࣜ
Πϯετʔϧ $ npm install assert $ npm install mocha
babelͷढറ $ npm install babel-preset-es2015 $ npm install babel-register {
"presets": ["es2015"] } .babelrc
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
ςετΛ࣮ߦ͢Δ $(npm bin)/mocha --require babel-register src/js/test/*.js
σϞ
ςετޭ
ςετࣦഊ
assert ςετJS ࣮JS mochaίϚϯυ ݁Ռग़ྗ ݱࡏͷςετڥ mocha src/js/test/*.js
௨ৗͷؔͷϢχοτ ςετڥΛ࡞Ͱ͖ͨ
͍ΘΏΔModelͷςετ ͜͜·ͰͷڥͰςετͰ͖Δ
ΞδΣϯμ •JSͷςετπʔϧΛཧ͢Δ •௨ৗͷؔͷϢχοτςετ •DOMૢ࡞͢ΔػೳͷϢχοτςετ
DOMૢ࡞͢Δػೳͷ Ϣχοτςετ
DOMૢ࡞͢Δػೳ • Web։ൃΛ͍ͬͯΔͱDOMૢ࡞ආ͚ΒΕͳ͍ • શϑΝΠϧςετͷͨΊɺ͜ͷΑ͏ͳ࣌ςετ ͍ͨ͠
୯७ͳྫ: ϦετʹՃ͢Δػೳ <ul class=“list”> </ul> ul = document.querySelector(‘.list’); appendList(ul, ‘ཁૉ1’);
<ul class=“list”> <li>ཁૉ1</li> </ul>
appendList(ul, ‘ཁૉ2’); <ul class=“list”> <li>ཁૉ1</li> <li>ཁૉ2</li> </ul> <ul class=“list”> <li>ཁૉ1</li>
</ul> ୯७ͳྫ: ϦετʹՃ͢Δػೳ
src/js/append-list.js function appendList(ul, text) { let li = document.createElement('li'); li.textContent
= text; ul.appendChild(li); } export { appendList }
2ͭͷ՝ • Ͳ͏ͬͯDOMૢ࡞Ͱ͖ΔϒϥβͰςετ Λಈ͔͔͢ • Ͳ͏ͬͯػೳΛ୯ମͰςετ͢Δ͔ • ࣮ࡍͷHTMLΛ৴͢ΔαʔόʔΛΘͣʹ
2ͭͷ՝ • Ͳ͏ͬͯDOMૢ࡞Ͱ͖ΔϒϥβͰςετ Λಈ͔͔͢ • Ͳ͏ͬͯػೳΛ୯ମͰςετ͢Δ͔ • ࣮ࡍͷHTMLΛ৴͢ΔαʔόʔΛΘͣʹ
Ͳ͏ͬͯDOMૢ࡞Ͱ͖Δ ϒϥβͰςετΛಈ͔͔͢ ςετϥϯφʔͷKarmaͰղܾ
Karma • CUIίϚϯυ͚ͩͰɺDOM APIͷ͋Δϒϥβ Λհͯ͠ςετ࣮ߦ • ϒϥβͰςετΛ͢ΔͨΊʹɺલॲཧͳͲͷ ػೳఏڙͯ͘͠ΕΔ
ग़ྗ ग़ྗ ग़ྗ લॲཧ ςετJS ίϚϯυ ࣮ߦ
KarmaΛͬͯaddNumberͷ ςετΛϒϥβͰಈ͔͠·͠ΐ͏ branch: karma PR#2
ࠓճChromeͰ ग़ྗ ग़ྗ ग़ྗ લॲཧ ςετJS ίϚϯυ ࣮ߦ
Πϯετʔϧ $ npm install karma $ npm install karma-browserify browserify
babelify watchify $ npm install karma-chrome-launcher $ npm install karma-mocha
Πϯετʔϧ $ npm install karma $ npm install karma-browserify browserify
babelify watchify $ npm install karma-chrome-launcher $ npm install karma-mocha લॲཧ༻ ϒϥβͭͳ͗ࠐΈ ςετϑϨʔϜϫʔΫͭͳ͗ࠐΈ
ॳظઃఆ • $(npm bin)/karma init • ࣭ʹ͍͑ͯ͘ͱɺkarma.conf.js͕Ͱ͖Δ • karma.conf.jsΛฤू •
ϑϨʔϜϫʔΫɺલॲཧɺϒϥβઃఆ
// ϑϨʔϜϫʔΫઃఆ frameworks: ['mocha', 'browserify'], // ςετϑΝΠϧॴ files: [ 'src/js/test/*.js'
], karma.conf.js
// લॲཧઃఆ preprocessors: { 'src/js/test/*.js': ['browserify'] }, browserify: { transform:
['babelify'], }, // ར༻͢Δϒϥβઃఆ browsers: ['Chrome'],
࣮ߦ͢Δ $(npm bin)/karma start
ςετΛϒϥβܦ༝Ͱ ಈ͔ͤͨ
2ͭͷ՝ • Ͳ͏ͬͯDOM APIͷ͋ΔϒϥβͰςετΛ ಈ͔͔͢ • Ͳ͏ͬͯػೳΛ୯ମͰςετ͢Δ͔ • ࣮ࡍͷαʔόʔΛΘͣʹ
Ͳ͏ͬͯػೳΛ ୯ମͰςετ͢Δ͔ branch: dom-api-unit-test PR#3
ΞΠσΞ • ػೳʹඞཁͳ࠷খݶͷHTMLஅยΛಡΈࠐΉ • JSΛ࣮ߦ͠ͳ͕ΒɺHTMLߏͷมԽ͕ҙਤ ௨Γ͔͔֬ΊΔ
ςετલʹ࠷খݶͷHTMLΛ༻ҙ <html><body> <ul class=“list”></ul> </body></html>
JSΛ࣮ߦͯ͠ςετ <html><body> <ul class=“list”></ul> </body></html> ul = document.querySelector(‘.list’); appendList(ul, ‘ཁૉ1’);
<html><body> <ul class=“list”> <li>ཁૉ1</li> </ul> </body></html>
import assert from 'assert'; import { appendList } from '../append-list';
document.body.innerHTML = '<ul class="list"></ul>'; 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
import assert from 'assert'; import { appendList } from '../append-list';
document.body.innerHTML = '<ul class="list"></ul>'; 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ΛೖΕΔ
import assert from 'assert'; import { appendList } from '../append-list';
document.body.innerHTML = '<ul class="list"></ul>'; 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Λ࣮ߦ͠ཁૉΛ͔֬ΊΔ
import assert from 'assert'; import { appendList } from '../append-list';
document.body.innerHTML = '<ul class="list"></ul>'; 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
࣮ߦ͢Δ $(npm bin)/karma start
DOMૢ࡞͢Δػೳ ςετͰ͖ͨ
HTMLஅย͕ڊେͩͱςετ͕Ԛ͘… Ұ͚ͭͩ
document.body.innerHTML = '<button id="modal-panel-open-buton">ϞʔμϧදࣔϘ λϯ</button><div class="modal- container"><div class="model-panel">Ϟʔμ ϧͷ༰<button>Ϟʔμϧด͡ΔϘλϯ</ button></div></div>';
document.body.innerHTML = '<button id="modal-panel-open-buton">ϞʔμϧදࣔϘ λϯ</button><div class="modal- container"><div class="model-panel">Ϟʔμ ϧͷ༰<button>Ϟʔμϧด͡ΔϘλϯ</ button></div></div>';
HTMLஅย͕ڊେͩͱςετ͕Ԛ͘… karma-html2js-preprocessor Ұ͚ͭͩ
karma-html2js-preprocessor • karmaͷલॲཧϓϥάΠϯ • HTMLஅยΛϑΝΠϧͰஔ͍͓ͯ͘ͱɺ ؆୯ʹಡΈࠐΈͰ͖Δπʔϧ
Πϯετʔϧ $ npm install karma-html2js-preprocessor
// htmlՃ files: [ 'src/js/test/*.js', 'src/js/test/*.html' ], // લॲཧઃఆʹϓϥάΠϯՃ preprocessors:
{ 'src/js/test/*.js': ['browserify'], 'src/js/test/*.html': ['html2js'] }, karma.conf.js
<ul class="list"> </ul> src/js/test/append-list.html
document.body.innerHTML = __html__['src/js/test/append-list.html']; __html__[‘ϑΝΠϧ໊’]ͰಡΈࠐΊΔΑ͏ʹ
HTMLஅย͕େ͖ͯ͘ ςετ͕Ԛ͘ͳΔ͜ͱ͕ͳ͘ͳͬͨ
σϞ
௨ৗͷؔɺDOMૢ࡞ͷ͋Δػೳ ςετΛ࡞ΕΔڥ͕ʂ ࣮ߦkarma start͚ͩ
CIͰಈ͔͍ͨ͠ • ϒϥβʹphantomjsjsdomΛ͏ • jsdomnode͚ͩͰಈ͘ϔουϨεϒϥβ • --reportersͷࢦఆͰCI༻ͷग़ྗ͕Ͱ͖Δ
ςετJS ࣮JS ςετHTML html2js ࠷ऴߏ karma start
࠷ऴߏ ग़ྗ ग़ྗ ग़ྗ html2js
·ͱΊ • ϢχοτςετڥΛҰ͔Βಋೖ͢Δํ๏ • ௨ৗͷؔͷςετͳΒassert + MochaͰ
·ͱΊ • DOMૢ࡞͢ΔػೳͷςετͳΒɺKarma + HTMLஅยಡΈࠐΈͰ • timerɺajaxɺlocalStorageͳͲͷςετผͷػ ձʹ • 12/5ͷͯͳΤϯδχΞΞυϕϯτΧϨϯμʔͰॻ͖·͢
JSͷϢχοτςετڥ Ұ௨ΓἧͬͨͷͰ͋ͱ͍͖ͬͯ·͠ΐ͏ʂ