Все знают, что написание тестов очень важно для разработки программного обеспечения. Это позволяет нам менять коды быстрее и с меньшим количеством ошибок.

Когда дело доходит до внешнего интерфейса, React Testing Library становится популярным, потому что на нем легче тестировать перехватчики React по сравнению с enzyme. Однако статей, объясняющих это с помощью TypeScript, недостаточно.

Итак, в этом руководстве основное внимание уделяется тому, как писать тесты на TypeScript с React Testing Library.

Если вы хотите узнать о других темах библиотеки тестирования React, обратитесь к статьям ниже.

Библиотека тестирования React

Он был создан Кентом Си Доддсом, который работает в PayPal как пионер внешнего интерфейса TDD. Первый принцип библиотеки тестирования React:

Чем больше ваши тесты похожи на то, как используется ваше программное обеспечение, тем больше уверенности они могут вам дать.

Он предполагает, что ваш тест должен работать так, как действует пользователь, а не как реализовано ваше приложение.

Пакет React Testing Library (называемый @testing-library/react) является одним из семейства @testing-library. Базовая библиотека семейства @testing-library/dom предоставляет общие API для React, Anguler, Vue. Но если вы используете такой фреймворк, как React, вам следует использовать библиотеку-оболочку @testing-library/react.

А для тестовой среды говорится, что React Testing Library может работать в любой тестовой среде. С другой стороны, поскольку многие статьи и люди используют его с JEST, это руководство также используется с JEST.

Установить демонстрационное приложение

Поскольку лучше писать код самому, подготовлено демонстрационное приложение под названием My Pokemon.

Технологический стек ниже.

  • Реагировать
  • Машинопись
  • реагирующий маршрутизатор
  • Redux
  • Материал-UI
  • другие (webpack, babel, eslint, prettier, PokéAPI)

Поскольку я хотел бы объяснить, как писать тесты с помощью Redux, response-router и Material-UI, технический стек немного сложен.

Вы можете просматривать Pokedex и добавлять любимых покемонов как My Pokemons.

  • Дом: "/"

  • Покедекс: «/ покемоны»

  • PokemonDetail: «/ pokemons /: id»

  • Мои покемоны: «/ my_pokemons»

Пожалуйста, клонируйте это репо, если хотите.

git clone https://github.com/egurinko/react-testing-library-demo.git

Установить пакеты

Давайте добавим пакеты для React-Testing-Library. То, что вам нужно, находится ниже.

yarn add -D @testing-library/react @testing-library/jest-dom jest

@testing-library/jest-dom предоставляет настраиваемые сопоставители DOM для JEST. Это облегчает вашу тестовую жизнь.

Для TypeScript вам следует добавить несколько пакетов.

yarn add -D ts-jest @types/jest @types/testing-library__react @types/testing-library__jest-dom

@types пакеты - это файлы типов каждого пакета. ts-jest - это препроцессор JEST для TypeScript. Это позволяет вам выполнять проверку типов.

Настраивать

Сначала установите Jest и TypeScript! Просто запустите одну команду ниже. Он создает файл конфигурации jest (jest.config.js) с настройкой TypeScript.

yarn ts-jest config:init

Перед написанием тестов добавьте eslint параметр, если он вам нужен, потому что eslint не знает кодов тестовой среды.

// .eslintrc.json
{
  ...
  "env": {
    "browser": true,
    "jest": true       // ADD THIS
  }
  ...
}

Напишем первый тест. Поскольку я хотел бы создать тестовые файлы в каталоге src, создайте тестовый каталог с именем __test__. JEST автоматически определяет, что файлы в __test__ являются тестовыми.

// src/__test__/integration/first.spec.ts
it('runs the first test', () => {
  expect(true).toBe(true);
});

Поскольку обычно создаются другие типы файлов, такие как конфигурации, макеты, я обычно создаю каталог интеграции для чисто тестовых файлов.

Чтобы легко запустить тест JEST, я рекомендую вам создать сценарий пряжи, как показано ниже.

// package.json
....
"scripts": {
  ....
  "check-types": "tsc",
  "test": "jest"
}
....

Итак, готов к запуску первого теста. Просто сделай это!

yarn test
$ jest
 PASS  src/__test__/integration/first.spec.ts
  ✓ runs the first test (2ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.141s, estimated 3s
Ran all test suites.
✨  Done in 3.50s.

Поздравления 🎉🎉

Напишите первый тест с помощью библиотеки тестирования React

Приведенный выше тест не является тестом библиотеки тестирования React. Это просто тест JEST. Итак, давайте напишем простой компонентный тест с помощью React Testing Library.

Самый простой компонент в моем репозитории покемонов - это src/components/NotFound.tsx. Он имеет простой HTML-тег и текст. Без Redux, без Material UI, без response-router, но с TypeScript.

// src/components/NotFound.tsx
import React from 'react';
const NotFound: React.FC<{}> = () => (
  <div>
    <h1>Not Found</h1>
    <h1>404</h1>
  </div>
);
export default NotFound;

Поэтому, пожалуйста, переименуйте первый тест в notFound.spec.tsx и напишите простой тест.

// src/__test__/notFound.spec.tsx
import * as React from 'react';
import { render, RenderResult } from '@testing-library/react';
import NotFound from '../../components/NotFound';
let documentBody: RenderResult;
describe('<NotFound />', () => {
  beforeEach(() => {
    documentBody = render(<NotFound />);
  });
  it('shows not found message', () => {
    expect(documentBody.getByText('Not Found')).toBeInTheDocument();
    expect(documentBody.getByText('404')).toBeInTheDocument();
  });
});

render API отображает компонент, который вы передали в качестве аргумента в document.body. Возвращает RenderResult. Если вас больше интересует RenderResult, проверьте его самостоятельно. Вы можете узнать, что можно делать с render API.

Итак, давайте проведем тест.

Умм 🤔 Там написано using the wrong test environment. Consider using the "jsdom" test environment. Это потому, что текущая среда установлена ​​как node в jest.config.js.

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

Но среда узлов не может обрабатывать DOM. Поэтому, пожалуйста, измените testEnvironment на jsdom.

По-прежнему получаю ошибку 🤔

Это потому, что toBeInTheDocument сопоставитель происходит от @testing-library/jest-dom. Если вы импортируете @testing-library/jest-dom, тест пройдет успешно.

Однако записывать предложение об импорте во весь файл непродуктивно. Итак, давайте создадим конфигурацию JEST, чтобы разрешить глобальный импорт @testing-library/jest-dom.

Сначала создайте файл конфигурации.

// src/__test__/config/importJestDOM.ts
import '@testing-library/jest-dom';

И добавьте файл в setupFilesAfterEnv jest.config.js, как показано ниже.

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv:['<rootDir>/src/__test__/config/importJestDOM.ts']
};

Если вы используете setupFilesAfterEnv, вы можете запускать любой модуль перед выполнением каждого тестового файла.

Теперь пройдет первое испытание !!

PASS  src/__test__/integration/notFound.spec.tsx
  <NotFound />
    ✓ shows not found message (23ms)
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.48s, estimated 4s
Ran all test suites.
✨  Done in 2.58s.

Моментальный тест для фиксированного текста

Если вы хотите протестировать фиксированные тексты в приложении, вам не нужно твердо писать фиксированный текст в тестах, потому что вы должны управлять фиксированными текстами как в приложении, так и в тестах.

В такой ситуации эффективен тест снимков. Вы делаете снимок компонента и фиксируете его на GitHub. Если фиксированный текст изменен, просто обновите снимок и снова зафиксируйте его.

Сам код очень простой.

// src/__test__/integration/notFound.spec.tsx
.....
describe('<NotFound />', () => {
  beforeEach(() => {
    documentBody = render(<NotFound />);
  });
  it('matches snapshot', () => {
    const { baseElement } = documentBody;
    expect(baseElement).toMatchSnapshot();
  });
})

Вам больше не нужно писать фиксированные тексты в тесте.

При первом запуске теста моментального снимка будут созданы каталог __snapshot__ и файл .snap, как показано ниже.

// src/__test__/integration/__snapshots__/notFound.spec.tsx.snap
exports[`<NotFound /> matches snapshot 1`] = `
  <body>
    <div>
      <div>
        <h1>Not Found</h1>
        <h1>404</h1>
      </div>
    </div>
  </body>
`;

Когда вы что-то обновляете, ваш тест не проходит. Но если это преднамеренное изменение, вы можете запустить тест с опцией --updateSnapshot и зафиксировать его.

※ Внимание
Тест снимков очень прост, но имеет некоторые недостатки для большого компонента. Если вы хотите узнать эффективный снимок, перейдите по ссылке



Дополнительно: обработка статических активов

Потому что в примере NotFound нет статических ресурсов, таких как таблицы стилей и изображения. Но если вы протестируете с ними компонент, он потерпит неудачу, потому что шутка не может разобрать.

Чтобы избежать этой ошибки, вы должны имитировать статические активы.



В этом примере создайте фиктивные файлы.

// src/__test__/mock/styleMock.ts
export default {};
// src/__test__/mock/fileMock.ts
export default "test-file-stub";

И используйте их в moduleNameMapper ofjest.config.js. ModuleNameMapper заменяет некоторые модули указанными вами.

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/src/__test__/config/importJestDOM.ts'],
  moduleNameMapper: {
    "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/__test__/mock/fileMock.ts",
    "\\.(css|less)$": "<rootDir>/src/__test__/mock/styleMock.ts"
  }
};

С помощью этой опции вы можете включать статические ассеты в свои тесты 🎉

В этой статье рассказывается, как настроить JEST и библиотеку тестирования React с помощью TypeScript, а также запустить первый тест. Поскольку я написал другие статьи о React Testing Library, посмотрите ее, если хотите.

Спасибо !

использованная литература

Примечание из JavaScript In Plain English

Мы запустили три новых издания! Проявите любовь к нашим новым публикациям, подписавшись на них: AI на простом английском, UX на простом английском, Python на простом английском - спасибо и продолжайте учиться!

Мы также всегда заинтересованы в продвижении качественного контента. Если у вас есть статья, которую вы хотели бы отправить в какую-либо из наших публикаций, отправьте нам электронное письмо по адресу [email protected] с вашим именем пользователя Medium, и мы добавим вас в качестве автора. Также сообщите нам, к каким публикациям вы хотите быть добавлены.