Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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

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

hypermkt

July 07, 2017
Tweet

More Decks by hypermkt

Other Decks in Programming

Transcript

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

    View Slide

  2. ιϑτ΢ΣΞΤϯδχΞ

    View Slide

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

    View Slide

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

    View Slide

  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
    })


    Account:


    <br/>import api from '../libs/api'<br/>export default {<br/>data () {<br/>return {<br/>msg: ''<br/>}<br/>},<br/>methods: {<br/>checkAccount: () => {<br/>api.checkAccount()<br/>}<br/>}<br/>}<br/>
    ίϯϙʔωϯτ ςετέʔε
    จࣈྻೖྗ͞ΕͨΒ"1*ͰνΣοΫ͢Δ JOQVUΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ

    View Slide

  6. ίϯϙʔωϯτͷςετͰͪΐͬͱࠔΔγʔϯᶄ


    {{ msg }}



    
<br/>import Child from './Child.vue<br/>export default {
<br/>components: {<br/>'child': Child<br/>},<br/>data () {<br/>return {<br/>msg: ‘Hello World'<br/>}<br/>}<br/>}<br/>
    ࢠίϯϙʔωϯτ಺Ͱ)551ܦ༝ͷ
    "1*ΛݺΜͰ͍Δɻ
    ͜ͷίϯϙʔωϯτͷςετͷΈʹ
    ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ
    ͕अຐͰςετ͕ͮ͠Β͍ɻ

    View Slide

  7. ΋ͬͱ؆୯ʹ7VFίϯϙʔωϯτͷ
    ςετ͕ॻ͚ͳ͍΋ͷ͔ʁ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  13. IUUQTGPSVNWVFKTPSHUJTBOZUIJOHCFJOHEPOFJODPSFWVFUPNBLFVOJUUFTUJOHFBTJFS

    View Slide

  14. WVFUFTUVUJMTͷొ৔

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. BWPSJB[

    B7VFKTUFTUJOHVUJMJUZMJCSBSZ
    IUUQTHJUIVCDPNFEEZFSCVSHIBWPSJB[

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  23. 4IBMMPXϨϯμϦϯά

    View Slide

  24. ՝୊


    {{ msg }}



    
<br/>import Child from './Child.vue<br/>export default {
<br/>components: {<br/>'child': Child<br/>},<br/>data () {<br/>return {<br/>msg: ‘Hello World'<br/>}<br/>}<br/>}<br/>
    ࢠίϯϙʔωϯτ಺Ͱ)551ܦ༝ͷ
    "1*ΛݺΜͰ͍Δɻ
    ͜ͷίϯϙʔωϯτͷςετͷΈʹ
    ूத͍ͨ͠ͷʹɺࢠίϯϙʔωϯτ
    ͕अຐͰςετ͕ͮ͠Β͍ɻ

    View Slide

  25. ղܾ๏ɿ4IBMMPXϨϯμϦϯάΛར༻͢Δ
    w4IBMMPXϨϯμϦϯάͱ͸ɺࢠίϯϙʔωϯτΛల։
    ͤͣʹϨϯμϦϯά͢Δ͜ͱ
    wBWPSJB[Ͱ͸TIBMMPXػೳΛར༻͢Δ͜ͱͰɺશͯͷࢠ
    ίϯϙʔωϯτΛελϒ ʹͳΔʣͯ͠ɺϨϯμ
    Ϧϯάͨ͠ϥούʔΦϒδΣΫτΛฦ͢

    View Slide



  26. {{ msg }}



    
<br/>import Child from './Child.vue<br/>export default {
<br/>components: {<br/>'child': Child<br/>},<br/>data () {<br/>return {<br/>msg: ‘Hello World'<br/>}<br/>}<br/>}<br/>
    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Λ࢖༻ͨ͠ςετέʔε

    View Slide

  27. ͜ΕͰςετ͍ͨ͠ίϯϙʔωϯτ
    ͚ͩʹूதͰ͖Δʂʂ

    View Slide

  28. *OUFHSBUJPO5FTU

    View Slide

  29. ՝୊


    {{ msg }}



    
<br/>import Child from './Child.vue<br/>export default {
<br/>components: {<br/>'child': Child<br/>},<br/>data () {<br/>return {<br/>msg: ‘Hello World'<br/>}<br/>}<br/>}<br/>
    ࢠίϯϙʔωϯτ΋ؚΊͯը໘શମ
    ͕ਖ਼ৗʹϨϯμϦϯά͞Ε͍ͯΔͷ
    Λ֬ೝ͍ͨ͠ɻ

    View Slide

  30. ղܾ๏ɿ'VMMϨϯμϦϯάΛར༻͢Δ
    w'VMMϨϯμϦϯάͱ͸ɺίϯϙʔωϯτશମΛϨϯμ
    Ϧϯά͢Δ
    wBWPSJB[Ͱ͸NPVOUػೳΛར༻͢Δ͜ͱͰɺ'VMMϨϯ
    μϦϯά͞ΕͨϥούʔΦϒδΣΫτΛऔಘͰ͖Δ

    View Slide



  31. {{ msg }}



    
<br/>import Child from './Child.vue<br/>export default {
<br/>components: {<br/>'child': Child<br/>},<br/>data () {<br/>return {<br/>msg: ‘Hello World'<br/>}<br/>}<br/>}<br/>
    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Λར༻ͨ͠ςετέʔε

    View Slide

  32. &WFOU5FTUJOH

    View Slide

  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
    })


    Account:


    <br/>import api from '../libs/api'<br/>export default {<br/>data () {<br/>return {<br/>msg: ''<br/>}<br/>},<br/>methods: {<br/>checkAccount: () => {<br/>api.checkAccount()<br/>}<br/>}<br/>}<br/>
    ίϯϙʔωϯτ ςετέʔε
    จࣈྻೖྗ͞ΕͨΒ"1*ͰνΣοΫ͢Δ JOQVUΠϕϯτΛൃੜͤ͞Δͷ͕खؒɾɾɾ

    View Slide

  34. ղܾ๏ɿUSJHHFSΛར༻͢Δ
    wUSJHHFS FWFOU/BNF
    ͸ࢦఆͨ͠ΠϕϯτΛݺͼग़͢
    ͜ͱ͕ग़དྷΔ

    View Slide

  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
    })

    View Slide

  36. ·ͱΊ

    View Slide

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

    View Slide