Typescript와 결합된 세 가지 적용 범위: React, Cypress e2e + Cypress CT 및 React Testing Library

이전 게시물에서 우리는 JS로 작성된 React 앱에서 세 가지 결합 커버리지를 다뤘습니다. 아아, Typescript는 결합된 코드 커버리지로 까다로울 수 있습니다. 우리는 책CCTDD: Cypress Component Test Driven Design에 나오는 React TS 앱을 사용하는 Typescript 예제로 시리즈를 계속합니다. 이 책에 내장된 애플리케이션은 TS에 있으며 Cypress e2e, CT 테스트 및 React Testing Library 미러를 포함합니다. repotour-of-heroes-react-cypress-ts에는 3중 결합 커버리지 설정이 있는 repo의 최종 버전이 있습니다. 코드 커버리지 이전의 repo 상태는 브랜치before-code-coverage에 있으며 이 가이드를 재현하기 위한 샘플PR이 있습니다.

Cypress 구성 요소 및 E2e 적용 범위 설정



패키지 추가



TS를 사용하면 패키지가 약간 다릅니다.

yarn add -D @babel/plugin-transform-modules-commonjs @babel/preset-env @babel/preset-react @babel/preset-typescript @bahmutov/cypress-code-coverage @cypress/instrument-cra  babel-loader istanbul istanbul-lib-coverage nyc


E2e용 앱 계측



이 스크립트는 반응 버전과 동일합니다.

"start": "react-scripts -r @cypress/instrument-cra start"


로컬 커버리지 평가를 위해 nyc 구성



구성을 위한 .nycrc 파일을 추가합니다. Jest에서 격리하기 위해 커버리지 보고서 디렉토리를 coverage-cy로 설정하고 있습니다. all 속성 계측은 테스트에서 건드리지 않은 파일도 포함합니다. excludeAfterRemapCypress code coverage package docs에 따라 true로 설정되어 제외된 파일이 통과하지 않도록 합니다. 여기에 빠른 reference to nyc docs이 있습니다.

{
  "excludeAfterRemap": true,
  "report-dir": "coverage-cy",
  "reporter": ["text", "json", "html"],
  "extension": [".ts", ".tsx", "js", "jsx"],
  "include": ["src/**/*.tsx", "src/**/*.ts", "src/**/*.jsx", "src/**/*.js"],
  "exclude": [
    "src/setupTests.ts",
    "src/**/*.test.tsx",
    "src/**/*.cy.ts",
    "src/**/*.cy.tsx",
    "src/**/*.d.ts",
    "src/reportWebVitals.ts"
  ]
}


코드 적용 범위에 대한 cypress.config.js 구성, 구성 요소 테스트를 위한 앱 계측



구성의 TS 버전에는 3가지 주요 차이점이 있습니다. 파일 시작 부분에서 @cypress/instrument-cra를 가져와야 합니다. 모듈 사전 설정에 @babel/preset-typescript를 포함해야 하며 테스트 속성은 JS 대신 TS여야 합니다.

import '@cypress/instrument-cra'
import {defineConfig} from 'cypress'
const codeCoverageTask = require('@bahmutov/cypress-code-coverage/plugin')

module.exports = defineConfig({
  projectId: '7mypio',
  experimentalSingleTabRunMode: true,
  retries: {
    runMode: 2,
    openMode: 0,
  },
  env: {
    API_URL: 'http://localhost:4000/api',
  },
  e2e: {
    specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
    baseUrl: 'http://localhost:3000',
    setupNodeEvents(on, config) {
      return Object.assign({}, config, codeCoverageTask(on, config))
    },
  },

  component: {
    setupNodeEvents(on, config) {
      return Object.assign({}, config, codeCoverageTask(on, config))
    },
    specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
    devServer: {
      framework: 'create-react-app',
      bundler: 'webpack',
      // here are the additional settings from Gleb's instructions
      webpackConfig: {
        // workaround to react-scripts 5 issue https://github.com/cypress-io/cypress/issues/22762
        devServer: {
          port: 3001,
        },
        mode: 'development',
        devtool: false,
        module: {
          rules: [
            // application and Cypress files are bundled like React components
            // and instrumented using the babel-plugin-istanbul
            {
              test: /\.ts$/,
              exclude: /node_modules/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: [
                    '@babel/preset-env',
                    '@babel/preset-react',
                    '@babel/preset-typescript',
                  ],
                  plugins: [
                    'istanbul',
                    ['@babel/plugin-transform-modules-commonjs', {loose: true}],
                  ],
                },
              },
            },
          ],
        },
      },
    },
  },
})

/* eslint-disable @typescript-eslint/no-unused-vars */


This is our preferred component test config because @babel/plugin-transform-modules-commonjs lets us customize webpack config, so that we can make all imports accessible from any file including specs. This allows to spy/stub a wider range of code in the component tests.



cypress/support/e2e.ts 및 cypress/support/component.ts 모두 구성



JS 앱에 무관심합니다.

import "@bahmutov/cypress-code-coverage/support";


package.json에 커버리지 편의 스크립트 추가



JS 버전과 동일한 편의 스크립트

"cov:combined": "yarn copy:reports && yarn combine:reports && yarn finalize:combined-report",
"copy:reports": "(mkdir reports || true) && cp coverage-cy/coverage-final.json reports/from-cypress.json && cp coverage/coverage-final.json reports/from-jest.json",
"combine:reports": "(mkdir .nyc_output || true) && yarn nyc merge reports && mv coverage.json .nyc_output/out.json",
"finalize:combined-report": "yarn nyc report --reporter html --reporter text --reporter json-summary --report-dir combined-coverage",
"cov:reset": "rm -rf .nyc_output && rm -rf reports && rm -rf coverage && rm -rf coverage-cy && rm -rf combined-coverage",


TS 버전에서는 로컬 통합 커버리지, CodeCov 서비스, Github Actions 설정에 차이가 없습니다.



가이드의 JS 변형에서 동일한 단계를 복제할 수 있습니다. CodeCov 비밀을 리포지토리에 추가해야 합니다. 다음은 codecov.yml 파일입니다.

codecov:
  notify:
    after_n_builds: 3
coverage:
  status:
    project:
      default:
        target: auto
        # this allows a 1% drop from the previous base commit coverage
        threshold: 2%
  # makes it so that unit, cy ct and cy e2e reports finish running before the report is shown in a PAR
  # https://docs.codecov.com/docs/notifications#preventing-notifications-until-after-n-builds
  ignore:
    - 'src/setupTests.ts'
    - 'src/**/*.test.tsx'
    - 'src/**/*.cy.ts'
    - 'src/**/*.cy.tsx'
    - 'src/**/*.d.ts'
    - './src/models'
    - 'src/reportWebVitals.ts'


cy.ts* 파일을 무시하는 jest


cy.ts* 파일의 적용 범위를 포함하지 않도록 Jest에 알려야 합니다. 이것은 package.json 스크립트에서 수행할 수 있습니다. 또한 e2e 테스트를 계측하기 위해 시작 스크립트를 수정해야 한다는 점을 기억하십시오.

"start": "react-scripts -r @cypress/instrument-cra start",
"test:coverage": "yarn test --watchAll=false --collectCoverageFrom=src/**/*.ts* --collectCoverageFrom=!src/**/*.*.ts* --coverage",

좋은 웹페이지 즐겨찾기