Утверждения Playwright – типы и лучшие практики

Что такое утверждения Playwright?

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

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

БЕСПЛАТНО СКАЧАТЬ КНИГИ в телеграм канале "Библиотека тестировщика"

Типы утверждений Playwright

Playwright предлагает множество типов утверждений для различных сценариев тестирования. Есть две большие категории: гибкие, основанные на Web-утверждениях, и жесткие, хрупкие, невосстанавливающиеся утверждения. Утверждения Web-first возвращают обещания, поскольку они вернутся, когда будут успешными или по истечении времени, в то время как утверждения non-retrying бросают свой ответ немедленно.

Автоматическое повторное выполнение, утверждения, основанные на веб-технологиях

Утверждения с автоматическим повторением автоматически перепроверяют условия до тех пор, пока они не пройдут или не будет достигнут тайм-аут. Они делают тест более стабильным, могут ускорить его выполнение и, говоря языком теории игр, должны быть “строго лучше”, чем утверждения без повторного выполнения.

УтверждениеОписание
expect(locator).toBeChecked()элемент отмечен (например, для флажков или радиокнопок).
expect(locator).not.toBeChecked()элемент не проверяется.
expect(locator).toBeDisabled()элемент отключен.
expect(locator).not.toBeDisabled()элемент не отключен.
expect(locator).toBeEditable()элемент можно редактировать.
expect(locator).not.toBeEditable()элемент не редактируется.
expect(locator).toBeEmpty()Элемент не имеет текстового содержимого.
expect(locator).not.toBeEmpty()Элемент имеет текстовое содержимое.
expect(locator).toBeEnabled()элемент включен.
expect(locator).not.toBeEnabled()элемент не включен.
expect(locator).toBeHidden()элемент скрыт или не существует в DOM.
expect(locator).not.toBeHidden()элемент виден.
expect(locator).toBeVisible()элемент виден.
expect(locator).not.toBeVisible()элемент скрыт или не существует в DOM.
expect(locator).toContainText()элемент содержит ожидаемый текст.
expect(locator).not.toContainText()элемент не содержит ожидаемого текста.
expect(locator).toHaveAttribute()элемент имеет ожидаемое значение атрибута.
expect(locator).not.toHaveAttribute()элемент не имеет ожидаемого значения атрибута.
expect(locator).toHaveClass()Элемент имеет ожидаемый класс.
expect(locator).not.toHaveClass()Элемент не имеет ожидаемого класса.
expect(locator).toHaveCount()локатор имеет ожидаемое количество элементов.
expect(locator).toHaveCSS()элемент имеет ожидаемое значение свойства CSS.
expect(locator).toHaveId()элемент имеет ожидаемое значение атрибута ID.
expect(locator).toHaveJSProperty()элемент имеет ожидаемое значение свойства JavaScript.
expect(locator).toHaveText()элемент имеет ожидаемое текстовое содержимое.
expect(locator).not.toHaveText()Элемент не имеет ожидаемого текстового содержимого.
expect(locator).toHaveValue()элемент имеет ожидаемое входное значение.
expect(locator).not.toHaveValue()элемент не имеет ожидаемого входного значения.
expect(locator).toBeFocused()элемент сфокусирован.
expect(locator).not.toBeFocused()элемент не фокусируется.

Утверждения, не требующие отлагательств

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

УтверждениеОписание
expect(value).toBe()значение строго равно ожидаемому значению.
expect(value).not.toBe()значение не строго равно ожидаемому значению.
expect(value).toEqual()значение глубоко равно ожидаемому значению.
expect(value).not.toEqual()значение не полностью совпадает с ожидаемым значением.
expect(value).toBeTruthy()значение является истинным.
expect(value).toBeFalsy()значение является ложным.
expect(value).toBeGreaterThan()значение больше ожидаемого.
expect(value).toBeGreaterThanOrEqual()значение больше или равно ожидаемому значению.
expect(value).toBeLessThan()значение меньше ожидаемого.
expect(value).toBeLessThanOrEqual()значение меньше или равно ожидаемому значению.
expect(value).toMatch()значение соответствует ожидаемому регулярному выражению.
expect(value).not.toMatch()значение не соответствует ожидаемому регулярному выражению.
expect(value).toContain()Проверяет, содержит ли массив или строка ожидаемый элемент или подстроку.
expect(value).not.toContain()Проверяет, не содержит ли массив или строка ожидаемый элемент или подстроку.
expect(value).toHaveLength()Проверяет, имеет ли массив или строка ожидаемую длину.
expect(value).toBeNull()значение равно null.
expect(value).toBeUndefined()значение не определено.
expect(value).toBeDefined()значение определено (не неопределено).
expect(value).toBeNaN()значение равно NaN.

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

Отрицание утверждений

Отрицающие матчики позволяют утверждать, что условие не выполняется. Например, вы можете использовать toBeFalsy или not.toContain, чтобы сделать отрицательные утверждения (как будет объяснено позже, если вы проверяете элемент напрямую, вероятно, последний из этих двух вариантов будет работать лучше, поскольку он реализует автоповторы Playwright).

Мягкие утверждения

Мягкие утверждения собирают все сбои в блоке, прежде чем вывести тест из строя, а не останавливаются на первом сбое. Такой подход полезен для сбора более полной информации во время выполнения тестов. Мягкие утверждения являются важным компонентом мониторинга производства, поскольку при измерении таких вещей, как время загрузки, неудачное время отклика может не означать, что мы хотим полностью остановить проверку. Любой тест Playwright с неработающими мягкими утверждениями будет занесен в список неудачных, но тест все равно будет выполняться до завершения (или до следующего жесткого утверждения, которое не сработает).

Checkly, мягкие утверждения и вырожденные состояния проверки

Checkly может использовать мягкие утверждения как часть состояния “деградации” для проверок. Если проверка не прошла мягкие утверждения и есть вызов markCheckAsDegraded, то проверка будет помещена в категорию “желтый свет” как деградировавшая, а не как провалившаяся. Вместо того чтобы классифицировать проверку как полный провал, состояние ‘degraded’ сигнализирует о том, что проверка столкнулась с проблемами, но все же завершила выполнение. У деградировавших проверок разные политики уведомлений. Например, вы можете заставить деградировавшие проверки сообщать в Slack, а не отправлять уведомление, которое разбудит людей.

Это полезно для различения частичных и полных перебоев в работе сервиса, что позволяет командам получить более точное представление о производительности и надежности. Если ваш тест Playwright работает на Checkly, проверка переходит в состояние “деградации”, когда некоторые мягкие утверждения терпят неудачу, или если вы вызываете markCheckAsDegraded во время ее выполнения.

import { test, expect } from "@playwright/test"
import { getAPIResponseTime, markCheckAsDegraded } from "@checkly/playwright-helpers"

const baseUrl = "https://api.spacexdata.com/v3"

test("SpaceX-API Dragon Capsules & Next Launch", async ({ request }) => {
  await test.step("get all capsules", async () => {
    const response = await request.get(`${baseUrl}/dragons`)

    // Hard assertion for a 200 status code, this passes!
    expect(response).toBeOK()
    
    // Soft assertion of a very fast response time
    expect.soft(getAPIResponseTime(response), 'GET /dragons too slow').toBeLessThanOrEqual(200)

    return response.json()
  })

  // Mark as degraded if we got any errors. 
  if (test.info().errors.length) {
    markCheckAsDegraded('Check degraded due to soft assertion failure.')
  }
})

В этом случае, если ответ имеет код состояния 200, но время ответа API превышает 200 секунд, статус этой проверки будет ухудшен, а медленное время ответа api будет включено как неудачный шаг. Если в ответ пришел статус не 200 (указывающий на ошибку), то проверка будет “провалена”, независимо от того, была ли вызвана markCheckAsDegraded. Вы можете настроить каналы оповещения, чтобы они уведомляли вас о деградации проверки.

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

Хотя в основных методах Playwright поддерживаются практически все сценарии тестирования, он остается достаточно настраиваемым, позволяя даже создавать собственные утверждения.

Когда использовать мягкие и жесткие утверждения

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

ScenarioUse Soft AssertionUse Hard Assertion
End-to-end testing with multiple checksYes. Useful for gathering comprehensive failure data and understanding multiple points of failure.No. Would stop execution on the first failure, which is not ideal when you want to diagnose multiple issues.
Critical conditions where failure must stop execution immediatelyNo. Collecting multiple errors is unnecessary and may lead to misleading results.Yes. Essential for scenarios where a single failure invalidates the entire test.
Monitoring a production system (e.g., API response times)Yes. Enables the test to continue running, gathering more data while signaling performance degradation.Also yes! If components like login buttons, critical notifications, or essential UI elements are missing, we should stop the test and notify the team, rather than waiting for all test steps to be attempted.
Testing load times or performance benchmarksYes. Helps measure performance without halting the test, giving more insight into overall behavior.No. Use hard assertions sparingly here; usually not necessary unless a single metric is critical.
Asserting non-deterministic or flaky conditions (for example images loading in X seconds)Yes. Can handle variations more gracefully, allowing the test to proceed for better overall coverage.No. Would stop execution unnecessarily and increase the risk of flaky tests.
Pre-check for test prerequisitesNo. If a condition must be true for the rest of the test to proceed, use a hard assertion.Yes. If a pre-requisite check kicks off further steps, all further steps should stop if the rerequisite fails.
Validating UI elements during navigationYes. When testing multiple UI states, soft assertions can log failures without interrupting the flow.Only if the missing UI element would block further navigation.
Critical database operation validationsNo. If a data inconsistency occurs, it’s usually vital to stop further operations.Yes. Data integrity should be enforced strictly with hard assertions.
Form field validationsYes. Allows collecting errors on multiple fields at once, providing more detailed feedback.No. Stopping at the first validation failure can hinder broader test coverage.
Verifying the presence of essential elements before actionNo. If the element must exist for the test to continue, a hard assertion ensures reliability.Yes, if the element’s presence is not critical and you want the test to proceed.

Как начать работу с утверждениями драматурга в простых шагах

Выполните следующие шаги, чтобы начать работу с Playwright Assertions:

  1. Установите Playwright:npm init playwright@latest.
  2. Начните писать тесты с различными типами утверждений для проверки поведения приложения.

Как добавить пользовательские матчеры с помощью expect.extend

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

Пользовательские матрицы драматургии с примером

Вот краткий пример того, как создать пользовательский матчер для проверки определенных условий:

expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;
    if (pass) {
      return {
        message: () => `expected ${received} not to be within range ${floor} - ${ceiling}`,
        pass: true,
      };
    } else {
      return {
        message: () => `expected ${received} to be within range ${floor} - ${ceiling}`,
        pass: false,
      };
    }
  },
});

// Usage
expect(100).toBeWithinRange(90, 110)

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

Распространенные ошибки утверждений и способы их отладки

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

Тяжелые ожидания

Жесткого ожидания следует избегать. Под “жестким ожиданием” понимается указание точного периода времени перед переходом к следующему шагу теста. Обычно используется код типа:

await page.waitForTimeout(3000);

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

После этого фиксированного периода, если следующий шаг не сработает, тест будет провален. Жесткое ожидание – самая распространенная причина ненадежных или “нестабильных” тестов в Playwright. Они также неэффективны: если элемент, который мы проверяем, становится доступным до истечения времени жесткого ожидания, прогонщику тестов все равно придется ждать до конца времени ожидания. Подробнее об этом читайте на нашей странице об ожидании в Playwright.

Ручные утверждения

В то время как жесткое ожидание проблематично, поскольку оно не использует преимущества автоожидания Playwright, неправильно структурированное утверждение вообще не включает ожидание. Если обернуть await внутри expect(), а не наоборот, и использовать утверждение, не относящееся к web-first, мы получим отсутствие ожидания. В данном случае мы проверяем, есть ли текст внутри элемента.

// expects the text to be visible instantly
expect(await targetPage.locatorToSomeElement.innerText()).toBeTruthy();

Вместо этого используйте веб-утверждения, такие как toBeEmpty().

// uses auto-waiting, defaulting to five seconds max
await expect(targetPage.locatorToSomeElement).not.toBeEmpty();

Отладка ошибок утверждения

Playwright предоставляет такие инструменты отладки, как page.pause() и подробное протоколирование, чтобы проверить, что происходит, когда тест терпит неудачу. Вы также можете рассмотреть визуальные средства, такие как расширение Playwright VS Code, чтобы добавить визуальный отладчик при написании или отладке тестов. Подробнее об отладке скриптов Playwright.

Выявление некачественных тестов

Нестабильные тесты – это тесты, которые периодически терпят неудачу, часто из-за проблем со временем или непредсказуемых факторов окружения. Вы можете использовать таймауты expect.poll и .toPass для стабилизации нестабильных тестов. Для выявления нестабильных тестов можно использовать --repeat-each=100, чтобы действительно забить тест и посмотреть, проходит ли он постоянно.

Лучшие практики использования утверждений драматурга

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

  • Гранулярность тестов: структурируйте тесты так, чтобы они охватывали отдельные, изолированные модели поведения, что облегчает отладку. При выборе между одним “супертестом” и 5 или 10 меньшими тестами всегда следует выбирать более гранулированный вариант. Поскольку тесты могут выполняться параллельно, вполне вероятно, что лучшая детализация тестов также улучшит время их выполнения.
  • Создавайте лаконичные утверждения: Утверждения должны быть простыми и целенаправленными. Утверждение о наличии пяти различных компонентов страницы – это показатель того, что вы проверяете несколько идей в одном тесте, и вам следует либо разбить тест на части, либо, по крайней мере, сделать несколько шагов.
  • Используйте описательные сообщения: Добавление четких сообщений к утверждениям помогает быстро выявлять сбои. Также полезно использовать шаги тестирования, чтобы добавить дополнительное описание того, на каком именно этапе произошел сбой. Читайте далее, чтобы узнать, как программно добавлять шаги тестирования с помощью декораторов Typescript.
  • Параметризация утверждений: Используйте переменные для параметров утверждений, чтобы улучшить читаемость и сопровождаемость тестов.
  • Использование библиотек: По возможности используйте существующие библиотеки для общих утверждений. Обратите внимание, что если вы выполняете тесты на каденции, полный набор библиотек может быть недоступен в вашей среде выполнения.
  • Будьте конкретны: Чтобы избежать ложных срабатываний, убедитесь, что ваши утверждения как можно более целенаправленны. Сделайте ставку на автоожидание и утверждения, ориентированные на веб. Даже переход от проверки наличия нужного текста в текстовом ярлыке к использованию .toContain(), а не toBe() может повысить надежность монитора страницы.
  • Используйте встроенный таймаут: Используйте встроенные в Playwright функции тайм-аута, чтобы изящно справляться с нестабильными условиями. По возможности избегайте жестких ожиданий.

Как Checkly может помочь с утверждениями драматурга

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

Заключение

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

Для утверждений в большинстве сценариев предпочтительнее использовать веб-утверждения с автоповтором, поскольку они используют встроенные в Playwright механизмы ожидания, делая тесты более устойчивыми и менее подверженными расслаиванию. Эти утверждения непрерывно проверяют условия до тех пор, пока они не пройдут или не достигнут таймаута, что может помочь упростить выполнение тестов. Такие примеры, как toBeVisible или toContainText, иллюстрируют, как эти утверждения могут повысить стабильность тестов. С другой стороны, утверждения без повторных попыток оценивают условия только один раз и должны быть зарезервированы для сценариев, где повторные попытки не нужны или могут внести двусмысленность. Любые другие утверждения, кроме web-first, приведут к хрупким тестам с большим количеством ложных срабатываний.

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

Я снова рекомендую избегать некоторых распространенных ловушек, таких как использование жестких ожиданий, которые могут привнести в ваши тесты зыбкость и неэффективность. Использование механизмов автоматического ожидания и правильное структурирование утверждений могут существенно изменить ситуацию. Такие инструменты отладки, как page.pause() и подробное протоколирование, в сочетании с опциями визуальной отладки, могут быть ценными для диагностики сбоев в тестировании.

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

Перевод статьи «Playwright Assertions – Types & Best Practices».

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *