Vueコンポーネントのユニットテスト

 Vueコンポーネントのユニットテスト

Vueコンポーネントのユニットテスト
Vue.js Tokyo v-meetup #4
https://vuejs-meetup.connpass.com/event/58071/

022fe97731555344992c588527848cb7?s=128

hypermkt

July 07, 2017
Tweet

Transcript

  1. όʔνʔ(.01&1"#0JOD 7VFKT.FFUVQ 7VFίϯϙʔωϯτͷ Ϣχοτςετ

  2. ιϑτ΢ΣΞΤϯδχΞ <b1)1FS` b7VFKT` b3BJMT`>
 Ξχϝ෦෦௕ όʔνʔ!IZQFSNLU IUUQCMPHIZQFSNLUKQ

  3. 7VFίϯϙʔωϯτͷ Ϣχοτςετ

  4. ຊ೔ͷର৅ऀ wओʹ7VFίϯϙʔωϯτͷςετΛॻ͍͍ͯΔਓ wࠓޙ7VFίϯϙʔωϯτͷςετΛॻ͖͍ͨਓ

  5. ίϯϙʔωϯτͷςετͰͪΐͬͱࠔΔγʔϯᶃ 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ΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ
  6. ίϯϙʔωϯτͷςετͰͪΐͬͱࠔΔγʔϯᶄ <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*ΛݺΜͰ͍Δɻ ͜ͷίϯϙʔωϯτͷςετͷΈʹ ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ ͕अຐͰςετ͕ͮ͠Β͍ɻ
  7. ΋ͬͱ؆୯ʹ7VFίϯϙʔωϯτͷ ςετ͕ॻ͚ͳ͍΋ͷ͔ʁ

  8. 7VFKT༻ςετϥΠϒϥϦͩʂ

  9. ୳ͨ͠Βͨ͘͞Μ͋ͬͨ wWVFUFTU wBWPSJB[ wWVFVOJU wWVFUFTUJOH wSFWVF wWVFOJU

  10. ొ৔ͨ࣌͠ظ΋͍͍ͩͨಉ͡ wWVFUFTU wBWPSJB[ wWVFVOJU wWVFUFTUJOH wSFWVF wWVFOJU

  11. ػೳ΋͍͍ͩͨಉ͡ w4IBMMPX'VMM3FOEFSJOH w%0.&WFOU5SJHHFS w7VFY 3PVUFS )551ͷϞοΫελϒ w"TTFSUJPO w%0.4FMFDUPS

  12. ެࣜͷςετϥΠϒϥϦ͕ ແ͍ͩΖ͏͔ʁ

  13. IUUQTGPSVNWVFKTPSHUJTBOZUIJOHCFJOHEPOFJODPSFWVFUPNBLFVOJUUFTUJOHFBTJFS

  14. WVFUFTUVUJMTͷొ৔

  15. WVFUFTUVUJMTͷݱঢ় wBWPSJB[։ൃऀͷ!FEEZFSCVSHIࢯ͕ϝΠϯͰ։ൃத wWVFUFTU SFWVF WVFVOJU WVFOJUͷ։ൃ͕ҙݟΛग़ ͠߹͍ w։ൃ͸ऴ൫ɻॳظ50%0ͷׂ׬ྃ wݱࡏυΩϡϝϯτ४උத wۙʑЌ൛͕ϦϦʔε͞Εͦ͏ͳ༧ײ

    ࣌఺
  16. WVFUFTUVUJMT͸ ·ͩЌ൛͢ΒϦϦʔε͞Ε͍ͯͳ͍Ͱ ݱঢ়Ͱਂ͘௥͏ͷ͸࣌ظঘૣ

  17. WVFUFTUVUJMT͸BWPSJB[Λ౿ऻͯ͠։ൃ͞Ε͍ͯΔɻ BWPSJB[Λ஌Δ͜ͱͰWVFUFTUVUJMTΛઌऔΓ͠Α͏ʂ

  18. BWPSJB[
 B7VFKTUFTUJOHVUJMJUZMJCSBSZ IUUQTHJUIVCDPNFEEZFSCVSHIBWPSJB[

  19. BWPSJB[ͷػೳ wK2VFSZϥΠΫͳηϨΫλʔ w%0.ΠϕϯττϦΨʔ w4IBMMPX 'VMMϨϯμϦϯά

  20. BWPSJB[ͷྑ͍ͱ͜Ζ wγϯϓϧͳ"1* wυΩϡϝϯτ͕๛෋ w֤ςετϥΠϒϥϦผͷαϯϓϧίʔυ΋๛෋

  21. $PNQPOFOUͷςετख๏ w*TPMBUFE5FTUJOH w $PNQPOFOUͷϩδοΫͷΈΛςετ͢Δ w4IBMMPX5FTUJOH w ࢠίϯϙʔωϯτ͸ϨϯμϦϯάͤͣɺࣗ਎ͷ$PNQPOFOUͷΈΛϨϯμϦϯάͯ͠ςε τ͢Δ w*OUFHSBUJPO5FTUJOH w

    ࢠίϯϙʔωϯτ΋શͯϨϯμϦϯάͯ͠ςετ͢Δ w&WFOU5FTUJOH w %0.ΠϕϯτΛൃੜͤ͞ɺ૝ఆ͢ΔڍಈΛ͢Δ͔ςετ͢Δ
  22. $PNQPOFOUͷςετख๏ w*TPMBUFE5FTUJOH w $PNQPOFOUͷϩδοΫͷΈΛςετ͢Δ w4IBMMPX5FTUJOH w ࢠίϯϙʔωϯτ͸ϨϯμϦϯάͤͣɺࣗ਎ͷ$PNQPOFOUͷΈΛϨϯμϦϯάͯ͠ςε τ͢Δ w*OUFHSBUJPO5FTUJOH w

    ࢠίϯϙʔωϯτ΋શͯϨϯμϦϯάͯ͠ςετ͢Δ w&WFOU5FTUJOH w %0.ΠϕϯτΛൃੜͤ͞ɺ૝ఆ͢ΔڍಈΛ͢Δ͔ςετ͢Δ
  23. 4IBMMPXϨϯμϦϯά

  24. ՝୊ <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*ΛݺΜͰ͍Δɻ ͜ͷίϯϙʔωϯτͷςετͷΈʹ ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ ͕अຐͰςετ͕ͮ͠Β͍ɻ
  25. ղܾ๏ɿ4IBMMPXϨϯμϦϯάΛར༻͢Δ w4IBMMPXϨϯμϦϯάͱ͸ɺࢠίϯϙʔωϯτΛల։ ͤͣʹϨϯμϦϯά͢Δ͜ͱ wBWPSJB[Ͱ͸TIBMMPXػೳΛར༻͢Δ͜ͱͰɺશͯͷࢠ ίϯϙʔωϯτΛελϒ ʹͳΔʣͯ͠ɺϨϯμ Ϧϯάͨ͠ϥούʔΦϒδΣΫτΛฦ͢

  26. <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Λ࢖༻ͨ͠ςετέʔε
  27. ͜ΕͰςετ͍ͨ͠ίϯϙʔωϯτ ͚ͩʹूதͰ͖Δʂʂ

  28. *OUFHSBUJPO5FTU

  29. ՝୊ <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> ࢠίϯϙʔωϯτ΋ؚΊͯը໘શମ ͕ਖ਼ৗʹϨϯμϦϯά͞Ε͍ͯΔͷ Λ֬ೝ͍ͨ͠ɻ
  30. ղܾ๏ɿ'VMMϨϯμϦϯάΛར༻͢Δ w'VMMϨϯμϦϯάͱ͸ɺίϯϙʔωϯτશମΛϨϯμ Ϧϯά͢Δ wBWPSJB[Ͱ͸NPVOUػೳΛར༻͢Δ͜ͱͰɺ'VMMϨϯ μϦϯά͞ΕͨϥούʔΦϒδΣΫτΛऔಘͰ͖Δ

  31. <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Λར༻ͨ͠ςετέʔε
  32. &WFOU5FTUJOH

  33. ՝୊ 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ΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ
  34. ղܾ๏ɿUSJHHFSΛར༻͢Δ wUSJHHFS FWFOU/BNF ͸ࢦఆͨ͠ΠϕϯτΛݺͼग़͢ ͜ͱ͕ग़དྷΔ

  35. 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 })
  36. ·ͱΊ

  37. ·ͱΊ wWVFUFTUVUJMT͸ɺ։ൃதͳͷͰࠓޙͲ͏ͳΔ͔·ͩ ෼͔Βͳ͍ɻ wBWPSJB[Λར༻͢Ε͹ɺ؆୯ʹίϯϙʔωϯτͷςε τ͕ॻ͚ΔΑ͏ʹͳΔɻ wBWPSJB[ͱWVFUFTUVUJMT͸"1*͕͍͍ͩͨಉ͡ͳͷ Ͱɺ৐Γ׵͑΋ָɻࠓ͔ΒͰ΋BWPSJB[Λ࢖͏ͷ͸༗ Γɻ