Slide 1

Slide 1 text

Testing Vue components with Jest and vue-test-utils @ryohashimoto

Slide 2

Slide 2 text

ࠓճ͓࿩͢͠Δ͜ͱ • 2िؒ΄ͲલʹɺVue.jsΛϑϩϯτΤϯυͰ ࢖ͬͨRuby on RailsͷϓϩδΣΫτͰɺJest ͱvue-test-utilsΛಋೖɻ • ؆୯ʹVueίϯϙʔωϯτͷ୯ମςετ͕ॻ͚ ΔΑ͏ʹͳͬͯɺΧόϨοδ΋औΕΔΑ͏ʹ ͳͬͨɻ

Slide 3

Slide 3 text

ͳͥɺVueίϯϙʔωϯτͷ
 ςετΛߦ͏͔ʁ

Slide 4

Slide 4 text

Why? • ֤ίϯϙʔωϯτ͕ࢦఆ͞Εͨঢ়ଶͰਖ਼͘͠ ಈ͘͜ͱΛอূ͢ΔͨΊʢϢχοτςετʣ • खಈςετͷ৔߹ͷखؒʢϒϥ΢βͷૢ࡞ʣ Λল͖ɺCIͰ࣮ߦՄೳʹ͢ΔͨΊ • কདྷతͳVue.jsͷΞοϓάϨʔυʹඋ͑ΔͨΊ

Slide 5

Slide 5 text

Vue.jsΞϓϦέʔγϣϯͷ
 ߏ੒ཁૉ

Slide 6

Slide 6 text

Vueίϯϙʔωϯτ • HTMLςϯϓϨʔτ+Vue.jsίʔυ • ΧϓηϧԽ͞Εͨ࠶ར༻Մೳͳίʔυ • ୯ҰϑΝΠϧίϯϙʔωϯτ(.vue֦ுࢠ)Λ࢖ ༻Ͱ͖Δ • ૊Έ߹ΘͤΔ͜ͱͰΞϓϦέʔγϣϯΛߏ੒

Slide 7

Slide 7 text

Vueίϯϙʔωϯτͷྫ

{{ greeting }} World!

module.exports = { data () { return { greeting: 'Hello' } } } JavaScript
 (ES6) HTML

Slide 8

Slide 8 text

Vuex ετΞ • ΞϓϦέʔγϣϯͷঢ়ଶʢεςʔτʣΛҰݩ อ࣋͢Δ • ঢ়ଶͷมԽ͸ϛϡʔςʔγϣϯͷίϛοτʹ Αͬͯߦ͏ • ίϯϙʔωϯτຖʹঢ়ଶΛ࣋ͨͳͯ͘ࡁΉ
 (ύϥϝʔλͷड͚౉͕͠ෆཁʹͳΔ)

Slide 9

Slide 9 text

Vuex ετΞͷྫ const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) εςʔτ
 ύϥϝʔλ ϛϡʔςʔγϣϯ
 ૢ࡞

Slide 10

Slide 10 text

Vueίϯϙʔωϯτͷςετ

Slide 11

Slide 11 text

લఏɿ୯ମςετͷ3-A • Arrange (४උ)
 ॳظԽ͠ɺσʔλΛ४උ͢Δ • Act (࣮ߦ)
 ςετର৅ͱͳΔॲཧΛ࣮ߦ͢Δ • Assert (ݕূ)
 ༧ଌ௨Γʹಈ࡞͢Δ͜ͱΛݕূ͢Δ

Slide 12

Slide 12 text

Vueίϯϙʔωϯτͷ3A (1) Vue component Vuex state HTML • Vueίϯϙʔωϯτʹ VuexεςʔτΛೖྗͱ ͯ͠༩͑Δ͜ͱͰɺHTMLΛग़ྗ͢Δ • Arrange: VuexεςʔτɺAct: Vueίϯϙʔω ϯτɺAssert: HTML

Slide 13

Slide 13 text

Vueίϯϙʔωϯτͷ3A (2) Vue component Vuex state HTML Event • ΠϕϯτΛ༩͑ͨ৔߹ʢΫϦοΫͳͲʣ • Arrange: Vuexεςʔτ, Act: Πϕϯτ / Vueί ϯϙʔωϯτ, Assert: HTML / Vuexεςʔτ

Slide 14

Slide 14 text

Vueίϯϙʔωϯτͷςετཁ݅ • Vue ίϯϙʔωϯτ୯ମͰςετ͕Ͱ͖Δ • VuexετΞɺΠϕϯτͳͲΛਖ਼͘͠ѻ͑Δ • πʔϧͷಋೖ͕؆୯ͰɺΧόϨοδ΋औΕΔ • Jest ͱ vue-test-utilsͳΒશ͕ͯՄೳʂ

Slide 15

Slide 15 text

ςετͷπʔϧ
 (Jest / vue-test-utils)

Slide 16

Slide 16 text

Jest • JavaScriptͷςετϑϨʔϜϫʔΫ
 ʢFacebook੡, React΍YarnͳͲͰ΋ར༻) • ΦʔϧΠϯϫϯͰɺগͳ͍ઃఆͰར༻Ͱ͖Δ • ؆୯ʹΧόϨοδΛऔಘͰ͖Δ • Vue.jsͰ΋΋ͪΖΜར༻͕Մೳ

Slide 17

Slide 17 text

Jestͷίʔυྫ // sum.js function sum(a, b) { return a + b } module.exports = sum // sum.test.js import sum from './sum' test('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3) });

Slide 18

Slide 18 text

vue-test-utils • Vue.js޲͚ͷެࣜ୯ମςετϥΠϒϥϦ • VueίϯϙʔωϯτΛִ཭ͯ͠Ϛ΢ϯτͯ͠ಈ ࡞ͤ͞ɺςετΛߦ͏͜ͱ͕Ͱ͖Δ • JestΛ࢖ͬͨςετͷެࣜυΩϡϝϯτ͋Γ (https://vue-test-utils.vuejs.org/ja/guides/testing-SFCs-with-jest.html)

Slide 19

Slide 19 text

wrapper (vue-test-utils) • ίϯϙʔωϯτͱԾ૝ DOM Λςετ͢Δϝ ιουΛؚΉΦϒδΣΫτ • mount / shallowϝιουͰίϯϙʔωϯτΛ ࢦఆͯ͠ɺॳظԽ͢Δ • wrapper.findͰDOMΤϨϝϯτΛࢦఆͯ͠ɺ triggerͰΠϕϯτΛൃՐͤ͞Δ͜ͱ͕Մೳ

Slide 20

Slide 20 text

vue-test-utilsΛ༻͍ͨྫ test('close the app', () => { // Arrange const wrapper = shallow(TriggerButton) // Act wrapper.find('.close').trigger('click') // Assert expect(store.state.closed).toBe(true) })

Slide 21

Slide 21 text

Jestͱvue-test-utilsͷ ϓϩδΣΫτ΁ͷಋೖ

Slide 22

Slide 22 text

ύοέʔδͷΠϯετʔϧ • yarn add @vue/test-utils jest vue- jest babel-jest jest-serializer- vue --dev • jest.config.jsʹઃఆϑΝΠϧΛ௥Ճ • Rails 5.1ͷϓϩδΣΫτͰWebpackerΛ࢖༻ ͍ͯ͠ΔͷͰɺ༰қʹಋೖͰ͖ͨɻ

Slide 23

Slide 23 text

jest.config.js module.exports = { "moduleFileExtensions": [ "js", "json", "vue" ], "moduleNameMapper": { "^@/(.*)$": "/app/javascript/$1" }, "transform": { ".*\\.(vue)$": "/node_modules/vue-jest", "^.+\\.js$": "/node_modules/babel-jest" }, "snapshotSerializers": [ "/node_modules/jest-serializer-vue" ], "testRegex": "/app/javascript/test/.*\\.test\\.js$" }

Slide 24

Slide 24 text

·ͱΊ • Jestͱvue-test-utilsΛಋೖ͢Ε͹ɺ؆୯ʹ Vue.jsίϯϙʔωϯτͷ୯ମςετΛॻ͘͜ͱ ͕Ͱ͖Δɻ • ϑϩϯτΤϯυͷςετίʔυ΋ͲΜͲΜॻ ͍͍͖ͯ·͠ΐ͏ɻ