Как стать автором
Обновить

Как проверить локаторы с помощью Playwright

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров6.1K

В этой статье мы поговорим о том, что можно проверить у локатора (элемента) и какие вообще есть возможности проверок. Более того, в этой статье я описал упражнения, которые вы можете выполнить и отработать в качестве практики.

Обычно мои статьи были холиварными, а не техническими. Но в этот раз решила выложить что-то действительно техническое и полезное. Тестировщики, налетай!

Проверки локаторов

Разумеется, чаще всего, мы будем проверять элементы. Это могут быть как интерактивные элементы (кнопки, поля ввода, чек-боксы и т.д.), так и статика (картинки, текст, иконки и т.д.).

Каждый элемент на странице может давать пользователю обратную связь:

  • Поле ввода подсвечивается красным, если введены невалидные данные.

  • Иконка "Сохранить" неактивна, потому что ты еще не внес изменения в документ.

  • Цвет всплывающего уведомления красный, потому что произошла ошибка.

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

С другой стороны, иногда нам нужно все же уметь получать свойства элементов для промежуточных действий. Например, мы хотим посмотреть, сколько сейчас строк в таблице, удалить одну и проверить, что их стало на одну меньше. Чтобы организовать такую проверку, нам нужно вычислить, сколько строк было до того, как мы удалили последнюю. Если в таблице было X строк, то после нажатия должно быть X-1. Найдите икс, получается? И вот тут нам нужна "ручка", которую мы дернем и получим число, без всяких assert.

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

Текст элемента

Давай начнем с простого примера — получение и проверка текста. Напишем скрипт, который открывает страницу и забирает текст у первого на странице элемента по локатору h2.tn-atom.

const { test, expect } = require("@playwright/test");

test("get text", async ({ page }) => {
  await page.goto("https://inzhenerka.tech/");

  const description = await page.locator("h2.tn-atom").first().textContent();
  console.log(description);
});

В консоль выведется текст: "Делаем обучение интересным, сохраняя авторский подход и помогаем повысить востребованность на рынке труда специалистам". Почему мы увидели его в консоли? Потому что строка console.log(description). А почему в переменной description оказалось значение? Потому что мы использовали метод textContent(), который возвращает нам текст переданного локатора.

Ссылка на документацию.

Что еще за first()?

Ты мог заметить, что мы используем у локатора какой-то метод first() перед тем, как запросить текст элемента. Нужно ли его применять каждый раз, когда хочешь получить текст элемента? Или что будет, если этот метод не вызвать? Объясняем. Дело в том, что по нашему локатору h2.tn-atom на странице обнаруживается 2 элемента. Playwright в таких случаях выбрасывает ошибку Error: strict mode violation: locator('h2.tn-atom') resolved to 2 elements. Что переводится примерно как "разберись, че ты хочешь, потом приходи, по такому локатору определяется 2 элемента". PW не выбирает за нас, с каким элементом работать, а просто останавливается. Хочешь выполнения кода – давай более точные инструкции. Ведь метод textContent() работает только с одним элементом, а тут их больше.

Итак, что же делать?

Путя всего два.

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

Путя второй и последний: объясни PW, какой из найденных элементов нужно выбрать. В нашем случае мы просим взять первый — first. Кстати, угадай, какой по порядку элемент мы получим, если напишем не .first(), а .last()? Раз уж мы умеем обращаться к первому подходящему и последнему подходящему элементу, возникает вопрос: а что, если я хочу обратиться к четвертому из 10 элементов? Или к третьему, и я не знаю, сколько их там будет всего? Здесь у нас есть метод .nth(number), который принимает на вход число — порядковый номер элемента. И да, индексация начинается с 0. Получается, что nth(1) вернет мне второй по порядку элемент?

Ага! А еще получается, что nth(0) – то же самое, что и first()?

Ага! Просто "ферст" читается как-то проще, согласен? Ссылочки на эти методы, если ты их читаешь: nth, first и last.

Итак, мы умеем получать текст элемента. И тут, если ты работал с Selenium, например, тебе уже все понятно: чтобы написать тест, нам нужно получить текст и сравнить его с ожидаемым. Ну как-то так, например:

`const { test, expect } = require("@playwright/test");

test("get text", async ({ page }) => {
  await page.goto("https://inzhenerka.tech/");

  // сохранили текст элемента в переменную
  const description = await page.locator("h2.tn-atom").first().textContent();
  // проверили, что текст в переменной равен тому, который мы указали
  expect(description).toEqual(
    "Делаем обучение интересным, сохраняя авторский подход и помогаем повысить востребованность на рынке труда специалистам"
  );
});

И это даже будет работать.С другой стороны, если открыть документацию, можно увидеть вот такое предупреждение:

Untitled

Разработчики инструмента прямо нам говорят, что, если хотите проверить текст, используйте лучше метод toHaveText(). Мы с тобой в интернете давно и знаем, что в таких ситуациях нужно сразу спрашивать — а чем это лучше?Сначала давай посмотрим, как будет выглядеть наш тест, если мы будем использовать рекомендуемый метод:

const { test, expect } = require("@playwright/test");

test("get text", async ({ page }) => {
  await page.goto("https://inzhenerka.tech/");

  await expect(page.locator("h2.tn-atom").first()).toHaveText(
    "Делаем обучение интересным, сохраняя авторский подход и помогаем повысить востребованность на рынке труда специалистам"
  );
});

Смотри, обошлись без переменной description, сразу написали проверку, мол, такой-то элемент должен содержать такой-то текст. В критерии "читаемость" один балл записываем в пользу второго подхода. Заметил, кстати, что теперь у expect() можно вызвать другой набор методов? Это все потому, что на вход мы передали не page, как раньше, а locator. Вот и методы подходящие появились.У toHaveText() есть еще пара трюков в запасе.Во-первых, этот метод умеет сравнивать, игнорируя регистр. Это пригодится тебе, когда выяснится, что в HTML текст написан маленькими буквами, а на странице отображается КАПСОМ (спроси у своего фронтенд-разработчика, как такое можно организовать).

И вот для того, чтобы не собирать шишки, подбирая правильный регистр у ожидаемого результата, мы можем просто передать правильную настройку:

await expect(page.locator("")).toHaveText("ожидаемый текст", {
  ignoreCase: true,
});

Вторая интересная фича метода toHaveText() — он умеет проверять текст у группы элементов. Как это работает: если твой локатор определяет не один элемент на странице, а группу (например, список), то и для проверки текста у элементов мы должны передать группу (массив) значений. Метод соотнесет полученные и ожидаемые тексты один к одному. Если что-то не совпадет — ошибка. Примеры:

<!-- вот у нас есть вот такой список на странице  -->
<ul>
  <li>Билли</li>
  <li>Вилли</li>
  <li>Дилли</li>
</ul>
// ✓ Вот этот код проверит, что тексты у элементов соответственно равны переданным.
await expect(page.locator("ul > li")).toHaveText(["Билли", "Вилли", "Дилли"]);

// ✖ Вот такая проверка упадет, потому что текстовки идут в другом порядке
await expect(page.locator("ul > li")).toHaveText(["Дилли", "Билли", "Вилли"]);

// ✖ Такой тест тоже упадет, потому что текст одного из элементов не совпадем с ожидаемым
await expect(page.locator("ul > li")).toHaveText([
  "Билли",
  "Вилли",
  "Джонатан?",
]);

// ✖ Вот тут сложнее.
// Тест упадет, потому что локатор собирает не группу элементов (li), а только один (ul).
// Нельзя сравнить текст одного элемента с группой текстов.
await expect(page.locator("ul")).toHaveText(["Text 1", "Text 2", "Text 3"]);

Ссылка на документацию.

В общем-то, действительно и удобнее, и код более читаемый. Давай так и будем поступать: хотим получить данные — используем метод класса Locator. Хотим проверку — заносим локатор в expect и вызываем интересный нам метод.

Это бесплатная демо-часть урока тренажера по Playwright от INZHENERKA.TECH. Больше обсуждений по теме проходит в нашем сообществе по Playwright в телеграмме

Напомню о цели этой статьи: поделитесь своим мнением о примерах в тексте, как вам? Считаете ли вы их достаточно информативными?

Теги:
Хабы:
Всего голосов 6: ↑6 и ↓0+6
Комментарии0

Публикации

Истории

Работа

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань