🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Подробное руководство по внедрению TDD в рабочий процесс и использованию продвинутых возможностей Jest. С примерами кода и пояснениями каждого шага.
🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Привет, друзья! Я – Кирилл Мыльников, frontend-разработчик в ГК Юзтех. Сегодня стартует вторая часть увлекательного путешествия в мире тестирования с помощью Jest. Если вы пропустили первую часть, не беда, ссылку на нее оставлю тут. Мы начнем с краткого обзора теории и сразу перейдем к конкретным примерам. Весь код с примерами будет выкладываться на GitHub для вашего удобства.

В данной статье разберем следующие темы:

  • TDD – что это?
  • Практический пример использования
  • Расширенные возможности Jest

TDD – что это такое?

Test Driven Development методология разработки программного обеспечения, основанная на принципах тестирования.

Основная идея TDD – Интеграция тестирования с самых ранних этапов разработки играет ключевую роль в минимизации ошибок и повышении качества программного обеспечения. Поддерживая постоянное тестирование на всех стадиях процесса разработки, мы обеспечиваем более стабильный и надежный продукт. Давайте продолжим интеграцию тестирования на каждом этапе разработки для достижения оптимальных результатов.

Процесс TDD

TDD
TDD

Выделим с вами сразу несколько положительных сторон и укажем их в виде мемов :)

Повышение продуктивности – Благодаря тому, что ошибки выявляются на ранних этапах благодаря тестированию, время, затраченное на исправление дефектов, значительно сокращается. Это позволяет сэкономить ресурсы команды разработки и ускорить выпуск продукта на рынок.

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

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

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Долгосрочная поддержка кода – Обширный набор тестов упрощает процесс внесения изменений в проект, что минимизирует риски нарушения работы существующего функционала. Это способствует гибкости разработки и повышению стабильности программного обеспечения.

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Разобрали тему TDD в теории, давайте приступим к практике

Практический пример использования и с чего начать?

Мы начнем разработку с написания тестов. Давайте возьмем поле email в качестве примера и определим базовые требования к нему. Далее мы составим тесты, чтобы протестировать это поле. Давайте приступим!

Пример:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

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

Пример с тестом:

        import { validateEmail } from "./validateEmail";

describe("validateEmail", () => {
  it("should return true for valid email", () => {
    expect(validateEmail("test@example.com")).toBe(true);
  });

  it("should return false for invalid email", () => {
    expect(validateEmail("")).toBe(false);
    expect(validateEmail("testexample.com")).toBe(false);
    expect(validateEmail("test@example@example.com")).toBe(false);
    expect(validateEmail("test@example")).toBe(false);
    expect(validateEmail("test@192.168.1.1")).toBe(false);
  });

  it("should return true for email with dot at the end", () => {
    expect(validateEmail("test@example.com.")).toBe(true);
  });

  it("should return true for email with plus sign", () => {
    expect(validateEmail("test+example@example.com")).toBe(true);
  });

  it("should return true for email with special character in local part", () => {
    expect(validateEmail("test!example@example.com")).toBe(true);
  });
});
    

Пример с функцией validateEmail:

        export const validateEmail = (email: string) => {};
    

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

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

После чего можем писать уже функционал и поэтапно запускать тесты

Пример:

        export function validateEmail(email: string) {
  if (!email) {
    return false;
  }
  const emailRegex =
    /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  return emailRegex.test(email);
}
    

Результат:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Изменение требований (рефакторинг)

Теперь, при изменении требований, необходимо не только выводить общую ошибку "Неверный email", но также точно подсвечивать клиенту, что именно было введено некорректно. После изменения требований потребуется провести рефакторинг, так как после запуска тестов они упадут.

Новые требования:

  1. Отображать текст ошибки когда пустое поле: "Email should not be empty."
  2. Отображать текст ошибки если отсутствует символ "@": "Invalid email format. Please include '@' symbol."

Пример:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

После рефакторинга

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Тесты, которые были добавлены:

         it('should return "Email should not be empty" for empty email', () => {
    expect(validateEmail("")).toBe(validationEmailMessage.length);
  });

  it('should return "Invalid email format. Please include "@" symbol." for invalid email', () => {
    expect(validateEmail("testexample.com")).toBe(
      validationEmailMessage.format
    );
  });
    

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

  • Несколько конфигов
  • Shapshot тестирование
👨‍💻🎨 Библиотека фронтендера
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека фронтендера»

Несколько конфигов

Есть ситуации, когда нам нужно 2 разных jest конфига, например отдельный конфиг для unit-тестов и отдельный конфиг для интеграционных тестов. Соответственно можем их настраивать по-разному, хранить в разных папках, создавать разные расширения для файлов и т. д. Давайте перейдем сразу к практике, у нас есть уже один файл jest конфига, создаем второй под названием jest.integration.config и пропишем сразу настройки.

        import type { Config } from "jest";


const config: Config = {
  verbose: true,
  preset: "ts-jest",
  collectCoverage: true,
  collectCoverageFrom: [
    "<rootDir>/*.{js,ts}",
    "!**/node_modules/**",
    "!<rootDir>/*.mock*",
    "!<rootDir>/*.config.*",
  ],
   testMatch: ["<rootDir>/src/**/*.spec.ts"],
};


export default config;
    

Обратите внимание на testMatch, где наши интеграционные тесты будут лежать с расширением spec. Чтобы по разному запускать тесты, нужно это указать в scripts

Пишем тесты уже с расширением spec и запускаем их. Подробно можно посмотреть тут

Пример:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Snapshot тестирование – это подход к тестированию, который фиксирует вывод или состояние приложения и сравнивает его с ранее сохраненным снимком. Этот метод тестирования опциональный, используется не всегда.

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

Пример:

        type User = {
  name?: string;
  lastName?: string;
  age?: number;
  phone?: string;
  email?: string;
};
export const createUser = ({ name, lastName, age, phone, email }: User) => {
  return {
    name,
    phone,
    email,
    age,
    lastName,
  };
};

    

Теперь давайте напишем к нему тесты и запустим

Пример:

        import { createUser } from "./createUser";


describe("createUser", () => {
  it("should create user with firstname and lastname", () => {
    const user = createUser({ name: "Kirill", lastName: "Korobov" });
    expect(user).toMatchSnapshot();
  });
});

    

Здесь с вами создаем пользователя и когда запустим тесты, то сделается снимок нашего теста

Результат:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

Теперь давайте просто в нашей функции удалим одно значение и заново запустим тесты. Я удалил поле name и теперь снепшот-тесты падают, т. к. ожидалось это поле.

Пример:

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2

А если вы вправду удалили это поле и оно больше не нужно, тогда нужно обновить снепшоты, в моем случае командой yarn start -u

Обновленный снепшот файл

🧪 Успешное тестирование: TDD и расширенные возможности с Jest. Часть 2
***

Итак, мы с вами разобрали, что такое TDD и увидели все это на примере. Рассмотрели более продвинутые возможности Jest. Впереди нас ждет 3 часть статьи уже на примере React приложения.

Материалы:

GitHubhttps://github.com/kirill0202/Jest

Jest https://jestjs.io/

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ