Vue 3 테스트용 Vite 플러그인



왜 테스트가 필요합니까?


  • 코드를 위반하면 오류가 발생함
  • 시간 절약(수동으로 테스트할 필요 없음)
  • 변경할 때마다 모든 것을 수동으로 테스트할 필요가 없기 때문에 개발 속도가 빨라집니다.

  • 빌드 작업 흐름에 통합
  • 코드 개선

  • Vite은 개발 중에 기본 ES 모듈 가져오기를 통해 코드를 제공하고 프로덕션을 위해 롤업과 함께 번들로 제공하는 독창적인 웹 개발 빌드 도구입니다.

    Vue-Test-Utils은 Vue 구성 요소를 테스트하기 위한 유틸리티입니다.

    목차


  • Getting Started
  • Adding Test
  • Create a Vite Plugin

  • 시작하기

    • Lets create a folder mkdir vue-testing
    • cd vue-testing then npm init -y
    • Install dependencies
     npm install [email protected]
     npm install vite @vue/test-utils@^2.0.0-beta.5 --save-dev
    
    • Create ./src/App.vue
     <template>
       <h1>
         Hello world!
       </h1>
     </template>
    
     <script>
     export default { 
      name: 'App'
     }
     </script>
    
    
    • Create ./src/main.js root director
    import {createApp} from 'vue'
    import App from './App.vue'
    
    createApp(App).mount('#app')
    
    • Add index.html
     <!DOCTYPE html>
     <html lang="en">
     </head>
       <body>
         <div id="app"></div>
         <script type="module" src="./src/main.js"></script>
       </body>
     </html>
    
    • Update or Add scripts to your package.json file
      "scripts": {
        "serve": "vite",
        ....
      }
    
    • Now we can run our application to make sure everything is working.
    npm run serve
    

    애플리케이션에 테스트 추가

    • Lets create a folder mkdir test
    • cd test
    • Create ./test/App.spec.js
    import { mount } from '@vue/test-utils'
    import App from '../src/App.vue'
    
     describe('App.spec.js', () => {
      it('renders', () => {
        const wrapper = mount(App, { attachTo: '#root' })
        expect(wrapper.html()).to.contain('Hello')
      })
     })
    
    • Create ./test/index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Vue Testing</title>
      <link href="https://unpkg.com/[email protected]/mocha.css" rel="stylesheet"/>
      <script src="https://unpkg.com/[email protected]/chai.js"></script>
      <script src="https://unpkg.com/[email protected]/mocha.js"></script>
      <style>
        #meta > * {
          margin: 20px 50px 0 50px;
          font-weight: 200;
          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        }
    
        #meta > h1 { font-size: 2em; }
        #meta > h2 { font-size: 1.5em; }
    
        #root {
          margin: 20px 50px 0 50px;
        }
      </style>
      <script>
        mocha.setup('bdd')
        window.expect = chai.expect
      </script>
    </head>
    <body>
      <div id="meta">
        <h2>Mocha HTML Reporter</h2>
        <div>
          <div id="mocha" style="margin: 0;"></div>
        </div>
      </div>
    
    </body>
    </html>
    
    • Add setup
      beforeEach(() => {
        delete window["__VUE_DEVTOOLS_TOAST__"]
    
        const existingRoot = document.getElementById('root')
        if (existingRoot) {
          existingRoot.innerHTML = ''
          return
        }
        const root = document.createElement('div')
        root.id = 'root'
        document.body.appendChild(root)
      })
    
      afterEach(() => {
        document.getElementById('root').remove()
      })
    
    • Load all spec or test files
    import('./test/App.spec.js').then(() => {
      mocha.setup({ reporter: 'html' })
      mocha.checkLeaks()
      mocha.run()
    })
    
    • Run the test
    npm run serve
    
    • Go to http://localhost:3000/test
    • Open the browser console, you will have expected error, vite can only process es module, and @babel/parser is commonjs module
    • Vite under the hood uses rollup to build Single File Component SFC , so lets use rollup to convert @babel/parser to es module
    • Create a file ./tools/babel-parser.js
    export { parse } from '@babel/parser'
    
    • Create rollup.config.js
    import resolve from '@rollup/plugin-node-resolve'
    import commonjs from '@rollup/plugin-commonjs'
    
    export default {
      input: './tools/babel-parser.js',
      plugins: [  commonjs(), resolve() ],
      output: {
        file: './node_modules/@babel/parser/index.js',
        format: 'es',
        sourcemap: true
      }
    }
    
    • Also create vite.config.js to create alias for @babel/parser and to use it later
    export default {
      alias: {
        '@babel/parser': '@babel/parser/index.js'
      }
    }
    
    • Add npm script to run the rollup
     "scripts": {
        ...
        "optimize": "rollup -c"
      },
    
    • Run npm run optimize and npm run serve

    Vite 플러그인 만들기

    • Create file ./tools/testPlugin.js
    import Router from 'koa-router'
    import fs from 'aria-fs'
    
    function getTestFiles() {
      const router = new Router()
    
      return ({ app }) => {
    
        router.get('/test-files', async (ctx, next) => {
          ctx.body = await fs.globFiles(`./test/**/*.spec.js`, true)
          await next()
        })
    
        app.use(router.routes())
      }
    }
    
    export default function testPlugin() {
      return {
        configureServer: [ getTestFiles() ]
      }
    }
    
    • Install dependencies
    npm install koa-router aria-fs --save-dev
    
    • Update vite.config.js
    import testPlugin from './tools/testPlugin'
    
    export default {
      alias: {
        '@babel/parser': '@babel/parser/index.js'
      },
      plugins: [ testPlugin() ]
    }
    
    • Update script in ./test/index.html
    (async function() {
    
      beforeEach(() => {
        delete window["__VUE_DEVTOOLS_TOAST__"]
    
        const existingRoot = document.getElementById('root')
        if (existingRoot) {
          existingRoot.innerHTML = ''
          return
        }
        const root = document.createElement('div')
        root.id = 'root'
        document.body.appendChild(root)
      })
    
      afterEach(() => {
        document.getElementById('root').remove()
      })
    
      const response = await fetch('/test-files')
      const files = await response.json()
    
      await Promise.all(files.map(file => import(file)))
    
      mocha.setup({ reporter: 'html' })
      mocha.checkLeaks()
      mocha.run()
    })()
    
    • Let's add another test Button increment, file ./src/Button.vue
    <template>
      <div>
        <p>Times clicked: {{ count }}</p>
        <button @click="increment">increment</button>
      </div>
    </template>
    
    <script>
      export default {
        name: 'Button',
        data: () => ({
          count: 0,
        }),
        methods: {
          increment() {
            this.count++
          },
        },
      }
    </script>
    
    • And test for our Button , ./tools/Button.spec.js
    import { mount } from '@vue/test-utils'
    import Button from '../src/Button.vue'
    
     describe('Button.spec.js', () => {
      it('increments value on click', async () => {
        const wrapper = mount(Button, { attachTo: '#root' })
        const button = wrapper.find('button')
    
        await button.trigger('click')
        expect(wrapper.find('p').html()).to.contain('Times clicked: 1')
      })
     })
    
    • Run npm run serve and go to http://localhost:3000/test

    좋은 웹페이지 즐겨찾기