image Привет, Хаброжители!

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

Автор предлагает примеры использования более чем 40 инструментов, которые вы сможете немедленно опробовать. Профессионалы и новички получат навыки тестирования производительности, защищенности и доступности, а также поближе познакомятся с особенностями исследовательского, межфункционального тестирования, тестирования данных и мобильных приложений, автоматизации тестирования, и многими другими вопросами, связанными с тестированием. Руководство поможет вам справиться со сложной задачей поддержания качества программного обеспечения в процессе его разработки.
Кому адресована эта книга
В первую очередь эта книга адресована новичкам в тестировании ПО, а также специалистам по тестированию, желающим расширить свои знания. Однако она может оказаться полезной всем, кто работает в сфере разработки ПО и чьи обязанности пересекаются с тестированием, например разработчикам приложений или DevOps-инженерам. В любом случае главным требованием является наличие некоторых знаний в области программирования, особенно на Java, потому что в книге присутствуют практические упражнения на Java и в некоторых местах на JavaScript. Кроме того, если вы новичок в индустрии ПО, я бы рекомендовала сначала прочитать о процессах разработки ПО в таких методологиях, как водопадная модель или Agile, а потом браться за эту книгу.
Структура издания
Книга начинается с введения в фулстек-тестирование и подробно описывает десять навыков, необходимых для создания высококачественных мобильных и веб-приложений. После знакомства с основами вас ждут десять независимых глав, посвященных отдельным навыкам. Все они организованы одинаково.
  • Сначала в разделе «Введение» обсуждаются темы, определяющие контекст. Если вы пока не владеете обсуждаемым навыком, то здесь узнаете, какие умения он включает в себя, а также почему и где применяется.
  • Далее следует раздел, посвященный стратегии, где подробно описывается применение навыка в конкретной ситуации.
  • В следующем разделе, «Упражнения», читатель найдет пошаговые инструкции по овладению навыком с использованием нескольких инструментов.
  • В некоторых главах имеется раздел «Дополнительные инструменты», в котором параллельно обсуждаются инструменты, аналогичные представленным в разделе «Упражнения» или другие, которые могут принести пользу читателю и обогатить понимание этого навыка.
  • Наконец, в некоторых главах вы найдете описание моей точки зрения, основанной на личных наблюдениях и опыте, и ключевые выводы, представляющие собой краткий обзор уроков из этой главы.
За десятью главами, посвященными развитию навыков, идет глава, в которой рассказывается, куда двигаться дальше, опираясь на основные принципы и вновь приобретенные навыки тестирования. Для читателей-энтузиастов есть также дополнительная глава, представляющая собой введение в тестирование новых технологий. В ней представлен краткий обзор приемов тестирования четырех новых технологий — искусственного интеллекта (ИИ) и машинного обучения, блокчейна, Интернета вещей и дополненной/виртуальной реальности, — чтобы помочь читателям начать изучать приемы тестирования в этих областях.

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


Введение


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

Введение в визуальное тестирование


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

Прежде всего согласимся с тем, что человеческий глаз не способен заметить изменения на уровне пикселов, поэтому простое визуальное наблюдение позволяет добиться лишь определенного уровня точности. Например, довольно легко пропустить такие детали, как скругленные края кнопок или логотип, сдвинутый вверх или вниз на несколько пикселов. Исследование (https://oreil.ly/BaE1m), проведенное в 2012 году, показало, что наблюдатели не замечают изменений в пятой части изображений. Этот феномен, называемый слепотой к изменениям, не имеет ничего общего с дефектами зрения — он чисто психологический. Итак, представьте, что небольшие изменения в приложении могут легко остаться незамеченными при ручном тестировании. Кроме того, не будем забывать о времени и усилиях, которые требуются для ручного визуального тестирования приложения на множестве браузеров, устройств и комбинаций разрешений экрана. Очевидно, что здесь нужна некоторая автоматизация.

Но одних только автоматизированных функциональных тестов на основе пользовательского интерфейса (хотя они частично способствуют проверке визуального качества) может быть недостаточно, потому что они не оценивают внешний вид элементов, а просто идентифицируют элемент по его локатору, например идентификатору или пути XPath, и проверяют, работает ли он так, как ожидалось. Например, тесты пользовательского интерфейса, изображенного на рис. 6.1, выполнились бы успешно, потому что кнопка Continue (Продолжить) обнаруживается тестами в соответствии с ее локатором и ожидаемой меткой и при нажатии успешно перенаправляет пользователя на следующую страницу. Мы здесь не можем винить тест, потому что он вполне соответствует своему предназначению — проверке пользовательского сценария. Еще одно замечание, касающееся применения функциональных тестов на основе пользовательского интерфейса для визуального тестирования: вы не можете добавлять тесты для проверки присутствия каждого элемента на каждой странице приложения, потому что это значительно замедлит их выполнение и потребует больших усилий по обслуживанию.

К счастью, для преодоления этих проблем существуют вполне зрелые инструменты автоматизированного визуального тестирования, подобные инструментам автоматизированного функционального тестирования. Они существуют уже довольно давно, базируются на различных методологиях визуального тестирования и со временем стали более стабильными и простыми в применении. Перечислю некоторые методы работы существующих инструментов для визуального тестирования:
  • написание кода для проверки CSS-аспектов элементов (например, тест, проверяющий соответствие условию border-width=10px);
  • анализ статического кода CSS для выявления несовместимости между браузером и элементами пользовательского интерфейса;
  • применение искусственного интеллекта для распознавания изменений на странице, как это делает человеческий глаз;
  • создание скриншота страницы и сравнение его попиксельно с ожидаемым базовым скриншотом.
Последний из этих методов наиболее часто используется в регрессионном визуальном тестировании. По этой причине его иногда называют тестированием скриншотов. Такого рода визуальное тестирование выполняют некоторые инструменты с открытым исходным кодом, например PhantomJS и BackstopJS. Существуют также коммерческие инструменты, такие как Applitools Eyes и Functionize, работающие на базе искусственного интеллекта. Эти инструменты можно задействовать для автоматизации визуального тестирования после ручного сравнения приложения с эталонным дизайном и с их помощью выявлять визуальные ошибки, подобно тому как с помощью автоматизированного функционального тестирования обнаруживаются функциональные ошибки. В ходе итеративной разработки визуальные тесты будут постоянно давать вам обратную связь о визуальном качестве приложения.

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

Критически важные для проекта/бизнеса варианты применения


Мы обсудили, почему важно добавлять автоматизированные визуальные тесты, но это не может быть обязательным для всех приложений. Важным фактором является стоимость. Стоимость тестирования накапливается со временем. В любом проекте в первую очередь приходится платить за разработку и поддержку функциональных тестов на основе пользовательского интерфейса, абсолютно обязательных для всех приложений. Кроме того, у нас есть затраты на разработку и поддержку визуальных тестов даже при том, что два типа тестов можно объединить в один набор. Поэтому, принимая решение об обязательности или полезности автоматизированного визуального тестирования, важно учитывать характер приложения. Например, при разработке внутреннего приложения, которым будут пользоваться лишь несколько администраторов, вероятно, не стоит тратить время и силы на создание автоматизированных визуальных тестов — ручного визуального тестирования будет вполне достаточно. Однако в некоторых из перечисленных далее случаев автоматизированное визуальное тестирование может принести выгоду, достаточную для того, чтобы оправдать затраты.
  • Для приложения «бизнес — клиент» (Business-to-Customer, B2C) качество изображения является важнейшим атрибутом общего качества. Поэтому вам нужна постоянная обратная связь по этому аспекту приложения во время разработки. Например, при создании глобального веб-сайта электронной коммерции с большим количеством компонентов на каждой странице постоянная обратная связь по визуальному качеству необходима точно так же, как необходима постоянная обратная связь по функциональности, которую обеспечивают тесты на основе пользовательского интерфейса. В подобных случаях, если только вы не разрабатываете прототип для оценки потребностей рынка и не планируете позже улучшать его дизайн, автоматизированные визуальные тесты помогут создать стабильное приложение.
  • Когда необходимо поддерживать приложение, работающее в нескольких браузерах, на различных устройствах и с разными разрешениями экрана, автоматизированные визуальные тесты помогут справиться с огромной нагрузкой регрессионного тестирования.

    На рис. 6.2 показана статистика использования веб-сервисов по устройствам, браузерам, производителям, ОС и разрешениям экрана по состоянию на март 2022 года, согласно данным gs.statcounter.com (https://gs.statcounter.com). Как видите, пользователей мобильных устройств больше, чем пользователей настольных компьютеров. Chrome занимает наибольшую долю рынка браузеров, за ним следует Safari. Среди операционных систем важными игроками являются Android, Windows и iOS. Тестирование визуального качества приложения во всех этих комбинациях может легко превратиться в круглосуточную работу, а автоматизированное визуальное тестирование значительно уменьшит усилия вашей команды.
image

  • Обычно предприятия, владеющие наборами приложений, имеют централизованную команду, которая разрабатывает компоненты пользовательского интерфейса, образующие единую систему дизайна, и несколько команд, повторно применяющих эти компоненты. Например, компоненты пользовательского интерфейса, такие как панели навигации в заголовке с такими элементами, как «Часто задаваемые вопросы», «Свяжитесь с нами» и «Поделиться в социальных сетях», разрабатываются одной командой и повторно используются во всем наборе приложений. В таких случаях визуальное тестирование на уровне компонентов становится необходимостью, потому что любой недочет в стандартных компонентах будет распространяться на весь пакет.
  • Иногда приложение полностью перестраивается для улучшения масштабируемости и других аспектов качества, но ожидается, что пользовательский опыт останется таким, какой он есть, потому что клиенты уже обладают им. Написание визуальных тестов может послужить подстраховкой для команд, работающих над таким приложением.
  • Точно так же визуальные тесты пригодятся при проведении значительного рефакторинга существующего приложения. Например, повышение эффективности внешнего интерфейса может потребовать значительной реорганизации компонентов пользовательского интерфейса. В такой ситуации автоматизированные визуальные тесты дадут команде бо́льшую уверенность.
  • Когда приложение расширяется для того, чтобы охватить аудиторию в разных странах, в него включаются такие функции локализации, как особый внешний вид для каждого региона и текст на родном языке. Эти изменения могут повлиять на макет страницы. А когда нужно протестировать несколько версий, автоматизация визуальных тестов может оказаться большим подспорьем.
Таким образом, принимая решение о необходимости реализации автоматизированного визуального тестирования для приложения, учитывайте такие факторы, как влияние на клиента, виды работ, которые требуется выполнить, уверенность команды и объем усилий на ручное тестирование. По мере возможности старайтесь сбалансировать свою стратегию тестирования пользовательского интерфейса и разрабатывайте минимальный набор визуальных тестов только для наиболее важных путей. В следующем разделе представлены различные типы тестов, которые может включать такая стратегия.

Стратегия тестирования фронтенда


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

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

Код фронтенда веб-приложения состоит из трех основных частей: HTML-кода, определяющего базовую структуру страницы, CSS-кода, определяющего стили элементов на странице, и сценариев, задающих поведение этих элементов. Еще один важный компонент — браузер, отображающий этот код. Большинство новых браузеров придерживаются стандартов отображения элементов. В результате среды разработки фронтенда могут обеспечить встроенную поддержку различных браузеров. Это означает, что элементы или функции, созданные с помощью этих платформ, гарантированно корректно отображаются в основных браузерах, но вам, возможно, придется проверить наличие проблем с совместимостью браузеров при использовании функций, которые платформы не тестируют в старых и новых браузерах.

Для проверки различных частей кода фронтенда мы можем применять различные типы тестов на микро- и макроуровне. Обычно разработчики и тестировщики совместно владеют этими тестами. На рис. 6.3 показано, как можно задействовать различные тесты фронтенда на микро- и макроуровне на протяжении всего процесса разработки, чтобы быстрее получить обратную связь, — другими словами, рисунок проливает свет на реализацию раннего тестирования фронтенда. Мы обсудили некоторых из этих типов тестов в главе 3, а в этом разделе рассмотрим их с точки зрения кода фронтенда, чтобы понять, как они могут помочь выполнять визуальное тестирование.

image

Модульные тесты


Модульные тесты фронтенда пишутся на уровне компонентов и проверяют их поведение в различных состояниях. Они также частично помогают выполнить визуальное тестирование. Например, модульные тесты могут проверять вывод приветственного сообщения в заголовке страницы или состояние (активна/неактивна) кнопки отправки. Обычно разработчики пишут эти тесты в начале разработки, используя такие инструменты, как Jest и React Testing Library. Они находятся внутри базы кода и обеспечивают быструю обратную связь на этапе разработки.

В примере 6.1 показан пример модульного теста для проверки приветственного сообщения. Как видите, он извлекает заголовок h1 и проверяет содержащийся в нем текст. Проверяя элемент h1, мы вносим вклад в визуальное тестирование.

Пример 6.1. Пример модульного теста с использованием Jest

describe("Component Unit Testing", () => {
    it('displays greeting message as a default value', () => {
        expect(enzymewrapper.find("h1").text()).toContain("Good Morning!")
    })
})

Интеграционные/компонентные тесты


Эти тесты написаны для проверки функциональности компонентов и интеграции между ними, например для контроля поведения формы входа, как показано в примере 6.2. Здесь проверяется функциональность всей формы, а не только одного компонента, как при модульном тестировании. Интеграционные тесты обычно имитируют вызовы сервисов и изменение состояния компонентов пользовательского интерфейса. В примере 6.2 имитируется ответ на попытку входа, и тест проверяет исчезновение с экрана формы входа после успешного входа. Также интеграционные тесты могут помочь проверить компоненты с несколькими дочерними компонентами и интеграцию между ними в разных состояниях.

Пример 6.2. Пример интеграционного теста с использованием Jest

test('User is able to login successfully', async () => {

  // имитация ответа на попытку входа
  jest
    .spyOn(window, 'fetch')
    .mockResolvedValue({ json: () => ({ message: 'Success' }) });

  render(<LoginForm />);
  const emailInput = screen.getByLabelText('Email');
  const passwordInput = screen.getByLabelText('Password');
  const submit = screen.getByRole('button');

  // ввод учетных данных и отправка формы
  fireEvent.change(emailInput, { target: { value: 'testUser@mail.com' } });
  fireEvent.change(passwordInput, { target: { value: 'admin123' } });
  fireEvent.click(submit);

  // кнопка отправки должна немедленно деактивироваться
  expect(submit).toBeDisabled();

  // ждать сокрытия элементов формы после успешного входа
  await waitFor(() => {
    expect(submit).not.toBeInTheDocument();
    expect(emailInput).not.toBeInTheDocument();
    expect(passwordInput).not.toBeInTheDocument();
    });
});

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

Скриншот-тесты


Скриншот-тесты предназначены для проверки структурных аспектов отдельных компонентов и их групп, что напрямую способствует визуальному тестированию на микроуровне. Эти тесты визуализируют фактическую структуру DOM компонентов с помощью средств тестирования и сравнивают результаты с ожидаемой структурой, хранящейся в эталонном скриншоте вместе с тестом. Для этой цели, например, можно использовать такие инструменты, как Jest (https://jestjs.io/docs/snapshot-testing) и react-test-renderer (https://reactjs.org/docs/test-renderer.html).

Скриншот-тесты сравнивают фрагменты HTML-кода. Они отличаются от визуальных тестов, обсуждаемых далее, которые попиксельно сравнивают изображения (скриншоты).

В примере 6.3 показан тест скриншота для проверки структуры DOM компонента Link с помощью Jest.

Пример 6.3. Пример скриншот-теста с использованием Jest

import React from 'react';
import renderer from 'react-test-renderer';
import Link from '../Link.react';

it('renders correctly', () => {
  const tree = renderer
    .create(<Link page="http://www.example.com">Sample Site</Link>)
    .toJSON();
  expect(tree).toMatchSnapshot();
});

Для каждого коммита кода этот тест создает новый файл со структурой DOM компонента Link, как показано в примере 6.4, и сверяет его с предыдущим скриншотом.

Пример 6.4. Файл со скриншотом, созданный Jest

exports[`renders correctly`] = `
<a
  className="test"
  href="http://www.example.com"
  onMouseEnter={[Function]}
  onMouseLeave={[Function]}
>
  Sample Site
</a>
`;

Эти тесты позволяют быстро получить информацию о структурных аспектах компонентов. (Визуальные тесты, напротив, требуют, чтобы приложение было полностью функциональным.) Данные тесты становятся особенно важными, когда компоненты повторно используются в нескольких приложениях, например в системах проектирования. Подобно модульным и интеграционным тестам, они пишутся в процессе разработки и хранятся вместе с прикладным кодом.

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

Функциональные сквозные тесты


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

Визуальные тесты


Все обсуждавшиеся ранее типы тестов так или иначе помогают проводить визуальное тестирование, но основную работу выполняют, конечно, визуальные тесты. Как и функциональные тесты, описанные в предыдущем разделе, они открывают приложение в браузере, затем сравнивают скриншот (снимок экрана) каждой страницы с эталонным скриншотом. Визуальные тесты можно хранить отдельно или интегрировать в набор функциональных тестов, чтобы их проще было поддерживать. Для этой цели можно использовать инструменты с открытым исходным кодом, такие как Cypress, Galen, BackstopJS и др., а также коммерческие инструменты, например Applitools Eyes, CrossBrowserTesting и Percy.

ВИЗУАЛЬНОЕ ТЕСТИРОВАНИЕ ПО СРАВНЕНИЮ СО СКРИНШОТАМИ


Визуальные тесты и скриншот-тесты могут показаться похожими, но они работают на разных уровнях. Их можно сравнить с высокоуровневыми функциональными сквозными тестами и низкоуровневыми тестами API. Цикл обратной связи этих двух видов тестов также существенно различается. И как уже говорилось, визуальные тесты проверяют приложение после того, как оно полностью отображается в браузере, тогда как скриншот-тесты дают обратную связь о структуре HTML и, следовательно, удобны для разработчиков и помогают при раннем тестировании.

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

Кросс-браузерное тестирование


Кросс-браузерное тестирование преследует две важные цели: выполнение функциональной проверки и проверки визуального качества в разных браузерах. Функциональный поток приложения обычно почти не меняется в разных браузерах, но были случаи выявления расхождений. Например, в 2020 году Twitter пришлось исправлять критическую проблему безопасности (https://oreil.ly/hG81i), из-за которой конфиденциальная информация пользователей сохранялась в кэше браузера Firefox. Судя по всему, в Chrome такой проблемы не было. Поэтому тестирование функционального потока в разных браузерах должно быть частью стратегии кросс-браузерного тестирования.

Приступая к такому тестированию, прежде всего необходимо определиться со списком браузеров, на которых вы собираетесь сосредоточиться. Как мы видели ранее, наиболее широкое распространение в мире получили браузеры Chrome и Safari, и пользователи могут обращаться к вашему приложению с их помощью, используя различные устройства: настольные ПК, планшеты и смартфоны. Еще один важный фактор, который следует учитывать при тестировании в разных браузерах, — скорость реагирования приложения. Общее практическое правило — сосредоточиться на браузерах и разрешениях, на которые приходится 80 % пользователей. Оставшиеся 20 % можно протестировать в ходе проверки ошибок ближе к выпуску.

Таким образом, хорошей стратегией получения обратной связи о совместимости с разными браузерами, учитывая замечания, сделанные при обсуждении функциональных тестов на основе пользовательского интерфейса (предполагающих более медленную обратную связь и не включающих визуальное тестирование), может стать выбор ограниченного числа наиболее важных функциональных потоков и их опробование в выбранных вами браузерах. А для получения обратной связи о качестве изображения можно повторно применять визуальные тесты. Они способны дать информацию как о совместимости с браузерами, так и об отзывчивости приложения. Выберите браузеры и разрешения экрана, используемые 80 % ваших конечных пользователей, и добавьте визуальные тесты для наиболее важных пользовательских сценариев. В итоге у вас должно быть несколько функциональных и визуальных тестов (их можно объединить с помощью таких инструментов, как Cypress и Applitools Eyes), проверяющих совместимость с браузерами и скорость реагирования приложения.

Если вам кажется, что этих усилий будет недостаточно для кросс-браузерного тестирования всех страниц приложения, то задействуйте инструменты/библиотеки разработки пользовательского интерфейса, такие как React, Vue.js, Bootstrap и Tailwind, имеющие встроенную поддержку проверки совместимости. Они могут помочь обеспечить визуальное качество некритичных пользовательских сценариев в приложении. Но имейте в виду, что эти инструменты и библиотеки поддерживают только наиболее свежие стандартизированные версии браузеров и некоторые их возможности могут не поддерживаться старыми браузерами.

Проверить, поддерживает ли данный браузер определенную функцию среды разработки (и, следовательно, возможность ее использования), можно по таблицам поддержки на сайте CanIUse (https://caniuse.com/ciu/comparison). Например, если вы хотите применить макет flexbox CSS в своем пользовательском интерфейсе, то уточните сначала, поддерживают ли его целевые браузеры. Для автоматической проверки функций CSS, не поддерживаемых целевыми браузерами, на основе данных CanIUse можно использовать также плагины, такие как stylelint-no-unsupported-browser-features (https://oreil.ly/Zo62P). Похожий плагин eslint-plugin-caniuse (https://oreil.ly/asdQ1) поможет выявить функции сценариев, не поддерживаемые целевыми браузерами. Существует еще один способ обеспечить обратную совместимость кода JavaScript — применять транспилеры, такие как Babel. Они преобразуют код, написанный на последней версии JavaScript, в версию, совместимую со старыми браузерами. Используя все перечисленные инструменты, вы сможете гарантировать соответствие всех страниц вашего приложения требованиям совместимости с разными браузерами, особенно с точки зрения их визуального качества.

РАННЕЕ КРОСС-БРАУЗЕРНОЕ ТЕСТИРОВАНИЕ


Начиная слева:
  • применяйте библиотеки разработки, такие как React, Vue.js и др., которые поддерживают стандартизированные браузеры;
  • задействуйте плагины и инструменты, такие как stylelint-no-unsupported-browser-features и CanIUse, чтобы обеспечить совместимость функций пользовательского интерфейса с целевыми браузерами во время разработки;
  • создайте несколько функциональных тестов на основе пользовательского интерфейса и визуальных тестов для проверки совместимости с выбранным набором браузеров и устройств, охватывающих 80 % потенциальных пользователей вашего приложения;
  • регулярно проверяйте наличие ошибок, чтобы охватить как можно большую часть из оставшихся 20 %.

Тестирование производительности фронтенда


Тестирование производительности фронтенда включает проверку задержек при отрисовке визуальных компонентов браузером. Вы можете повысить привлекательность и визуальное качество приложения, добавив приятные глазу изображения и необычные жесты, но если это приведет к ухудшению производительности, то пользователи, скорее всего, уйдут от вас. Общеизвестно, что загрузка компонентов внешнего интерфейса занимает около 80 % всего времени загрузки страницы. Поэтому очень важно найти правильный баланс между производительностью интерфейса и качеством изображения. Инструменты и передовые приемы тестирования производительности фронтенда подробно обсуждаются в главе 8, тем не менее, учитывая их относительную важность, они заслужили упоминания и здесь.

Тестирование доступности


Законодательство многих стран предусматривает нормы доступности веб-сайтов, поэтому код пользовательского интерфейса должен разрабатываться в соответствии с требованиями WCAG 2.0 (https://oreil.ly/TRxmX). Функции доступности значительно влияют на визуальное качество веб-сайта и в целом улучшают его, поскольку поощряют единообразие макета организации всего сайта, наличие понятного текста, достаточного пространства для щелчков кнопкой мыши и т. д. Подробнее об инструментах тестирования доступности и передовых практиках рассказывается в главе 9.

На этом мы завершаем обзор различных видов тестирования фронтенда. Главный вывод, который можно сделать: команда должна адаптировать свою стратегию тестирования фронтендв к целям различных видов тестов и потребностям приложения. В целом рекомендуется иметь больше тестов на микроуровне (например, модульных) и меньше — на макроуровне (например, визуальных и сквозных функциональных).

Упражнения


Теперь вы готовы приступить к изучению инструментов автоматизированного визуального тестирования. Для этого можно применять инструменты, поддерживающие управление из командной строки или из программного кода либо делегировать эту задачу поставщикам программного обеспечения как услуги (Software-as-a-Service, SaaS). Здесь мы рассмотрим два упражнения с использованием BackstopJS и Cypress. Можете добавить эти визуальные тесты в свои конвейеры CI и запускать их после развертывания каждого коммита вместе с функциональными тестами.

BackstopJS


BackstopJS (https://github.com/garris/BackstopJS) — популярный инструмент визуального тестирования, который поддерживается активным сообществом разработчиков ПО с открытым исходным кодом. По сути это библиотека Node, которую легко интегрировать с CI, использующая стиль тестирования на основе конфигурации, что означает отсутствие необходимости писать программный код. Она применяет Puppeteer, инструмент автоматизации пользовательского интерфейса, для отображения приложения в Chrome и навигации по нему, а также Resemble.js для сравнения скриншотов веб-страниц. После сравнения изображений BackstopJS генерирует результаты в форме HTML-отчетов. Она позволяет настраивать чувствительность сравнения изображений и автоматического исправления после неудачных тестов, о чем мы сейчас и поговорим.

Это упражнение поможет вам создать визуальный тест с помощью BackstopJS для проверки веб-приложения в трех разрешениях, типичных для планшетов, мобильных телефонов и обычных браузеров.

Установка и настройка


Предварительно вам может потребоваться установить и настроить Node.js и Visual Studio Code (как в упражнении Cypress в главе 3). После этого выполните следующие действия, чтобы установить инструмент и получить базовую структуру проекта.

1. Создайте новую папку проекта и запустите следующую команду в терминале, чтобы установить BackstopJS:

$ npm install -g backstopjs

Библиотека BackstopJS будет установлена глобально на вашем локальном компьютере, чтобы ее можно было повторно использовать в разных проектах. Эта команда попутно установит движки chromium (для поддержки Chrome) и puppeteer.

2. Настройте конфигурации по умолчанию и структуру проекта с помощью следующей команды:

$ backstop init

Теперь вы сможете просмотреть файл конфигурации по умолчанию backstop.json в папке проекта. В него будете добавлять свои визуальные тесты в форме конфигураций.

Рабочий процесс


Теперь возьмите любой образец общедоступного веб-сайта для визуального тестирования и выполните следующие действия, чтобы создать тест.

1. Чтобы проверить веб-страницу в трех разных разрешениях экрана, как того требует наш тестовый сценарий, добавьте конфигурацию backstop.json, показанную в примере 6.5.

Пример 6.5. Пример теста в конфигурационном файле backstop.json

{
  "id": "backstop_demo",
  "viewports": [
    {
      "label": "browser",
      "width": 1366,
      "height": 784
    },
    {
      "label": "tablet",
      "width": 1024,
      "height": 768
    },
    {
      "name": "phone",
      "width": 320,
      "height": 480
    }
  ],
  "onBeforeScript": "puppet/onBefore.js",
  "onReadyScript": "puppet/onReady.js",
  "scenarios": [
    {
      "label": "Application Home page",
      "cookiePath": "backstop_data/engine_scripts/cookies.json",
      "url": "<укажите здесь URL приложения>",
      "referenceUrl": "<укажите здесь тот же самый URL>",
      "readyEvent": "",
      "delay": 5000,
      "hideSelectors": [],
      "removeSelectors": [],
      "hoverSelector": "",
      "clickSelector": "",
      "readySelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "expect": 0,
      "misMatchThreshold" : 0.1,
      "requireSameDimensions": true
    }
  ],
  "paths": {
    "bitmaps_reference": "backstop_data/bitmaps_reference",
    "bitmaps_test": "backstop_data/bitmaps_test",
    "engine_scripts": "backstop_data/engine_scripts",
    "html_report": "backstop_data/html_report",
    "ci_report": "backstop_data/ci_report"
  },
  "report": ["browser"],
  "engine": "puppeteer",
  "engineOptions": {
    "args": ["--no-sandbox"]
  },
  "asyncCaptureLimit": 5,
  "asyncCompareLimit": 50,
  "debug": false,
  "debugWindow": false
}

Вот несколько важных замечаний, касающихся этого файла.
  • Массив viewports определяет три разрешения экрана, типичные для настольных компьютеров, планшетов и мобильных устройств.
  • Сценарии Puppeteer для взаимодействия с элементами пользовательского интерфейса в Chrome настраиваются с помощью параметров onBeforeScript и onReadyScript. Также можно добавить свои сценарии для определения новых действий.
  • Тестовый сценарий определяется в массиве scenarios с такими параметрами, как url, referenceURL, clickSelector, hideSelectors и т. д. Позже вы узнаете назначение каждого из них.
  • Места хранения эталонных и тестовых скриншотов определяются параметрами bitmaps_reference и bitmaps_test. Место для сохранения отчетов задается параметром html_report.
  • Параметру report присвоено значение «browser», чтобы разрешить просмотр результатов в браузере. Если ему присвоить значение «CI», то будет сгенерирован отчет в формате JUnit.
  • Параметр engine применятся для настройки соответствующего браузера. По умолчанию ему присваивается значение «puppeteer», соответствующее механизму, который использует браузер Chrome. Вы можете изменить это значение на «phantomjs», чтобы запускать тесты в Firefox с помощью более старых версий BackstopJS.
  • Параметр asyncCaptureLimit со значением 5 будет запускать тесты параллельно в пяти потоках.
2. Следующий шаг — создание эталонных скриншотов веб-страницы на экранах разных размеров для сравнения. Библиотека BackstopJS поможет вам в этом и выполнит все автоматически. Она откроет URL, указанный в параметре referenceURL, сделает эталонные снимки с разными размерами экрана, которые перечислены в массиве viewports, и сохранит их в папке, указанной в параметре bitmaps_reference. Вот команда, которая сделает это:

$ backstop reference

3. Следующий шаг — запуск тестов с помощью команды:

$ backstop test

После ее запуска BackstopJS проверит веб-сайт, заданный параметром url, и сравнит его внешний вид с эталонными скриншотами для всех разрешений.

По завершении теста вы сможете просмотреть результаты в браузере (рис. 6.4). В качестве тестового сайта я выбрала домашнюю страницу Amazon, и, как показывают результаты, один тест успешно пройден, а два потерпели неудачу. В частности, тест в браузере с большим разрешением экрана пройден, а два других — нет.

Открыв отчет о неудачных тестах, я увидела эталонные и реальные скриншоты, кроме того, там есть и третье изображение, подчеркивающее различия с первыми двумя. Все три изображения приведены на рисунке. Различия выделены в нижней половине третьего изображения.

image

Неудачи обусловлены динамическим контентом на домашней странице Amazon. В тестовой среде есть возможность контролировать тестовые данные, но если вы столкнетесь с динамическим контентом в своем приложении, то BackstopJS позволит скрыть его во время выполнения теста. Скрыть или полностью удалить динамическое содержимое можно с помощью параметров hideSelectors или removeSelectors в файле backstop.json. В роли селекторов могут выступать имена классов или идентификаторов, как показано здесь:

"hideSelectors": [".feed-carousel-viewport"]

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

Иногда даже после удаления динамического контента тесты могут терпеть неудачу из-за небольших изменений на уровне пикселов, которые на самом деле не ухудшают визуальное качество. В таких случаях можно настроить чувствительность тестов в параметре misMatchThreshold, задав значение от 0,00 до 100,00 %. Это может избавить вас от хаоса при тестировании и обслуживании.

BackstopJS помогает и при сопровождении тестирования. Представьте, что ваше приложение изменилось и нужно обновить эталонные скриншоты. Вы можете просто одобрить новые скриншоты, сделанные во время последнего тестирования (конечно же, предварительно просмотрев их глазами), с помощью следующей команды:

$ backstop approve

Также можно расширить тест и реализовать в нем поиск товара и проверку страницы с информацией о нем с помощью keyPressSelectors. В примере 6.6 показана конфигурация, настраивающая ввод текста в поле поиска на сайте Amazon и нажатие кнопки поиска.

Во многих проектах часто сравниваются страницы в разных средах, например на локальном компьютере и в среде тестирования. Это можно сделать, указав локальный URL в параметре url и URL тестовой среды — в параметре referenceURL.

Пример 6.6. Ввод текста для поиска с помощью keyPressSelectors в конфигурационном файле backstop.json

"keyPressSelectors": [
  {
    "selector": "#twotabsearchtextbox",
    "keyPress": "Women's Tshirt"
  }
],
"clickSelectors": ["#nav-search-submit-button"],

При интеграции с CI нужно изменить значение параметра report на «CI» и сохранить все результаты вывода, включая скриншоты. Также рекомендуется заархивировать старые скриншоты, чтобы при необходимости можно было изучить историю.

Cypress


Предварительные условия и настройку среды автоматизации функционального тестирования с использованием Cypress мы обсудили в главе 3. Вы можете организовать визуальное тестирование как часть той же среды с помощью плагина cypress-plugin-snapshots (https://oreil.ly/76YwA). Как и BackstopJS, он сравнивает скриншоты и выделяет различия между ними. А также предоставляет похожие возможности, например позволяет настраивать чувствительность теста, выбирать элементы для сравнения и делать многое другое.

Установка и настройка


Чтобы начать работу с плагином Cypress, выполните следующие действия.

1. Для установки плагина запустите команду:

$ npm i cypress-plugin-snapshots -S

2. В файлы cypress/plugins/index.js и cypress/support/index.js добавьте код, импортирующий команды плагина, как показано в примере 6.7.

Пример 6.7. Конфигурация плагина Cypress

// cypress/plugins/index.js

const { initPlugin } = require('cypress-plugin-snapshots/plugin');

module.exports = (on, config) => {
  initPlugin(on, config);
  return config;
};

// cypress/support/index.js

import 'cypress-plugin-snapshots/commands';

3. Конфигурация Cypress хранится в файле cypress.json. Добавьте в него тестовые конфигурации, как показано в примере 6.8. Отмечу несколько важных параметров: threshold определяет чувствительность теста, auto clean-up автоматически удаляет неиспользуемые скриншоты и ignoreFields — массив компонентов, исключаемых из сравнения скриншотов.

Пример 6.8. Пример теста в конфигурационном файле cypress.json

{"env": {
  "cypress-plugin-snapshots": {
    "autoCleanUp": false,
    "autopassNewSnapshots": true,
    "diffLines": 3,
    "excludeFields": [],
    "ignoreExtraArrayItems": false,
    "ignoreExtraFields": false,
    "normalizeJson": true,
    "prettier": true,
    "imageConfig": {
      "createDiffImage": true,
      "resizeDevicePixelRatio": true,
      "threshold": 0.01,
      "thresholdType": "percent"
    },
    "screenshotConfig": {
      "blackout": [],
      "capture": "fullPage",
      "clip": null,
      "disableTimersAndAnimations": true,
      "log": false,
      "scale": false,
      "timeout": 30000
    },
    "serverEnabled": true
    "serverHost": "localhost",
    "serverPort": 2121,
    "updateSnapshots": false,
    "backgroundBlend": "difference"
  }
}}

Рабочий процесс


Для добавления визуальных тестов плагин Cypress предоставляет метод toMatchImageSnapshot(), который делает скриншот указанного компонента или текущей страницы и сравнивает его с базовым скриншотом. В качестве базовых он использует скриншоты, сделанные во время первого запуска теста. В примере 6.9 показан тест, который открывает URL приложения, ждет, пока страница станет видимой, а затем делает скриншот всего ее содержимого для сравнения изображений.

Пример 6.9. Визуальный тест с использованием Cypress для проверки домашней страницы приложения

describe('Application Home page', () => {
    it('Visits the Application home page', () => {
      cy.visit('<укажите здесь URL приложения>')
      cy.get('#twotabsearchtextbox')
        .should('be.visible')
      cy.get('#pageContent').toMatchImageSnapshot()
    })
  })

Если запустить тест на домашней странице Amazon, он завершится неудачей из-за динамического контента. Результаты тестирования в Cypress с выделенными различиями в изображениях показаны на рис. 6.5.

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

image

Об авторе
Гаятри Мохан — увлеченный техлид и эксперт в различных областях разработки программного обеспечения и промышленных технологий. Гаятри не раз доказывала свою компетентность, успешно управляя большими командами обеспечения качества в Thoughtworks, где в настоящее время занимает должность главного консультанта. Будучи директором технического обеспечения, Гаятри поддерживала местные технологические сообщества, организовывала технические мероприятия и развивала интеллектуальное лидерство по техническим темам.

Гаятри является соавтором книги Perspectives of Agile Software Testing (https://oreil.ly/PoAST), выпущенной компанией Thoughtworks к десятилетию Selenium.

Более подробно с книгой можно ознакомиться на сайте издательства:

» Оглавление
» Отрывок

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Тестирование

P.S Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.

Комментарии (0)