TDD를 사용하여 Vue 구성 요소 작성: 부드러운 소개

본 강좌에서 우리는 테스트 구동 개발(TDD)의 기본 개념을 배우고 TypeScript을 사용하여 간단한 Vue 구성 요소를 구축하고 Jest를 사용하여 테스트를 하고 설정coverageContinuous Integration을 할 것이다.

소개


테스트 드라이브 개발(TDD)은 코드를 작성하기 전에 테스트를 작성하는 개발 과정이다.먼저 예상 행위를 설명하는 테스트를 작성하고 실행하여 실패를 확인한 다음 최소한의 코드를 작성하여 통과시킵니다.그 다음에 필요하면 코드를 정확하게 재구성할 수 있습니다.완성될 때까지 모든 기능을 반복합니다.이 과정은 개발자로 하여금 단원 테스트를 작성하고 코드를 작성하기 전에 사고를 하게 하여 건장한 코드를 발표하게 한다.image placeholder 구성 요소를 만들기 위한 코드를 작성할 때입니다. 이 구성 요소는 LoremFlickr 에서 이미지를 가져옵니다. 이것은 무작위 이미지를 가져오고 너비, 높이, 종류 (쉼표 구분값), 필터 등 인자를 지정하는 간단한 서비스입니다.url에서, 예를 들어 320x240 또는 Brazil 에서 Rio 이미지를 가져오면 https://loremflickr.com/320/240/brazil,rio

LoremFlickr에는 여러 가지 옵션이 있지만 이 강좌에서는 widthheight 만 사용하여 LoremFlickr에서 이미지를 가져오고 categories 를 눌러 필터링하는 간단한 구성 요소를 중점적으로 개발할 것입니다.
https://loremflickr.com/<width>/<height>/<categories>

항목 만들기


Vue CLI를 사용하여 항목 만들기vue-image-placeholder
vue create vue-image-placeholder
Manually select features, 선택 TypeScriptUnit testing 옵션
? Check the features needed for your project:
 ◉ Babel
 ◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◉ Unit Testing
 ◯ E2E Testing
기본 설정을 사용하고 테스트 프레임워크로 Jest 를 선택합니다.
🧹 항목 삭제assets, components 폴더와 App.vue 내부src를 정리하면 이 강좌는 필요하지 않습니다.

첫 번째 테스트 작성

tests/unit 에서 example.spec.tsimageplaceholder.spec.ts 로 이름을 바꾸고 첫 번째 테스트를 작성합니다.
우리는 ImagePlaceholder 구성 요소가 <img> 표시를 보여 주기를 희망합니다. 그 중에서 srcwidth, heightimages (클래스) 속성으로 구성되어 있습니다.
<ImagePlaceholder width=500 height=250 images="dog" />
렌더링해야 함
<img src="https://loremflickr.com/500/250/dog">
속성ImagePlaceholder, width: 500, height:200, images: 'newyork' 구성 요소가 img 구성 요소를 가지고 있는지 확인하는 첫 번째 테스트를 작성합니다.
import { shallowMount } from '@vue/test-utils'
import ImagePlaceholder from '@/ImagePlaceholder.vue'

describe('ImagePlaceholder.vue', () => {
  it('renders the correct url for New York images', () => {
    const wrapper = shallowMount(ImagePlaceholder, {
      propsData: { width: 500, height:200, images: 'newyork' }
    })
    expect(
      wrapper.findAll('img').at(0).attributes().src
    ).toEqual('https://loremflickr.com/500/200/newyork')
  })
})
하면, 만약, 만약...
yarn test:unit
src=https://loremflickr.com/500/200/newyork 구성 요소가 존재하지 않기 때문에 모든 작업이 예상대로 실패했습니다.
테스트를 통과하려면 구성 요소를 작성해야 합니다ImagePlaceholder
<template>
  <img :src="url">
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class ImagePlaceholder extends Vue {

  @Prop({required: true}) readonly width!: number
  @Prop({required: true}) readonly height!: number
  @Prop({required: true}) readonly images!: string

  get url() {
    return `https://loremflickr.com/${this.width}/${this.height}/${this.images}`;
  }

}
</script>
파일을 저장하고 다시 실행합니다ImagePlaceholder.vue.
yarn run v1.19.2
$ vue-cli-service test:unit
 PASS  tests/unit/imageplaceholder.spec.ts
  ImagePlaceholder.vue
    ✓ renders the correct url for New York images (46ms)


Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.428s
Ran all test suites.
✨  Done in 2.40s.
✅ 예!테스트 실행이 틀림없습니다!
방금 TDD를 사용하여 최소 yarn test:unit 구성 요소를 만들었습니다!
실제 작업 보기: ImagePlaceholder 에서 다음 코드를 복사하여 붙여넣기
import Vue from 'vue'
import ImagePlaceholder from './ImagePlaceholder.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(
    ImagePlaceholder,
    {
      props : {
        width: 500,
        height:200,
        images: 'newyork'
      }
    }),
}).$mount('#app')
그리고 뛰기main.ts!

TDD를 사용하여 구성 요소 개선

yarn serve 어셈블리에 새 피쳐를 추가하려는 경우 ImagePlaceholder 속성이 지정되지 않은 경우 "random" 범주를 사용합니다.이 기능이 있습니다.
<ImagePlaceholder width=500 height=200 />
렌더링해야 함
<img src="https://loremflickr.com/500/200/random">
이것은 아래 테스트에서 예상한 행위이다
  it('renders the correct url for Random images if not specified', () => {
    const wrapper = shallowMount(ImagePlaceholder, {
      propsData: { width: 500, height:200 }
    })
    expect(
      wrapper.findAll('img').at(0).attributes().src
    ).toEqual('https://loremflickr.com/500/200/random')
  })
❌ 실행images 후 이 오류가 발생합니다.
  ● ImagePlaceholder.vue › renders the correct url for Random images if not specified

    expect(received).toEqual(expected) // deep equality

    Expected: "https://loremflickr.com/500/200/random"
    Received: "https://loremflickr.com/500/200/undefined"
TDD 이후에 테스트를 통과하기 위해 코드를 다시 작성할 때가 되었다. 지금은 yarn test:unitprop이 필요하지 않으며, images는 기본값이어야 한다.
  //...
  @Prop({required: false, default: 'random'}) readonly images!: string
  //...
✅ 테스트를 다시 실행하면 예상대로 통과됩니다!
만약 지정되지 않았다면, 어떻게 사각형 이미지를 지원하여 "random"height 와 같게 합니까?실패한 테스트 다시 작성
  it('renders a square image if height is not specified', () => {
    const wrapper = shallowMount(ImagePlaceholder, {
      propsData: { width: 500 }
    })
    expect(
      wrapper.findAll('img').at(0).attributes().src
    ).toEqual('https://loremflickr.com/500/500/random')
  })
그리고 최소한의 코드를 작성해서 통과시키세요.
@Component
export default class ImagePlaceholder extends Vue {

  @Prop({required: true}) readonly width!: number
  @Prop({required: false}) readonly height!: number
  @Prop({required: false, default: 'random'}) readonly images!: string

  get url(): string {
    let height = this.height;
    if (!this.height) {
      height = this.width;
    }
    return `https://loremflickr.com/${this.width}/${height}/${this.images}`
  }

}
✅ 테스트 통과!
우리는 이 새로운 특성에 대해 테스트를 진행했고, 그것을 통과할 수 있는 최소 코드를 제공했다.우리는 약간의 재구성을 진행할 수 있다!👨🏻‍💻
export default class ImagePlaceholder extends Vue {

  @Prop({required: true}) readonly width!: number
  @Prop({required: false}) readonly height!: number
  @Prop({required: false, default: 'random'}) readonly images!: string

  get url(): string {
    return `https://loremflickr.com/${this.width}/${this.height || this.width}/${this.images}`;
  }

}
✅ 테스트 다시 통과!우리는 출력에 영향을 주지 않는 상황에서 코드를 성공적으로 재구성했다.
당신이 원하는 모든 것을 실현하기 위해 이 과정을 교체합니다!기억해라: 네가 원하는 것을 생각해 봐라. 먼저 테스트를 써서 실패하게 하고, 가장 적은 코드를 써서 통과하게 해라!그리고 필요에 따라 코드를 재구성합니다.
너는 찾을 수 있다the complete code on GitHub

코드 덮어쓰기 추가


코드 덮어쓰기는 자동 테스트가 실행될 때 실행되는 코드의 줄 수, 지점 수, 문장 수를 측정하는 것이다.테스트 범위가 낮은 프로그램에 비해 코드 범위가 높은 프로그램은 오류가 검출되지 않을 가능성이 낮다.
Jest는 외부 도구 없이 코드 덮어쓰기를 쉽게 생성할 수 있습니다.이 기능을 사용하려면 width 파일에 행을 추가하여 덮어쓸 파일을 지정합니다.
module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
  collectCoverage: true,
  collectCoverageFrom: ["src/**/*.vue", "!**/node_modules/**"]
}
다시 실행jest.config.json, 테스트 결과에 앞서 덮어쓰기 보고서를 얻을 수 있습니다.
----------------------|----------|----------|----------|----------|-------------------|
File                  |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------------|----------|----------|----------|----------|-------------------|
All files             |      100 |      100 |      100 |      100 |                   |
 ImagePlaceholder.vue |      100 |      100 |      100 |      100 |                   |
---------------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        5.688s
Ran all test suites.
✨  Done in 8.70s.
⚠️ Jest에서 생성한 yarn test:unit 폴더를 /coverage에 추가하는 것을 기억하십시오.

지속적인 통합


지속적인 통합(CI)은 개발 실천으로 개발자가 코드를 공유 저장소에 자주 집적하기 때문에 하루에 몇 번 집적하는 것이 가장 좋다.그리고 자동 구축과 자동 테스트를 통해 모든 통합을 검증할 수 있다.목표는 비교적 작은 증량 개발과 테스트를 통해 더욱 건강한 소프트웨어를 구축하는 것이다.이것이 바로 TravisCI 같은 지속적인 통합 플랫폼의 용무지이다.
우리는 코드 커버율을 감시하기 위해 또 다른 유용한 서비스Codecov가 필요하다.
TravisCI와 Codecov는 Github와 통합되어 있으며 등록하고 서비스에 항목을 추가하기만 하면 됩니다.코드에서 CI를 활성화하려면 특수 파일.gitignore이 필요하며 TravisCI에서 구축을 수행하는 방법을 알려야 합니다.
language: node_js
node_js:
  - 10
before_script:
  - yarn add codecov
script:
  - yarn test:unit
after_script:
  codecov
이런 절차에 따라 트라비시는
  • 설정 환경(.travis.yml
  • 설치 종속성node_js 10
  • 적용 범위 테스트(before_script절)
  • Codecov(script 섹션에 덮어쓰기 보고서 보내기
  • 설치 프로그램 생성


    이제 구성 요소를 준비했습니다. 구축 과정을 설정해야 합니다.after_script 파일에서 package.json 스크립트를 수정하고 build 스크립트를 삭제합니다.
      "scripts": {
        "build": "vue-cli-service build --target lib --name vue-image-placeholder src/main.ts",
        "test:unit": "vue-cli-service test:unit",
        "lint": "vue-cli-service lint"
      },
    
    어셈블리를 내보내려면 해당 변경serve 파일--target lib이 필요합니다.
    import ImagePlaceholder from './ImagePlaceholder.vue'
    
    export default ImagePlaceholder
    
    main.ts라는 파일을 포함하는 폴더 추가types
    declare module 'vue-image-placeholder' {
      const placeholder: any;
      export default placeholder;
    }
    
    index.d.tsmaintypings 참조 증가
      "main": "./dist/vue-image-placeholder.common.js",
      "typings": "types/index.d.ts",
    
    package.json에 입력해야 함disable automatic polyfill injection
    module.exports = {
      presets: [
        ['@vue/app', {
          useBuiltIns: false
        }]
      ]
    }
    
    babel.config.js"include" 부분에서 테스트 파일을 삭제합니다.
    운영 운영을 위한 라이브러리 구축
    yarn build
    
    ⠦  Building for production as library (commonjs,umd,umd-min)...
    
     DONE  Compiled successfully in 20857ms                                                               11:37:47 PM
    
      File                                     Size             Gzipped
    
      dist/vue-image-placeholder.umd.min.js    8.50 KiB         3.16 KiB
      dist/vue-image-placeholder.umd.js        42.33 KiB        11.76 KiB
      dist/vue-image-placeholder.common.js     41.84 KiB        11.60 KiB
    
    📦 구축 완료!
    그것을 사용하려면 로컬의 다른 응용 프로그램에 설치하십시오tsconfig.json
    yarn add ../vue-image-placeholder
    
    구성 요소 사용
    <template>
      <div id="app">
        <h1>Welcome to the Vue Image Placeholder demo!</h1>
        <ImagePlaceholder width=500 />
      </div>
    </template>
    
    <script>
    import ImagePlaceholder from 'vue-image-placeholder';
    
    export default {
      name: 'App',
      components: {
        ImagePlaceholder
      }
    }
    </script>
    

    Here 공식 환매를 찾을 수 있습니다.
    이미지

    좋은 웹페이지 즐겨찾기