Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Vueコンポーネントのユニットテスト
Search
hypermkt
July 07, 2017
Programming
12
16k
Vueコンポーネントのユニットテスト
Vueコンポーネントのユニットテスト
Vue.js Tokyo v-meetup #4
https://vuejs-meetup.connpass.com/event/58071/
hypermkt
July 07, 2017
Tweet
Share
More Decks by hypermkt
See All by hypermkt
プロポーザルを書くときに 私が考えていること/what-i-think-about-when-writing-a-proposal
hypermkt
0
390
履歴 on Rails: Bitemporal Data Modelで実現する履歴管理/history-on-rails-with-bitemporal-data-model
hypermkt
1
2.9k
Sidekiqで実現する 長時間非同期処理の中断と再開 / Pausing and Resuming Long-Running Asynchronous Jobs with Sidekiq
hypermkt
8
5.9k
脆弱性から学ぶ Webセキュリティ Part2/study-web-security-from-vulnerability2
hypermkt
5
3.3k
脆弱性から学ぶ Webセキュリティ/study-web-security-from-vulnerability1
hypermkt
5
2.5k
モバイルアプリ向けAPI 開発を通じて学んだこと / learned-from-developing-mobile-app-api
hypermkt
3
4.5k
Passportのパスワードグラントで独自の認証を実装する方法 / how-to-implement-original-authentication-for-passport-password-grant
hypermkt
1
820
Webpackで作る Vueコンポーネント開発環境 / Creating the Vue component development with Webpack.
hypermkt
3
4.2k
あの問題解きました! / solved the code
hypermkt
0
350
Other Decks in Programming
See All in Programming
Herb to ReActionView: A New Foundation for the View Layer @ San Francisco Ruby Conference 2025
marcoroth
0
210
仕様がそのままテストになる!Javaで始める振る舞い駆動開発
ohmori_yusuke
8
4.7k
How Software Deployment tools have changed in the past 20 years
geshan
0
25k
関数実行の裏側では何が起きているのか?
minop1205
1
310
JEP 496 と JEP 497 から学ぶ耐量子計算機暗号入門 / Learning Post-Quantum Crypto Basics from JEP 496 & 497
mackey0225
2
510
Full-Cycle Reactivity in Angular: SignalStore mit Signal Forms und Resources
manfredsteyer
PRO
0
150
なぜ強調表示できず ** が表示されるのか — Perlで始まったMarkdownの歴史と日本語文書における課題
kwahiro
12
7.4k
モダンJSフレームワークのビルドプロセス 〜なぜReactは503行、Svelteは12行なのか〜
fuuki12
0
150
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
1
190
『実践MLOps』から学ぶ DevOps for ML
nsakki55
2
490
Phronetic Team with AI - Agile Japan 2025 closing
hiranabe
2
700
2025 컴포즈 마법사
jisungbin
0
160
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
95
14k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
360
The Invisible Side of Design
smashingmag
302
51k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.2k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
8.1k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
11
950
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
253
22k
Mobile First: as difficult as doing things right
swwweet
225
10k
How to Think Like a Performance Engineer
csswizardry
28
2.3k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
15k
Transcript
όʔνʔ(.01&1"#0JOD 7VFKT.FFUVQ 7VFίϯϙʔωϯτͷ Ϣχοτςετ
ιϑτΣΞΤϯδχΞ <b1)1FS` b7VFKT` b3BJMT`> Ξχϝ෦෦ όʔνʔ!IZQFSNLU IUUQCMPHIZQFSNLUKQ
7VFίϯϙʔωϯτͷ Ϣχοτςετ
ຊͷରऀ wओʹ7VFίϯϙʔωϯτͷςετΛॻ͍͍ͯΔਓ wࠓޙ7VFίϯϙʔωϯτͷςετΛॻ͖͍ͨਓ
ίϯϙʔωϯτͷςετͰͪΐͬͱࠔΔγʔϯᶃ it('จࣈྻ͕ೖྗ͞ΕͨΒɺAPI͕1ճݺΕΔ', () => { stub = sinon.stub(api, 'checkAccount') const
Constructor = Vue.extend(Event) const vm = new Constructor().$mount() const input = vm.$el.querySelector('input') const event = document.createEvent('HTMLEvents') event.initEvent('input', true, true) input.dispatchEvent(event) expect(stub.calledOnce).to.be.true }) <template> <div> Account: <input type="text" @input="checkAccount" > </div> </template> <script> import api from '../libs/api' export default { data () { return { msg: '' } }, methods: { checkAccount: () => { api.checkAccount() } } } </script> ίϯϙʔωϯτ ςετέʔε จࣈྻೖྗ͞ΕͨΒ"1*ͰνΣοΫ͢Δ JOQVUΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ
ίϯϙʔωϯτͷςετͰͪΐͬͱࠔΔγʔϯᶄ <template> <div> <p>{{ msg }}</p> <child></child> </div> </template> <script>
import Child from './Child.vue export default { components: { 'child': Child }, data () { return { msg: ‘Hello World' } } } </script> ࢠίϯϙʔωϯτͰ)551ܦ༝ͷ "1*ΛݺΜͰ͍Δɻ ͜ͷίϯϙʔωϯτͷςετͷΈʹ ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ ͕अຐͰςετ͕ͮ͠Β͍ɻ
ͬͱ؆୯ʹ7VFίϯϙʔωϯτͷ ςετ͕ॻ͚ͳ͍ͷ͔ʁ
7VFKT༻ςετϥΠϒϥϦͩʂ
୳ͨ͠Βͨ͘͞Μ͋ͬͨ wWVFUFTU wBWPSJB[ wWVFVOJU wWVFUFTUJOH wSFWVF wWVFOJU
ొͨ࣌͠ظ͍͍ͩͨಉ͡ wWVFUFTU wBWPSJB[ wWVFVOJU wWVFUFTUJOH wSFWVF wWVFOJU
ػೳ͍͍ͩͨಉ͡ w4IBMMPX'VMM3FOEFSJOH w%0.&WFOU5SJHHFS w7VFY 3PVUFS )551ͷϞοΫελϒ w"TTFSUJPO w%0.4FMFDUPS
ެࣜͷςετϥΠϒϥϦ͕ ແ͍ͩΖ͏͔ʁ
IUUQTGPSVNWVFKTPSHUJTBOZUIJOHCFJOHEPOFJODPSFWVFUPNBLFVOJUUFTUJOHFBTJFS
WVFUFTUVUJMTͷొ
WVFUFTUVUJMTͷݱঢ় wBWPSJB[։ൃऀͷ!FEEZFSCVSHIࢯ͕ϝΠϯͰ։ൃத wWVFUFTU SFWVF WVFVOJU WVFOJUͷ։ൃ͕ҙݟΛग़ ͠߹͍ w։ൃऴ൫ɻॳظ50%0ͷׂྃ wݱࡏυΩϡϝϯτ४උத wۙʑЌ൛͕ϦϦʔε͞Εͦ͏ͳ༧ײ
࣌
WVFUFTUVUJMT ·ͩЌ൛͢ΒϦϦʔε͞Ε͍ͯͳ͍Ͱ ݱঢ়Ͱਂ͘͏ͷ࣌ظঘૣ
WVFUFTUVUJMTBWPSJB[Λ౿ऻͯ͠։ൃ͞Ε͍ͯΔɻ BWPSJB[ΛΔ͜ͱͰWVFUFTUVUJMTΛઌऔΓ͠Α͏ʂ
BWPSJB[ B7VFKTUFTUJOHVUJMJUZMJCSBSZ IUUQTHJUIVCDPNFEEZFSCVSHIBWPSJB[
BWPSJB[ͷػೳ wK2VFSZϥΠΫͳηϨΫλʔ w%0.ΠϕϯττϦΨʔ w4IBMMPX 'VMMϨϯμϦϯά
BWPSJB[ͷྑ͍ͱ͜Ζ wγϯϓϧͳ"1* wυΩϡϝϯτ͕๛ w֤ςετϥΠϒϥϦผͷαϯϓϧίʔυ๛
$PNQPOFOUͷςετख๏ w*TPMBUFE5FTUJOH w $PNQPOFOUͷϩδοΫͷΈΛςετ͢Δ w4IBMMPX5FTUJOH w ࢠίϯϙʔωϯτϨϯμϦϯάͤͣɺࣗͷ$PNQPOFOUͷΈΛϨϯμϦϯάͯ͠ςε τ͢Δ w*OUFHSBUJPO5FTUJOH w
ࢠίϯϙʔωϯτશͯϨϯμϦϯάͯ͠ςετ͢Δ w&WFOU5FTUJOH w %0.ΠϕϯτΛൃੜͤ͞ɺఆ͢ΔڍಈΛ͢Δ͔ςετ͢Δ
$PNQPOFOUͷςετख๏ w*TPMBUFE5FTUJOH w $PNQPOFOUͷϩδοΫͷΈΛςετ͢Δ w4IBMMPX5FTUJOH w ࢠίϯϙʔωϯτϨϯμϦϯάͤͣɺࣗͷ$PNQPOFOUͷΈΛϨϯμϦϯάͯ͠ςε τ͢Δ w*OUFHSBUJPO5FTUJOH w
ࢠίϯϙʔωϯτશͯϨϯμϦϯάͯ͠ςετ͢Δ w&WFOU5FTUJOH w %0.ΠϕϯτΛൃੜͤ͞ɺఆ͢ΔڍಈΛ͢Δ͔ςετ͢Δ
4IBMMPXϨϯμϦϯά
՝ <template> <div> <p>{{ msg }}</p> <child></child> </div> </template> <script>
import Child from './Child.vue export default { components: { 'child': Child }, data () { return { msg: ‘Hello World' } } } </script> ࢠίϯϙʔωϯτͰ)551ܦ༝ͷ "1*ΛݺΜͰ͍Δɻ ͜ͷίϯϙʔωϯτͷςετͷΈʹ ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ ͕अຐͰςετ͕ͮ͠Β͍ɻ
ղܾ๏ɿ4IBMMPXϨϯμϦϯάΛར༻͢Δ w4IBMMPXϨϯμϦϯάͱɺࢠίϯϙʔωϯτΛల։ ͤͣʹϨϯμϦϯά͢Δ͜ͱ wBWPSJB[ͰTIBMMPXػೳΛར༻͢Δ͜ͱͰɺશͯͷࢠ ίϯϙʔωϯτΛελϒ ʹͳΔʣͯ͠ɺϨϯμ Ϧϯάͨ͠ϥούʔΦϒδΣΫτΛฦ͢
<template> <div> <p>{{ msg }}</p> <child></child> </div> </template> <script> import
Child from './Child.vue export default { components: { 'child': Child }, data () { return { msg: ‘Hello World' } } } </script> import Welcome from ‘../../src/components/Welcome.vue’ import { shallow } from 'avoriaz' describe('avoriaz༗Γͷςετέʔε', () => { it('Pλά͕ਖ਼ৗʹϨϯμϦϯά͞Ε͍ͯΔ͔', () => { const wrapper = shallow(Welcome) expect(wrapper.find(‘p')[0].text()).to.be.eql('Hello World') }) }) ίϯϙʔωϯτ ςετέʔε TIBMMPXΛ༻ͨ͠ςετέʔε
͜ΕͰςετ͍ͨ͠ίϯϙʔωϯτ ͚ͩʹूதͰ͖Δʂʂ
*OUFHSBUJPO5FTU
՝ <template> <div> <p>{{ msg }}</p> <child></child> </div> </template> <script>
import Child from './Child.vue export default { components: { 'child': Child }, data () { return { msg: ‘Hello World' } } } </script> ࢠίϯϙʔωϯτؚΊͯը໘શମ ͕ਖ਼ৗʹϨϯμϦϯά͞Ε͍ͯΔͷ Λ֬ೝ͍ͨ͠ɻ
ղܾ๏ɿ'VMMϨϯμϦϯάΛར༻͢Δ w'VMMϨϯμϦϯάͱɺίϯϙʔωϯτશମΛϨϯμ Ϧϯά͢Δ wBWPSJB[ͰNPVOUػೳΛར༻͢Δ͜ͱͰɺ'VMMϨϯ μϦϯά͞ΕͨϥούʔΦϒδΣΫτΛऔಘͰ͖Δ
<template> <div> <p>{{ msg }}</p> <child></child> </div> </template> <script> import
Child from './Child.vue export default { components: { 'child': Child }, data () { return { msg: ‘Hello World' } } } </script> import Welcome from ‘../../src/components/Welcome.vue’ import { mount } from 'avoriaz' describe('avoriaz༗Γͷςετέʔε', () => { it('Pλά͕ਖ਼ৗʹϨϯμϦϯά͞Ε͍ͯΔ͔', () => { // mount: ϑϧϨϯμϦϯά͞ΕͨίϯϙʔωϯτͷϥούʔΦϒδΣΫτΛฦ͢ const wrapper = mount(Welcome) // find: DOMͷྻΛฦ͢ // text: ϥούʔΦϒδΣΫτͷจࣈྻίϯςϯπΛฦ͢ expect(wrapper.find(‘p')[0].text()).to.be.eql('Hello World') }) }) ίϯϙʔωϯτ ςετέʔε NPVOUΛར༻ͨ͠ςετέʔε
&WFOU5FTUJOH
՝ it('จࣈྻ͕ೖྗ͞ΕͨΒɺAPI͕1ճݺΕΔ', () => { stub = sinon.stub(api, 'checkAccount') const
Constructor = Vue.extend(Event) const vm = new Constructor().$mount() const input = vm.$el.querySelector('input') const event = document.createEvent('HTMLEvents') event.initEvent('input', true, true) input.dispatchEvent(event) expect(stub.calledOnce).to.be.true }) <template> <div> Account: <input type="text" @input="checkAccount" > </div> </template> <script> import api from '../libs/api' export default { data () { return { msg: '' } }, methods: { checkAccount: () => { api.checkAccount() } } } </script> ίϯϙʔωϯτ ςετέʔε จࣈྻೖྗ͞ΕͨΒ"1*ͰνΣοΫ͢Δ JOQVUΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ
ղܾ๏ɿUSJHHFSΛར༻͢Δ wUSJHHFS FWFOU/BNF ࢦఆͨ͠ΠϕϯτΛݺͼग़͢ ͜ͱ͕ग़དྷΔ
BWPSJB[ͩͱΠϕϯτൃੜ͕Ͱ͖Δʂ it('จࣈྻ͕ೖྗ͞ΕͨΒɺAPI͕1ճݺΕΔ', () => { stub = sinon.stub(api, 'checkAccount') const
wrapper = mount(Event) wrapper.find('input')[0].trigger('input') expect(stub.calledOnce).to.be.true })
·ͱΊ
·ͱΊ wWVFUFTUVUJMTɺ։ൃதͳͷͰࠓޙͲ͏ͳΔ͔·ͩ ͔Βͳ͍ɻ wBWPSJB[Λར༻͢Εɺ؆୯ʹίϯϙʔωϯτͷςε τ͕ॻ͚ΔΑ͏ʹͳΔɻ wBWPSJB[ͱWVFUFTUVUJMT"1*͕͍͍ͩͨಉ͡ͳͷ ͰɺΓָ͑ɻࠓ͔ΒͰBWPSJB[Λ͏ͷ༗ Γɻ