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
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
160
履歴 on Rails: Bitemporal Data Modelで実現する履歴管理/history-on-rails-with-bitemporal-data-model
hypermkt
0
2.4k
Sidekiqで実現する 長時間非同期処理の中断と再開 / Pausing and Resuming Long-Running Asynchronous Jobs with Sidekiq
hypermkt
8
5.6k
脆弱性から学ぶ Webセキュリティ Part2/study-web-security-from-vulnerability2
hypermkt
5
3.3k
脆弱性から学ぶ Webセキュリティ/study-web-security-from-vulnerability1
hypermkt
5
2.4k
モバイルアプリ向けAPI 開発を通じて学んだこと / learned-from-developing-mobile-app-api
hypermkt
3
4.4k
Passportのパスワードグラントで独自の認証を実装する方法 / how-to-implement-original-authentication-for-passport-password-grant
hypermkt
1
810
Webpackで作る Vueコンポーネント開発環境 / Creating the Vue component development with Webpack.
hypermkt
3
4.1k
あの問題解きました! / solved the code
hypermkt
0
340
Other Decks in Programming
See All in Programming
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
3
910
大規模アプリのDIフレームワーク刷新戦略 ~過去最大規模の並行開発を止めずにアプリ全体に導入するまで~
mot_techtalk
1
460
Six and a half ridiculous things to do with Quarkus
hollycummins
0
180
ALL CODE BASE ARE BELONG TO STUDY
uzulla
25
6.3k
コードとあなたと私の距離 / The Distance Between Code, You, and I
hiro_y
0
170
バッチ処理を「状態の記録」から「事実の記録」へ
panda728
PRO
0
170
monorepo の Go テストをはやくした〜い!~最小の依存解決への道のり~ / faster-testing-of-monorepos
convto
2
500
Building, Deploying, and Monitoring Ruby Web Applications with Falcon (Kaigi on Rails 2025)
ioquatix
4
2.2k
kiroとCodexで最高のSpec駆動開発を!!数時間で web3ネイティブなミニゲームを作ってみたよ!
mashharuki
0
680
Cursorハンズオン実践!
eltociear
2
1.1k
Introduce Hono CLI
yusukebe
6
2.8k
テーブル定義書の構造化抽出して、生成AIでDWH分析を試してみた / devio2025tokyo
kasacchiful
0
160
Featured
See All Featured
Statistics for Hackers
jakevdp
799
220k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
190
55k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.2k
Facilitating Awesome Meetings
lara
56
6.6k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
The Power of CSS Pseudo Elements
geoffreycrofte
79
6k
Reflections from 52 weeks, 52 projects
jeffersonlam
353
21k
Become a Pro
speakerdeck
PRO
29
5.6k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Faster Mobile Websites
deanohume
310
31k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.7k
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[Λ͏ͷ༗ Γɻ