E2E тестирование

E2E (End-to-End) тестирование предназначено для проверки полного пользовательского сценария работы компонента автодополнения в условиях, максимально приближенных к реальной эксплуатации. В отличие от модульных тестов, которые проверяют отдельные методы и функции, и интеграционных тестов, контролирующих взаимодействие нескольких частей системы, E2E-тесты исследуют поведение всей страницы целиком через браузер.

Для библиотеки Awesomplete такой подход особенно важен, поскольку её работа зависит сразу от нескольких факторов:

  • пользовательского ввода;
  • событий клавиатуры;
  • событий мыши;
  • структуры DOM;
  • CSS-оформления;
  • загрузки данных;
  • взаимодействия с сервером;
  • сторонних библиотек.

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


Что именно проверяется в E2E тестах

Для компонентов автодополнения обычно тестируются следующие сценарии:

Отображение списка подсказок

После ввода текста пользователь должен увидеть список вариантов.

Пример сценария:

  1. Открыть страницу.
  2. Найти поле ввода.
  3. Ввести символы.
  4. Дождаться появления выпадающего списка.
  5. Убедиться, что список содержит ожидаемые элементы.

Проверяется не внутренняя логика Awesomplete, а фактическое поведение интерфейса.


Выбор элемента мышью

Пользователь может кликнуть по одной из подсказок.

Проверяется:

  • появление списка;
  • наличие нужного элемента;
  • реакция на клик;
  • изменение значения поля.

Например:

await page.click(".item");

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


Выбор через клавиатуру

Awesomplete активно использует навигацию клавиатурой.

Необходимо проверять:

  • стрелки вверх и вниз;
  • Enter;
  • Tab;
  • Escape.

Типичный пользовательский сценарий:

Ввод текста
↓
Стрелка вниз
↓
Выбор подсказки
↓
Enter

После завершения сценария тест должен подтвердить корректность выбранного значения.


Закрытие списка

Список должен исчезать в определённых ситуациях:

  • после выбора элемента;
  • после нажатия Escape;
  • после потери фокуса;
  • после удаления текста.

Тесты проверяют отсутствие выпадающего меню в DOM либо его скрытое состояние.


Работа с удалёнными данными

Многие проекты используют Awesomplete совместно с AJAX-запросами.

Типичная схема:

Пользователь вводит текст
↓
Fetch-запрос
↓
Получение данных
↓
Обновление списка
↓
Показ подсказок

E2E-тест проверяет весь процесс целиком.


Популярные инструменты для E2E тестирования

Cypress

Один из самых популярных инструментов для тестирования пользовательских интерфейсов.

Особенности:

  • простой API;
  • автоматическое ожидание элементов;
  • удобная отладка;
  • встроенные снимки состояния приложения.

Пример:

cy.visit("/");

cy.get("#country")
  .type("Kaz");

cy.get(".awesomplete ul li")
  .should("contain", "Kazakhstan");

Playwright

Современный инструмент от Microsoft.

Преимущества:

  • высокая скорость;
  • поддержка нескольких браузеров;
  • стабильность;
  • удобная работа с ожиданиями.

Пример:

await page.goto("/");

await page.fill("#country", "Kaz");

await expect(
    page.locator(".awesomplete ul li")
).toContainText("Kazakhstan");

Selenium

Классический инструмент автоматизации браузеров.

Несмотря на возраст, продолжает использоваться в крупных корпоративных системах.

Преимущества:

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

Подготовка тестового окружения

Перед запуском E2E-тестов необходимо обеспечить предсказуемую среду выполнения.

Обычно используются:

  • тестовая база данных;
  • тестовый сервер;
  • фиксированные наборы данных;
  • предсказуемые ответы API.

Пример списка стран:

[
    "Kazakhstan",
    "Canada",
    "China",
    "Japan"
]

Если данные меняются между запусками, тесты становятся нестабильными.


Проверка локального массива данных

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

HTML:

<input id="country">

Jav * aScript:

new Awesomplete(
    document.getElementById("country"),
    {
        list: [
            "Kazakhstan",
            "Canada",
            "China"
        ]
    }
);

E2E-тест:

cy.visit("/");

cy.get("#country")
    .type("Ka");

cy.contains("Kazakhstan")
    .should("exist");

Проверяется полный цикл работы интерфейса.


Проверка выбора элемента

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

Пример Cypress:

cy.get("#country")
    .type("Ka");

cy.contains("Kazakhstan")
    .click();

cy.get("#country")
    .should(
        "have.value",
        "Kazakhstan"
    );

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


Проверка навигации клавиатурой

Многие пользователи практически не используют мышь.

Поэтому необходимы тесты клавиатурного управления.

Пример:

cy.get("#country")
    .type("Ka")
    .type("{downarrow}")
    .type("{enter}");

Проверка результата:

cy.get("#country")
    .should(
        "have.value",
        "Kazakhstan"
    );

Тестирование асинхронной загрузки данных

Предположим, список загружается через API.

Код приложения:

fetch("/countries")
    .then(r => r.json())
    .then(data => {
        awesomplete.list = data;
    });

В E2E-тесте желательно перехватывать сетевые запросы.

Пример Cypress:

cy.intercept(
    "GET",
    "/countries",
    [
        "Kazakhstan",
        "Canada",
        "China"
    ]
);

После этого тест полностью контролирует источник данных.


Использование моков

Настоящие серверы могут:

  • работать медленно;
  • быть недоступными;
  • возвращать случайные данные.

Поэтому в E2E-тестировании часто используются моки.

Пример:

cy.intercept(
    "GET",
    "/countries",
    {
        fixture: "countries.json"
    }
);

Преимущества:

  • воспроизводимость;
  • стабильность;
  • высокая скорость выполнения.

Проверка пустого результата

Если совпадений нет, список не должен отображаться.

Тест:

cy.get("#country")
    .type("ZZZZ");

Проверка:

cy.get(".awesomplete ul")
    .should("not.be.visible");

Либо:

cy.get(".awesomplete li")
    .should("have.length", 0);

Проверка минимальной длины ввода

Многие конфигурации используют параметр:

minChars: 3

Тогда список не должен открываться раньше достижения порога.

Проверка:

cy.get("#country")
    .type("Ka");

Ожидание:

cy.get(".awesomplete li")
    .should("not.exist");

После ввода третьего символа:

cy.get("#country")
    .type("z");

Проверка:

cy.get(".awesomplete li")
    .should("exist");

Проверка фильтрации

Тестирование фильтрации позволяет убедиться в корректной работе поиска.

Исходные данные:

[
    "Kazakhstan",
    "Canada",
    "China"
]

Ввод:

Ca

Ожидаемый результат:

Canada

Тест должен убедиться, что лишние элементы отсутствуют.


Проверка специальных символов

Нередко ошибки появляются при вводе специальных символов.

Проверяем:

-
_
'
"
(
)
+
#
@

Пример:

cy.get("#search")
    .type("@");

Тест подтверждает отсутствие исключений и зависаний интерфейса.


Проверка Unicode

Современные приложения работают с многоязычными данными.

Примеры значений:

[
    "Қазақстан",
    "Россия",
    "日本",
    "العربية"
]

Тесты должны подтверждать корректное отображение и выбор таких элементов.


Проверка мобильных устройств

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

Особенно важно проверять:

  • виртуальную клавиатуру;
  • сенсорные события;
  • изменение размеров экрана;
  • адаптивный интерфейс.

Пример Playwright:

const context =
    await browser.newContext({
        viewport: {
            width: 375,
            height: 667
        }
    });

Проверка производительности интерфейса

Хотя полноценное нагрузочное тестирование не относится к E2E, некоторые показатели полезно контролировать.

Например:

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

Пример:

const start = Date.now();

await page.fill(
    "#country",
    "Ka"
);

await page.waitForSelector(
    ".awesomplete li"
);

const duration =
    Date.now() - start;

Полученное время можно сравнивать с допустимыми пределами.


Борьба с нестабильными тестами

Flaky-тесты являются одной из главных проблем E2E автоматизации.

Причины:

  • асинхронность;
  • сетевые задержки;
  • анимации;
  • случайные данные;
  • неправильные ожидания.

Нестабильный пример:

await page.fill(
    "#country",
    "Ka"
);

await page.click(
    ".awesomplete li"
);

Стабильный вариант:

await page.fill(
    "#country",
    "Ka"
);

await page.waitForSelector(
    ".awesomplete li"
);

await page.click(
    ".awesomplete li"
);

Стратегия покрытия E2E тестами

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

Для Awesomplete рационально покрывать E2E-тестами только критические пользовательские пути:

  • открытие списка;
  • поиск по данным;
  • выбор элемента мышью;
  • выбор элемента клавиатурой;
  • работа с серверными данными;
  • обработка ошибок загрузки;
  • работа на мобильных устройствах;
  • сценарии с многоязычными данными.

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