Slide 1

Slide 1 text

౔԰࿨ྑ(.01FQBCP *OD 7VF'FT+BQBO ೥ؒ୯ମςετΛ ॻ͖ଓ͚ͨݱ৔͔ΒૹΔ 7VF$PNQPOFOUͷςετ

Slide 2

Slide 2 text

IUUQTUTVDIJLB[VOFU (.0ϖύϘ&$ࣄۀ෦ςΫχΧϧϦʔυ ౔԰࿨ྑ!UTVDIJLB[V ୲౰αʔϏεΧϥʔϛʔϦϐʔτ

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

$PNQPOFOUͷςετ ॻ͍͍ͯΔਓ 

Slide 7

Slide 7 text

Α͘ฉ͘੠ 6*ͷςετ͸มߋ͕ൃੜ͠΍͘͢ ίετʹݟ߹Θͳ͍ΜͩΑͶ େࣄͳϩδοΫ͸$PNQPOFOUͷ ֎ʹग़ͯ͠ςετ͍ͯ͠Δ͔Β ͍Βͳ͍͔ͳͱ

Slide 8

Slide 8 text

ͦ͏͸ݴͬͯ΋ ͔ͩΒ͔ͬ͠Γͱ ಈ࡞֬ೝ͠Α͏ ςετ͕ͳ͍ͱ ҙਤ͠ͳ͍มߋ͕ى͖ͳ͍͔ෆ҆ʜ

Slide 9

Slide 9 text

ָͰ͖Δͱ͜Ζ͸ָͯ͠ ෆ҆ղফ͍͖͍ͯͨ͠

Slide 10

Slide 10 text

ͦͷͨΊʹ ݱ৔Ͱ΍͍ͬͯΔ͜ͱ

Slide 11

Slide 11 text

w$PNQPOFOUͷԿΛςετ͢Δͷ͔ʁ wͲ͏΍ͬͯςετ͢Δʁ w-JGFDZDMFฤ w1SPQT7VFY4UBUFฤ w6TFS*OUFSBDUJPOฤ "HFOEB

Slide 12

Slide 12 text

ԿΛςετ͢Δʁ

Slide 13

Slide 13 text

֎෦͔ΒݟͨৼΔ෣͍Λ ςετ͢Δ

Slide 14

Slide 14 text

DPNQPOFOUͷςετ΋ ͦ͏Ͱͳ͍ςετͱ ߟ͑ํ͸Ұॹ

Slide 15

Slide 15 text

!UXBEB 2ϓϥΠϕʔτϝιουͷϢχοτςετ ͸ॻ͔ͳ͍΋ͷʁ ϓϥΠϕʔτϝιουͷϢχοτςετ͸ॻ͔ͳ͍΋ͷʁ2"!*5 IUUQTRBBUNBSLJUDPKQR "୹͘·ͱΊΔͱɺϓϥΠϕʔτͳϝιο υͷςετΛॻ͘ඞཁ͸ແ͍ͱߟ͍͑ͯ· ͢ɻ தུ ϓϥΠϕʔτϝιου͸࣮૷ͷৄࡉͰ ͋ΓɺࣗಈςετͷλʔήοτͱͳΔʮ֎ ෦͔ΒݟͨৼΔ෣͍ʯͰ͸͋Γ·ͤΜɻ

Slide 16

Slide 16 text

૊৫ʹςετΛॻ͘จԽΛࠜ෇͔ͤΔઓུͱઓज़IUUQTTQFBLFSEFDLDPNUXBEB TUSBUFHZBOEUBDUJDTPGCVJMEJOHBVUPNBUFEUFTUJOHDVMUVSFJOUPPSHBOJ[BUJPO TMJEF

Slide 17

Slide 17 text

$PNQPOFOUͰ͍͏ͱʁ

Slide 18

Slide 18 text

1VCMJD*OUFSGBDF $PNQPOFOU -JGFDZDMF 7VFY 4UBUF 1SPQT 6TFS *OUFSBDUJPO

Slide 19

Slide 19 text

0VUQVU 7VFY "DUJPO &WFOU )5.- $44 $PNQPOFOU

Slide 20

Slide 20 text

7VFY "DUJPO &WFOU )5.- $44 $PNQPOFOU -JGFDZDMF 7VFY 4UBUF 1SPQT 6TFS *OUFSBDUJPO 7VF/:$$PNQPOFOU5FTUTXJUI7VFKT.BUU0$POOFMM:PV5VCFIUUQTXXXZPVUVCFDPNXBUDI W0*QG855IS, ςετλʔήοτ

Slide 21

Slide 21 text

NPVOUPSTIBMMPXNPVOU $PNQPOFOU NPVOU $IJME $PNQPOFOU $PNQPOFOU $IJME $PNQPOFOU TIBMMPXNPVOU

Parent

Parent

Slide 22

Slide 22 text

wجຊతʹNPVOU wʮ֎෦͔ΒΈͨৼΔ෣͍ʯ wʮઃܭͷՄಈҬΛ֬อʯ wର৅DPNQPOFOU wSPVUFS͔ΒಡΈࠐΉ͍ΘΏΔ1BHF $PNQPOFOU wෳࡶͳPSڞ௨Ͱ࢖༻͢Δ$PNQPOFOU w1BHF$PNQPOFOUͰΧόʔ͕໘౗ ࠓͷϓϩδΣΫτͰ͸

Slide 23

Slide 23 text

w$PNQPOFOUͷԿΛςετ͢Δͷ͔ʁ wͲ͏΍ͬͯςετ͢Δʁ w-JGFDZDMFฤ w1SPQT7VFY4UBUFฤ w6TFS*OUFSBDUJPOฤ "HFOEB

Slide 24

Slide 24 text

Ͳ͏΍ͬͯςετ͢Δʁ

Slide 25

Slide 25 text

+FTU .PDIB ,BSNB 7VF5FTU6UJMT *TUBOCVM $IBJ QPXFSBTTFSU 4JOPO Α͘࢖͏ςετπʔϧͷ ໾ׂΛ੔ཧ͠Α͏

Slide 26

Slide 26 text

NPDLϥΠϒϥϦ ςεςΟϯά ϑϨʔϜϫʔΫ ςετϥϯφʔ ࣮ߦ؀ڥ "TTFSUJPO ࣮ϒϥ΢β KTEPN ,BSNB .PDIB +FTU $PWFSBHF 4JOPO *TUBOCVM $PNQPOFOU 5FTU6UJMJUZ 7VF5FTU6UJMT $IBJQPXFSBTTFSU

Slide 27

Slide 27 text

NPDLϥΠϒϥϦ ςεςΟϯά ϑϨʔϜϫʔΫ ςετϥϯφʔ ࣮ߦ؀ڥ "TTFSUJPO ࣮ϒϥ΢β KTEPN ,BSNB .PDIB +FTU $PWFSBHF 4JOPO $IBJQPXFSBTTFSU *TUBOCVM $PNQPOFOU 5FTU6UJMJUZ 7VF5FTU6UJMT ࣮ϒϥ΢β͕ ඞཁͳͱ͖ ࣮ϒϥ΢β͕ ෆཁͳͱ͖

Slide 28

Slide 28 text

-JGFDZDMF ʹର͢Δςετίʔυ

Slide 29

Slide 29 text

-JGFDZDMFͷςετ 7VFY "DUJPO &WFOU )5.- $44 $PNQPOFOU -JGFDZDMF

Slide 30

Slide 30 text

wΑ͘ॲཧ͕ॻ͔ΕΔMJGFDZDMFIPPL wDSFBUFE wNPVOUFE w/VYUͳͲ443͍ͯ͠Δ৔߹ wBTZOD%BUB wGFUDI -JGFDZDMFͷςετ

Slide 31

Slide 31 text

࣮૷ྫ -JGFDZDMF created () { this.loadPosts() }, methods: { ...mapActions(['fetchPosts']), async loadPosts () { this.message = 'ಡΈࠐΈத...' try { await this.fetchPosts() } finally { this.message = ‘' } } }, .FUIPE ݺͼग़͠

Slide 32

Slide 32 text

࣮૷ྫ -JGFDZDMF created () { this.loadPosts() }, methods: { ...mapActions(['fetchPosts']), async loadPosts () { this.message = 'ಡΈࠐΈத...' try { await this.fetchPosts() } finally { this.message = ‘' } } }, දࣔมߋ

Slide 33

Slide 33 text

࣮૷ྫ -JGFDZDMF created () { this.loadPosts() }, methods: { ...mapActions(['fetchPosts']), async loadPosts () { this.message = 'ಡΈࠐΈத...' try { await this.fetchPosts() } finally { this.message = ‘' } } }, "DUJPO EJTQBUDI

Slide 34

Slide 34 text

ςετྫ -JGFDZDMF // ϩʔΧϧͳVueίϯετϥΫλʹVuexΛΠϯετʔϧ const localVue = createLocalVue() localVue.use(Vuex) beforeEach(() => { // fetchPostsΞΫγϣϯͷಈ࡞֬ೝͷͨΊͷVuexपΓͷઃఆ actions = { fetchPosts: sinon.stub() // fetchPostsΞΫγϣϯͷϞοΫ } store = new Vuex.Store({ actions }) wrapper = mount(Posts, {store, localVue }) }) ͓ܾ·Γ

Slide 35

Slide 35 text

ςετྫ -JGFDZDMF // ϩʔΧϧͳVueίϯετϥΫλʹVuexΛΠϯετʔϧ const localVue = createLocalVue() localVue.use(Vuex) beforeEach(() => { // fetchPostsΞΫγϣϯͷಈ࡞֬ೝͷͨΊͷVuexपΓͷઃఆ actions = { fetchPosts: sinon.stub() // fetchPostsΞΫγϣϯͷϞοΫ } store = new Vuex.Store({ actions }) wrapper = mount(Posts, {store, localVue }) }) TUPSFͷϞοΫΛ ࡞੒

Slide 36

Slide 36 text

ςετྫ -JGFDZDMF it('loadingදࣔ͞ΕΔ͜ͱ', async () => { expect(wrapper.text()).to.contain('ಡΈࠐΈத...') }) it('fetchPosts͕dispatch͞ΕΔ͜ͱ', () => { sinon.assert.calledOnce(actions.fetchPosts) }) it('dispatch੒ޭ͢Δͱɺloadingද͕ࣔফ͑Δ͜ͱ', async () => { actions.fetchPosts.resolves() await flushPromises() expect(wrapper.text()).not.to.contain('ಡΈࠐΈத...') })

Slide 37

Slide 37 text

w࣮ࡍʹ͸ɺදࣔʹඞཁͳσʔλऔಘͷͨΊʹ EJTQBUDI͢Δ͙Β͍ w͜ΕΛςετͯ͠΋ಘΒΕΔ҆৺ײ͸௿͍ wଞͷςετΛॻ͍ͨ΄͏͕Α͍ w-JGFDZDMFIPPL͸NPDLԽͯ͠ɺଞͷςετ ͷअຐʹͳΒͳ͍Α͏ʹ͢Δͷ΋ͭͷख -JGFDZDMFͷςετΛͯ͠Έͯ

Slide 38

Slide 38 text

w$PNQPOFOUͷԿΛςετ͢Δͷ͔ʁ wͲ͏΍ͬͯςετ͢Δʁ w-JGFDZDMFฤ w1SPQT7VFY4UBUFฤ w6TFS*OUFSBDUJPOฤ "HFOEB

Slide 39

Slide 39 text

1SPQT7VFY4UBUF ʹର͢Δςετίʔυ

Slide 40

Slide 40 text

1SPQT7VFY4UBUFͷςετ )5.- $44 $PNQPOFOU 7VFY 4UBUF 1SPQT

Slide 41

Slide 41 text

࣮૷ྫ දࣔ
·ͩ౤ߘ͸͋Γ·ͤΜ
λΠτϧ ಺༰ {{post.title}} {{post.body}} ݅ͷͱ͖ දࣔΛม͑Δ

Slide 42

Slide 42 text

ςετྫ ୯७ͳBTTFSU describe('౤ߘ͕0݅ͷ৔߹', () => { beforeEach(() => wrapper.setProps({posts: []}) it('0݅ͷද͕ࣔ͞Ε͍ͯΔ͜ͱ', () => { expect(wrapper.text()).to.contain('·ͩ౤ߘ͸͋Γ·ͤΜ') }) }) describe('౤ߘ͕1݅Ҏ্ͷ৔߹', () => { const post = {id: 1, title: ‘λΠτϧ’, body: ‘body’} beforeEach(() => wrapper.setProps({posts: [post]}) it('౤ߘͷ಺༰͕දࣔ͞Ε͍ͯΔ͜ͱ', () => { expect(wrapper.text()).to.contain(post.title) }) })

Slide 43

Slide 43 text

w FYQFDU XSBQQFSUFYU UPDPOUBJO b·ͩ౤ߘ ͸͋Γ·ͤΜ`  wදࣔมΘͬͨΒɺςετ΋௚͢ w FYQFDU XSBQQFSUFYU UPDPOUBJO QPTUYY  w Ͳ͜ʹදࣔ͞Ε͍ͯΔʁͬ͘͟Γ͗͢͠ wࡉ͔ͨ͘͠Βϝϯςେม ୯७ͳBTTFSUͷͭΒ͞ ˠ͜ΕΒΛ͍͍ײ͡ʹ΍Γ͍ͨ

Slide 44

Slide 44 text

4OBQTIPU5FTUJOH

Slide 45

Slide 45 text

NPDLϥΠϒϥϦ ςεςΟϯά ϑϨʔϜϫʔΫ ςετϥϯφʔ ࣮ߦ؀ڥ "TTFSUJPO ࣮ϒϥ΢β KTEPN ,BSNB .PDIB +FTU $PWFSBHF 4JOPO $IBJQPXFSBTTFSU *TUBOCVM $PNQPOFOU 5FTU6UJMJUZ 7VF5FTU6UJMT ͜Εͩͱ Մೳ

Slide 46

Slide 46 text

w DPNQPOFOUͷ%0.ʢTOBQTIPUʣΛൺֱ͢Δ w ίʔυमਖ਼લͷ%0.Λظ଴஋ͱͯ͠ɺࠓͷ%0. ͱൺֱ 4OBQTIPU5FTUJOH

Slide 47

Slide 47 text

w ࠩ෼͕ͳ͚Ε͹TVDDFTT w ࠩ෼͕͋Ε͹Ұ౓͸GBJM w ։ൃऀ͕ࠩ෼Λ֬ೝ w ҙਤతͳมߋͰ͋Ε͹
 มߋޙͷ%0.Λ࣍ͷظ଴஋ʹ࢖͏Α͏ʹ
 VQEBUF͢Δ 4OBQTIPU5FTUJOH

Slide 48

Slide 48 text

w %0.ͷมߋ͸͍͍ײ͡ʹςετͰ͖ΔΑ͏ʹ ͳΔ w DPNQPOFOU͸ɺ)5.- $44 w $44ͷςετ΋͍ͨ͠ 4OBQTIPU5FTUJOHͷͭΒ͞

Slide 49

Slide 49 text

7JTVBM5FTUJOH

Slide 50

Slide 50 text

w 4OBQTIPU5FTUJOHͷը૾൛ w ը૾ͷࠩ෼ݕग़πʔϧ͕ผʹඞཁ w ৭ʑͳํ๏͕͋Δ 7JTVBM5FTUJOH

Slide 51

Slide 51 text

ࢲ͕࠾༻ͨ͠ ࠷ߴͷ7JTVBM5FTUJOHͷํ๏ ʙ1SPQT7VFY4UBUFฤʙ

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

w QSPQT΍7VFYTUBUFΛ༩͑ͯදࣔύλʔϯΛ֬ೝͰ͖Δ w DPNQPOFOU୯ҐͳͷͰΤοδέʔεʹ΋ରԠԽ w ؆୯ʹTDSFFOTIPU͕ͱΕΔ w ࠓ͸[JTVJΛ࢖͍ͬͯΔ 4UPSZCPPLͱ͸ IUUQTTUPSZCPPLTWVFOFUMJGZDPN

Slide 54

Slide 54 text

4UPSZCPPLͰQSPQTΛ౉͢ storiesOf('propsΛड͚औΔcomponent', module) .add('ۭͷͱ͖', () => ({ components: { PostsByProps }, template: '', data: () => ({ posts: [] }) })) .add('౤ߘ͕͋Δͱ͖', () => ({ components: { PostsByProps }, template: '', data: () => ({ posts: [{id: 1, title: ‘title', body: 'ϘσΟ'}] }) }))

Slide 55

Slide 55 text

4UPSZCPPLͰ7VFY4UBUFΛ౉͢ storiesOf('vuex storeΛड͚औΔcomponentྫ', module) .add('ۭͷͱ͖', () => ({ components: { PostsByStore }, template: '', store: new Vuex({ state: () => ({ posts: [] }) }) })) .add('౤ߘ͕͋Δͱ͖', () => ({ components: { PostsByStore }, template: '', store: new Vuex({ state: () => ({ posts: [{id: 1, title: 'λΠτϧ1', body: 'ϘσΟ'}] }) }) }))

Slide 56

Slide 56 text

w7VFYʹґଘ͍ͯ͠ΔDPNQPOFOU͸TUPSFΛ४උ͢ Δͷ͕໘౗ w͚ͩͲɺ7JTVBM5FTU͍ͨ͠$PNQPOFOU w1SFTFOUBUJPOBMͱ$POUBJOFS$PNQPOFOUʹ෼ ͚Δ w൚༻తͳϞοΫTUPSFΛ४උͯ͠ɺશͯͷ DPNQPOFOUͰ࢖͍ճ͢ wࠓͷॴɺͬͪ͜Ͱ΍ͬͯΔ 4UPSZCPPLॻ͍ͯΈͯ

Slide 57

Slide 57 text

ݱ৔ͷίʔυ import { state, getters, mutations, actions } from ‘@/store' function createStubStore () { const store = new Vuex.Store({state, getters, mutations, actions}) sinon.stub(store, 'dispatch').resolves() store.state.posts = [{id: 1, title: 'λΠτϧ1', body: 'ϘσΟ'}] // ࣮ࡍ͸͜͜ͷstate४උ͕͍ͬͺ͍͋Δ return store } const emptyPostsStore = createStubStore() emptyPostsStore.state.posts = [] storiesOf('Posts', module) .add('ۭͷͱ͖', () => ({ components: { Posts }, template: '', store: emptyPostsStore, })) ຊ෺ͷTUPSFΛϕʔεʹ EJTQBUDINFUIPEͱ TUBUFΛϞοΫԽ͢Δ

Slide 58

Slide 58 text

ݱ৔ͷίʔυ import { state, getters, mutations, actions } from ‘@/store' function createStubStore () { const store = new Vuex.Store({state, getters, mutations, actions}) sinon.stub(store, 'dispatch').resolves() store.state.posts = [{id: 1, title: 'λΠτϧ1', body: 'ϘσΟ'}] // ࣮ࡍ͸͜͜ͷstate४උ͕͍ͬͺ͍͋Δ return store } const emptyPostsStore = createStubStore() emptyPostsStore.state.posts = [] storiesOf('Posts', module) .add('ۭͷͱ͖', () => ({ components: { Posts }, template: '', store: emptyPostsStore, })) ൚༻తͳ TUPSFΛඍௐ੔ͯ͠ TUPSZ΁

Slide 59

Slide 59 text

w7JTVBM5FTUJOHΛ։ൃϑϩʔʹࡌͤΔͷʹඞཁ ͳػೳΛඋ͍͑ͯΔπʔϧ wը૾ͷࠩ෼நग़ wࠩ෼ͷSFQPSUΛIUNMʹग़ྗͯ͠ɺT΁Ξοϓ ϩʔυ w(JUIVC΁ͷ௨஌ SFHTVJUͱ͸

Slide 60

Slide 60 text

w$PNQPOFOUΛमਖ਼ͯ͠GFBUVSFCSBODI΁QVTI TUPSZCPPLSFHTVJUͷ։ൃϑϩʔ IPPL QVTI

Slide 61

Slide 61 text

JO$* TUPSZCPPLSFHTVJUͷ։ൃϑϩʔ TDSFFOTIPU CZ[JTVJ ෼ذݩͷը૾ DPNQBSF GFBUVSFCSBODIը૾ DPNNFOU SFHTVJU

Slide 62

Slide 62 text

TUPSZCPPLSFHTVJUͷ։ൃϑϩʔ

Slide 63

Slide 63 text

TUPSZCPPLSFHTVJUͷ։ൃϑϩʔ #FGPSF "GUFS ࠩ෼ 13"QQSPWF

Slide 64

Slide 64 text

wDPNQPOFOU୯ҐͰͷςετ͕Մೳ w։ൃϑϩʔ͕ීஈͷ։ൃͱҰॹ wTUPSZCPPL͕؆୯ wσβΠφ͞Μ΋ฤूͯ͘͠ΕΔ wແྉ w༗ঈπʔϧ΋͍ͬͺ͍͋Δ ࠷ߴϙΠϯτ

Slide 65

Slide 65 text

wϦϑΝΫλ࣌΋ػೳ௥Ճ࣌΋ɺͱͯ΋҆৺ wϨϏϡʔґཔ΍ϨϏϡʔͷෛՙ͕Լ͕Δ w7JTVBM5FTUͷ݁Ռ͚ͩͰͳ͘ɺͦΕͱ͸ผʹ $*Ͱ13͝ͱʹTUPSZCPPL΋σϓϩΠ wϨϏϡʔ࣌ʹຖճDIFDLPVU΍ɺಈ࡞֬ೝ༻ ͷ؀ڥ͕ෆཁ 7JTVBM5FTU΍ͬͯΈͯ

Slide 66

Slide 66 text

wΫϩεϒϥ΢βରԠ wTUPSZCPPLͷTDSFFOTIPU͸QVQQFUFFS w༗ྉαʔϏε΋ݕ౼ ͜Ε͔ΒͷվળϙΠϯτ

Slide 67

Slide 67 text

w$PNQPOFOUͷԿΛςετ͢Δͷ͔ʁ wͲ͏΍ͬͯςετ͢Δʁ w-JGFDZDMFฤ w1SPQT7VFY4UBUFฤ w6TFS*OUFSBDUJPOฤ "HFOEB

Slide 68

Slide 68 text

6TFS*OUFSBDUJPO ʹର͢Δςετίʔυ

Slide 69

Slide 69 text

6TFS*OUFSBDUJPO 7VFY "DUJPO &WFOU )5.- $44 $PNQPOFOU 6TFS *OUFSBDUJPO

Slide 70

Slide 70 text

wϑΥʔϜೖྗ wϘλϯΫϦοΫ wεΫϩʔϧ w%% wεϫΠϓ wϐϯνΠϯɺΞ΢τ wFUD 6TFS*OUFSBDUJPOͱ͸

Slide 71

Slide 71 text

wϑΥʔϜೖྗ wϘλϯΫϦοΫ wεΫϩʔϧ w%% wεϫΠϓ wϐϯνΠϯɺΞ΢τ wFUD 6TFS*OUFSBDUJPOͱ͸ ςετ೉қ౓௿ ςετ೉қ౓ߴ ͬͪ͜ͷΈΛςετ͍ͯ͠Δ

Slide 72

Slide 72 text

࣮૷ྫ 6TFS*OUFSBDUJPO

৽ن࡞੒

λΠτϧ {{ errors.first('title') }}
಺༰ {{ errors.first('body') }}
อଘ
JOQVUUFYUY #VUUPOY γϯϓϧͳGPSN

Slide 73

Slide 73 text

࣮૷ྫ 6TFS*OUFSBDUJPO

৽ن࡞੒

λΠτϧ {{ errors.first('title') }}
಺༰ {{ errors.first('body') }}
อଘ
WFFWBMJEBUF ͰඞਢνΣοΫ

Slide 74

Slide 74 text

࣮૷ྫ 6TFS*OUFSBDUJPO export default { data: () => ({ post: { title: '', body: '' } }), methods: { async save () { const isValid = await this.$validator.validate() if (isValid) { await this.$store.dispatch( 'createPost', { post: this.post } ) this.$router.push({ path: '/' }) } } } } WBMJEBUFͯ͠ BDUJPOEJTQBUDI

Slide 75

Slide 75 text

ςετྫ XSBQQFS४උ // ϩʔΧϧͳVueίϯετϥΫλʹVuex/VeeValidateΛΠϯετʔϧ const localVue = createLocalVue() localVue.use(Vuex) localVue.use(VeeValidate) beforeEach(() => { // Vue RouterͷϞοΫઃఆ $router = { push: sinon.stub() } // createPostΞΫγϣϯͷಈ࡞֬ೝͷͨΊͷVuexपΓͷઃఆ actions = { createPost: sinon.stub() } store = new Vuex.Store({ actions }) wrapper = mount(NewPost, { mocks: { $router }, store, localVue, sync: false }) }) TUPSFͷϞοΫΛ ࡞੒NPVOU

Slide 76

Slide 76 text

ςετྫ ೖྗͯ͠DMJDLͨ͠ͱ͖ describe('ೖྗͯ͠อଘϘλϯΛclickͨ͠ͱ͖', () => { beforeEach(async () => { wrapper.find('#title').setValue('title') wrapper.find('#body').setValue('body') wrapper.find('#create-button').trigger('click') await flushPromises() }) it('ೖྗ͞Εͨ಺༰Ͱaction͕dispatch͞ΕΔ͜ͱ', () => { sinon.assert.calledWithMatch(actions.createPost, {}, { post: { title: 'title', body: 'body' } }) }) }) ೖྗޙʹϘλϯDMJDLͷͱ͖ EJTQBUDI͞ΕΔ

Slide 77

Slide 77 text

ςετྫ ೖྗͤͣʹDMJDLͨ͠ͱ͖ describe('ະೖྗͰอଘϘλϯΛclickͨ͠ͱ͖', () => { beforeEach(async () => { wrapper.find('#create-button').trigger('click') await flushPromises() }) it('validationΤϥʔ͕දࣔ͞ΕΔ͜ͱ', () => { expect(wrapper.text()).to.contain( 'The title field is required.') }) it('action͕dispatch͞Εͳ͍͜ͱ', () => { sinon.assert.notCalled(actions.createPost) }) }) ະೖྗͰϘλϯDMJDLͷͱ͖ WBMJEBUJPOΤϥʔදࣔEJTQBUDI͞Εͳ͍

Slide 78

Slide 78 text

ςετྫ ೖྗͤͣʹDMJDLͨ͠ͱ͖ describe('ະೖྗͰอଘϘλϯΛclickͨ͠ͱ͖', () => { beforeEach(async () => { wrapper.find('#create-button').trigger('click') await flushPromises() }) it('validationΤϥʔ͕දࣔ͞ΕΔ͜ͱ', () => { expect(wrapper.text()).to.contain( 'The title field is required.') }) it('action͕dispatch͞Εͳ͍͜ͱ', () => { sinon.assert.notCalled(actions.createPost) }) }) ද͕ࣔมΘͬͨ෦෼Λ ୯७ͳBTTFSUͯ͠Δ

Slide 79

Slide 79 text

wྫ͑͹
 WBMJEBUJPOΤϥʔৄࡉΛ։͘ด͡Δ
 Ϙλϯԡͯ͠Ϟʔμϧ։͘FUD wཁ͸ςετͷதͰɺTOBQTIPUΛࡱΓ͍ͨ 6TFS*OUFSBDUJPOޙͷը૾ΛࡱΓ͍ͨ wrapper.find('#create-button').trigger('click') screenshot(‘ະೖྗͰͷclickޙ.png’)

Slide 80

Slide 80 text

NPDLϥΠϒϥϦ ςεςΟϯά ϑϨʔϜϫʔΫ ςετϥϯφʔ ࣮ߦ؀ڥ "TTFSUJPO ࣮ϒϥ΢β KTEPN ,BSNB .PDIB +FTU $PWFSBHF 4JOPO $IBJQPXFSBTTFSU *TUBOCVM $PNQPOFOU 5FTU6UJMJUZ 7VF5FTU6UJMT ͜Εͩͱ Մೳ

Slide 81

Slide 81 text

wLBSNBOJHIUNBSF wLBSNBͰOJHIUNBSF FMFDUSPO ্ͰςετΛ ࣮ߦͰ͖Δ΋ͷ wTDSFFOTIPU"1*Λఏڙͯ͘͠ΕΔ wը૾͕ࡱΕͨΒTUPSZCPPLͷը૾ͱҰॹʹ SFHTVJUͷϑϩʔʹࡌͤΔ 5FTUதʹTDSFFOTIPUࡱΔʹ͸

Slide 82

Slide 82 text

w؆୯ͳ6TFS*OUFSBDUJPOͷςετ͸େม͡Όͳ͍ wॏཁͳ'PSN͚ͩͰ΋΍͓ͬͯ͘ͱ͍͍ wͦΕҎ֎͸ఘΊ΋؊৺ w6TFS*OUFSBDUJPOޙͷTDSFFOTIPUͱͬͯɺ7JTVBM 5FTU͸΍ͬͺΓศར 6TFS*OUFSBDUJPOͷςετͯ͠Έͯ

Slide 83

Slide 83 text

·ͱΊ

Slide 84

Slide 84 text

7VFY "DUJPO &WFOU )5.- $44 $PNQPOFOU -JGFDZDMF 7VFY 4UBUF 1SPQT 6TFS *OUFSBDUJPO ςετλʔήοτ

Slide 85

Slide 85 text

͜͜·Ͱ঺հ͖ͯͨ͠ ৭ʑͳςετΛ ݱ৔Ͱ͖ͯ͠·ͨ͠ ͦͷ݁ՌɺҰ൪࠷ߴͳςετ͸

Slide 86

Slide 86 text

)5.- $44 $PNQPOFOU 7VFY 4UBUF 1SPQT 6TFS *OUFSBDUJPO ͜ͷ෦෼ͷ7JTVBM5FTU

Slide 87

Slide 87 text

wTUPSZCPPLͰͷʮ1SPQT7VFY4UBUFˠදࣔʯ ͷςετ͚ͩͰ΋͋Δͱ҆৺ wʮ6TFS*OUFSBDUJPOˠදࣔʯͷςετ΋͋ Δͱߋʹ҆৺ͷ෯͕޿͕Δ w෭࡞༻ͱͯ͠ϨϏϡʔͷෛՙܰݮ w͜Ε͕ඇৗʹେ͖͍ 7JTVBM5FTU͸࠷ߴ

Slide 88

Slide 88 text

ָͰ͖Δͱ͜Ζ͸ָͯ͠ ෆ҆Λղফͭͭ͠ ָ͘͠։ൃ͍͖ͯ͠·͠ΐ͏