Comments 69
Полуавтомтический data-test-id='clients-search__SearchClientInput-lastName--item'
У нас nx-монорепозиторий. Есть соглашение, что в каждом модуле (1-2 страницы со своим api) вложенность компонентов только на 1 уровне - т.к. нет components/a/b/c.
Делюсь рабочим простым, но эффективным рабочим кодом по генерации test-id. Его положили модуль library.
const getString = (text: string | number | null, divider: string) => (text?.toString() ? `${divider}${text}` : '');
export const getTestId =
(module?: string | null) =>
(component: string, componentId: string | number | null = '') =>
(element: string | null = '', modifier: string | number | null = '') => {
const moduleTitle = module ? `${module}__` : '';
return `${moduleTitle}${component}${getString(componentId, '_')}${getString(element, '-')}${getString(
modifier,
'--'
)}`;
};
Для каждого модуля создаём функцию, которая содержит имя модуля. Например, для модуля clients-search.
import { getTestId } from '@bcs/library';
export const useTestId = getTestId('clients-search');
И в самом модуле, в компонент используем useTestId() для компонентов.
import { useTestId } from '../../utils/useTestId';
export const SearchClientInput: React.FC<ISearchClientInput> = ({ name, title, error, value, handleChange }) => {
const testId = useTestId('SearchClientInput');
return (
<FormControl data-test-id={testId()} error={Boolean(error[name])} key={name}>
<InputLabel htmlFor={name}>{title}</InputLabel>
<Input
data-test-id={testId(name)}
type='text'
name={name}
value={value}
inputProps={{
'data-test-id': testId(name, 'item'),
}}
onChange={handleChange}
/>
<FormHelperText data-test-id={testId(name, 'error')}>{error && error[name]}</FormHelperText>
</FormControl>
);
};
Плюсы такой функции - утилиты:
Минимальное количество сил для уникальных названий, не надо думать! Достаточно, чтобы в 1 компоненте префикс не повторялся
testId('префикс').
При том очень стабильное поведение. Изменяется только когда сам компонент (его название) меняет название. А это как правило в следствии меняющих требования доработок.
Уникальность работает в рамках нашей архитектуры, где только 1 уровень вложенности. Кстати, как показывает время - очень простое и удобное решение (по сравнению с FSD xD )
Ок, HabrGPT, держи ответ на этот пассаж:
Ни CSS, ни XPath не являются оптимальными инструментами для UI-автотестов. Вообще. Забудьте. Правильный, взрослый, стабильный подход — это кастомные атрибуты типа
data-test-id
Детский сад какой-то. Современные интерфейсы строятся из компонент. Отличительной особенностью компонент является возможность использования их в разных местах. Поэтому в них принципиально не возможно захардкодить эти ваши глобально уникальные data-test-id - их надо генерировать на основе иерархии владения. Как выглядят генерируемые глобально уникальные человекопонятные идентификаторы можно глянуть в любом приложении на $mol, где ни программистам, ни тестировщикам вообще не нужно об этом думать. Например: $hyoo_mol.Root(0).Apps().Filter().Clear()
- кнопка очистки поля фильтрации в галерее приложений.
Возникают вопросы:
Как быть если вы используете UI kit где нет test-id?
Почему используется кастомный атрибут, а например не name?
В статье как раз используется Material UI — один из самых популярных, удобных, функциональных и классных UI Kit'ов. Это доказывает, что использование data-test-id
никак не ограничено выбором библиотеки компонентов.
Даже если компоненты приходят из UI Kit'а, вы можете:
прокинуть пропсы с
data-test-id
черезslotProps
,InputProps
,ButtonProps
,componentsProps
, короче есть разные варианты, почти все нормальные библиотеки это поддерживают;создать враппер-компонент с нужными атрибутами;
или просто установить
data-test-id
на обёртывающий элемент, не нарушая логику библиотеки.
Почему используется кастомный атрибут, а например не name?
Потому что data-test-id
:
не мешает CSS/JS;
не ломает семантику;
не конфликтует с другими системами;
и явно сигнализирует, что атрибут используется только для автотестов — это отличная практика.
Можно конечно и name
, id
, что угодно. Главный посыл стати в том, что используйте тестовые идентификаторы, а как вы уже будете это реализовывать — дело ваше.
Очень много текста, а всё, по большому счёту, сводится к тому, что
Через специально оставленные API тестировать удобнее (кто бы сомневался)
Даём тестировщикам доступ к репе, пусть сами себе их делают (сомнительно... Обычно принято делать наоборот: тестировщики дают программерам заказ на нужные идентификаторы или что там, а не лезут в код сами).
Ну и ещё: такие тесты, конечно, будут реже разваливаться и программистам будет удобнее читать об ошибке, но внезапно есть ситуации, где такой тест пройдет успешно, невзирая на ошибку. Например, элемент с этим id переставили в какое-то место, где юзер его не найдёт никогда. Так что тесты "не через специально оставленную для них дырочку" тоже нужны.
Кажется, вы немного неверно интерпретировали суть статьи:
Через специально оставленные API тестировать удобнее (кто бы сомневался)
Это всё равно что сказать, что «все советы по инженерной практике сводятся к “пишите хороший код”». Простые идеи — не значит бесполезные. Важно не что, а как. В статье как раз и разбирается, как внедрить подход с data-test-id
в реальные проекты. Несмотря на кажущуюся очевидность, это до сих пор не становится нормой — что и делает статью актуальной.
Даём тестировщикам доступ к репе, пусть сами себе их делают (сомнительно... Обычно принято делать наоборот: тестировщики дают программерам заказ на нужные идентификаторы или что там, а не лезут в код сами).
Попробуйте мыслить шире. Современный QA-инженер — это не «человек, который кликает по кнопкам». Это инженер, который готовит инфраструктуру для автотестов, в том числе и тестовые API. Добавление data-test-id
— это такой же элемент тестовой инфраструктуры, как и factory-функции или фикстуры. При этом в статье явно указано, что это не обязанность QA, и добавлять такие идентификаторы могут (и должны) фронтенд-разработчики — особенно если они используют компоненты повторно.
Ну и ещё: такие тесты, конечно, будут реже разваливаться и программистам будет удобнее читать об ошибке, но внезапно есть ситуации, где такой тест пройдет успешно, невзирая на ошибку. Например, элемент с этим id переставили в какое-то место, где юзер его не найдёт никогда. Так что тесты "не через специально оставленную для них дырочку" тоже нужны.
Именно. Никто не говорил, что data-test-id
— это серебряная пуля. В статье отдельно подчёркнуто, что это способ сделать тесты более стабильными, но не единственный инструмент контроля качества. Локаторы — это лишь часть UI-тестов, а не вся валидация UX.
Речь не про суть (там трудно спорить). Речь про то, что вы написали целую статью там, где достаточно одного абзаца.
Насчёт "тестовой инфраструктуры" – обычно она отделена от основного кода и является зоной ответственности команды QA. QA не лезут в код самого проекта, программисты не лезут в тесты. Разумный предел – читать код друг друга, но не модифицировать самим.
Речь не про суть (там трудно спорить). Речь про то, что вы написали целую статью там, где достаточно одного абзаца.
Если вы не заметили, в статье не просто озвучена мысль "нужны тестовые идентификаторы" — она наполнена практикой: от установки и настройки, до готовых шаблонов, примеров, рекомендаций и таблиц. Я детально разобрал, как и зачем их внедрять, какие есть варианты, где проставлять, какие ошибки допускают и почему это важно. Свести всё это к одному абзацу — это всё равно что сказать "тестирование важно" и выкинуть все курсы и практики по тестированию. По вашей логике, почти любую инженерную тему можно уместить в пару строк. Но зачем тогда вообще писать статьи, документацию и делиться опытом? Тем более для новичков, это может быть очень полезно, когда вообще не знаешь откуда начать. Не у всех 10 лет опыта в индустрии и годы практики за плечами. Для меня тоже все эти вещи просты и очевидны, но это лишь субъективный взгляд.
Насчёт "тестовой инфраструктуры" – обычно она отделена от основного кода и является зоной ответственности команды QA. QA не лезут в код самого проекта, программисты не лезут в тесты. Разумный предел – читать код друг друга, но не модифицировать самим.
Это довольно устаревший взгляд. QA-инженеры уже давно не ограничиваются «тестированием интерфейса по кнопочкам». Они пишут интеграционные и изоляционные тесты внутри проекта, настраивают тестовую инфраструктуру, пайплайны, метрики, триггеры, покрытие, нагрузку, пишут кастомные ассерт-библиотеки и даже юнит-тесты — и делают это прямо в коде.
Вы описали не "правило", а модель взаимодействия, и таких моделей десятки. Всё зависит от зрелости команды, договорённостей и культуры. И если QA может внести улучшение в код — ничего страшного, если он это сделает. Это не вторжение, а вклад. Если разработчик против и может сделать все это сам — пожалуйста, флаг в руки.
У нас в gfn.am используются транзитивные идентификаторы, назвали dbs-codes (design breakout system) которые идут от фигмы, через реакт, и до самого гуглоаналитика.
Чтоб по айдишнику всегда можно было найти элемент где угодно.
Принцип тот же самый - котенкст-сабконтекст-контрол
Прочитал с большим интересом! Кстати, у нас с вами идеи довольно похожи. Вот тут я писал о кастомных идентификаторах и скоупах: https://habr.com/ru/articles/892326/. Будет интересно, загляните.
Попробую дополнить некоторые моменты для этого пройдусь по статье сверху вниз.
Завязка на текст: "А где кнопка?"
Текст - это не чья-то хотелка, а полноценный элемент дизайна системы. Что и куда должно быть вставлено и в каком виде определятеся требованиями к системе. А с точки зрения потока работ изменение текста - это то, что оформляется отдельной задачей и должно иметь обоснование. И, соответственно, вопрос, а надо ли такую задачу тестировать? И кто это должен делать?
На мой взгляд, получается так, что все равно в тестах (в чьих?) текст должен быть. И, соответственно, должны быть способы получить элемент по тексту.
Если разработчик против data-test-id — скорее всего, он просто не хочет, чтобы вы могли зацепиться за его DOM. Но это уже не про производительность. Это про территорию. И да, она теперь и ваша тоже.
Тут сразу такой вопрос возникает, если это все не нужно для продакшена, то зачем это туда посылать? Более того, какой-нибудь злонамеренный код получает удобную возможность парсить такой документ. Я не говорю, что все это серьезные проблемы, но вопросы такие напрашиваются.
Окей, пора перейти от слов к делу. Как именно ставить эти ваши data-test-id ...
На первый взгляд может показаться, что это что-то из разряда «требуется знание React на уровне Senior++», ...
Мне на первый взгляд приходит, что это организационная и техническая задача. Кто должен это делать? Как должен это делать? Когда должен это делать? Потому, что это отдельная ответственность и должен быть выработан подход внутри команды как решать эту задачу. Все упирается далеко не только, что бы навалить какого-то исходного кода в проект.
Каждый день тысячи QA Automation инженеров по всему миру просто открывают HTML, вставляют data-test-id="что-то-понятное" — и всё работает
Если честно, за десятилетие разработки такого ни разу не встречал. Просто для примера, что бы исходному коду попасть в ветку разработчика он должен пройти ревью. К репозиторию допущено только ограниченное количество сотрудников. Ни разу не видел, что бы тестеров добавляли в бэк или фрон репозитории просто для того, что бы он там добавлял локаторы.
Плюс, не забываем, что data-test-id может использоваться и на фронте, когда другие методы исчерпаны, а значит от них будут зависеть юнит-тесты, что тестер по определению трогать не должен.
Далее вы начинаете описывать, на мой взгляд, узкий кейс, который и обнажает недостаточную проработку деталей.
Установка Node.js
Могу посоветовать устанавливать ноду через менеджеры, например, nvm
Установка зависимостей
Тут имеет смысл, если не знакомы с фронтовыми проектами просто побеседовать с фронт-разработчиком или прочитать readme.md. Потому что то, что вы написали очень узкий кейс. Запустив yarn install
на современном проекте без должно подготовки приведет не к установки зависимостей, а к получению подробной подсказки что нужно сделать, что бы эту подготовку произвести.
Ждём немного... Да, установка может занять минутку
В данном конкретном случае, если бы вы использовали не 1.22 версию, то установка заняла бы в 2 раза меньше времени =Р. А может и в 10 раз.
Главное — после установки у вас появится волшебная папка node_modules, и проект оживёт.
На самом деле необязательно. Если проект поддерживает pnp загрузку моделей, то этой папки не будет и искать ее не нужно.
Поэтому, я и говорю, что опустил бы все такие детали и просто дал отсылку на инструкцию как установить ваш конкретный тестовый проект.
Почему это работает:
Разработчик знает структуру лучше всех.
Экономит вам часы бестолкового блуждания.
Думаю, дело не столько в знании структуры. Просто у разработчика стоят инструменты разработчика для реакта, вью и т.п. И он ищет нужный компонент по имени.
По сути, вот там выше вам тоже нужно было этот пункт добавить.
Случай 1: Простой компонент — просто добавляем data-test-id
Допустим, довили вы data-test-id={'welcome-title'}
и что вы собрались тут тестировать? Где сам тест?
Просто, что-то мне подсказывает, что где-то есть задача, в которой ясно указано какой текст должен быть на экране. И собственно в этом и есть часть задачи тестирования, т.е. проверить что бы такой текст попал на экран.
Как обстоят дела на самом деле в реальных проектах?
Почему? Потому что (внимание, шок-контент) продукт делают для пользователей, а не для ваших автотестов. Вот так поворот.
Сейчас под пользователями могут понимать довольно широкую аудиторию. Например, в том числе и людей с ограниченными возможностями. И сразу же вопрос, а вы с помощью тестовый идентификаторов будете и для них тестировать приложение?
Там тоже это будет лучшей практикой? Или автотесты игнорируют эту часть приложения?
Как внедрять data-test-id и не развалить проект?
Т.е. все внедрение, думаете, упирается только в добавление исходного кода, а кто, как, когда эти вопросы сами могут решиться?
Подключайте фронтенд-разработчиков (сюрприз: они не против)
Серьёзно, для фронтенда поставить data-test-id — это даже не задача. Это полсекунды внимания.
Это когда процесс определен и внедрен.
Не требует архитектуры.
Как все что добавляется в репозиторий - это так же требует архитектуры.
Не трогает бизнес-логику.
Тесты должны тестировать бизнес-логику. И если какую-то бизнес-логику протестировать не получается, очевидно, ее нужно "поменять" так, что бы она была тестируемой.
Общий принцип именования data-test-id
По сути, вы заменили неудобные селекторы на удобные. Но процесс выбора никак не опирается на семантику того, что происходит на экране. И в селекторе вы стараетесь повторить роли элементов DOM.
Поэтому сразу хочется спросить, а точно нет другого выбора?
Я вот открываю доку на плэйрайт и там в [первых же пунктах](https://playwright.dev/docs/writing-tests#first-test)
First test
Take a look at the following example to see how to write a test.
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Тут нет тестовых идентификаторов, а селекторы опираются на семантику того с чем взаимодействует пользователь. И проверяется ровно то, что находится (должно там находится) в описании к задаче
А
data-test-id
— это то, что делает автотесты надёжными, предсказуемыми и стабильными. Хотите вы этого или нет — он победит.
Что-то мне подсказывает, что в том виде в котором вы его продвигаете он уже себя отжил. Сейчас тестовые идентификаторы используют только когда другие способы исчерпаны.
Текст - это не чья-то хотелка, а полноценный элемент дизайна системы. Что и куда должно быть вставлено и в каком виде определятеся требованиями к системе. А с точки зрения потока работ изменение текста - это то, что оформляется отдельной задачей и должно иметь обоснование. И, соответственно, вопрос, а надо ли такую задачу тестировать? И кто это должен делать?
На мой взгляд, получается так, что все равно в тестах (в чьих?) текст должен быть. И, соответственно, должны быть способы получить элемент по тексту.
Конечно, надо. Если текст влияет на поведение пользователя — он часть функциональности, и как любая функциональность, должен покрываться тестами. Но вот что важно: тестировать по тексту — не значит привязываться к нему. Тексты меняются, локализуются, управляются вне продуктовой команды — и именно поэтому привязка к тексту делает тесты хрупкими. Это не про "хотелки", это про устойчивость автотестов и здравую архитектуру.
Тут сразу такой вопрос возникает, если это все не нужно для продакшена, то зачем это туда посылать? Более того, какой-нибудь злонамеренный код получает удобную возможность парсить такой документ. Я не говорю, что все это серьезные проблемы, но вопросы такие напрашиваются.
Во-первых, "не нужно для продакшена" — это спорное утверждение. Автотесты — это часть продукта, обеспечивающая его качество. Во-вторых, если вы опасаетесь, что data-test-id
могут быть использованы злоумышленниками — тогда стоит обеспокоиться всем HTML-кодом. Это публичная часть системы, и для защиты от парсинга или сканирования есть отдельные механизмы (например, Cloudflare, WAF и т.д.), а не отказ от удобств для QA.
Мне на первый взгляд приходит, что это организационная и техническая задача. Кто должен это делать? Как должен это делать? Когда должен это делать? Потому, что это отдельная ответственность и должен быть выработан подход внутри команды как решать эту задачу. Все упирается далеко не только, что бы навалить какого-то исходного кода в проект.
Согласен. Именно поэтому в статье и написано, как выстраивать этот процесс. Удивительно, что вы, видимо, этого не заметили. Вопрос не в том, чтобы "накидать кода", а в том, чтобы договориться в команде, зачем и как использовать data-test-id
— с учётом архитектуры, CI/CD и нужд тестирования.
Если честно, за десятилетие разработки такого ни разу не встречал. Просто для примера, что бы исходному коду попасть в ветку разработчика он должен пройти ревью. К репозиторию допущено только ограниченное количество сотрудников. Ни разу не видел, что бы тестеров добавляли в бэк или фрон репозитории просто для того, что бы он там добавлял локаторы.
То, что вы этого не видели — не делает это редкостью. В мобильной разработке, например, это повсеместная практика. Во многих веб-проектах — тоже. Всё зависит от культуры команды. Если у вас доступы к Postman дают через 2 месяца, а к репозиторию — через 6, это не аргумент, это сигнал о проблемах в организации, а не в data-test-id
.
Могу посоветовать устанавливать ноду через менеджеры, например,
nvm
Всё это уже рассмотрено в статье. Упомянуты варианты установки, необходимость обсуждений с фронтендом и чтение README.md
. Если вы это не заметили — возможно, стоит перечитать внимательнее.
Допустим, довили вы
data-test-id={'welcome-title'}
и что вы собрались тут тестировать? Где сам тест?
Это статья не про сами тесты, а про то, как сделать проект удобным для написания устойчивых тестов. Не нужно подменять тему статьи.
Сейчас под пользователями могут понимать довольно широкую аудиторию. Например, в том числе и людей с ограниченными возможностями. И сразу же вопрос, а вы с помощью тестовый идентификаторов будете и для них тестировать приложение?
Если вы действительно озабочены доступностью, то да, используйте aria-labels, роли и тесты с user-facing локаторами. Но это никак не отменяет использования data-test-id
— это не конкурирующие подходы, а взаимодополняющие.
Я вот открываю доку на плэйрайт и там в [первых же пунктах](https://playwright.dev/docs/writing-tests#first-test)
Playwright рекомендует в зависимости от целей: если вам важен текст — используйте текст. Если вы хотите стабильные тесты — используйте data-test-id
. Это не противопоставление, это инструмент под нужду. Просто откройте правильный раздел документации. И там четко написано:
Шах:
Testing by test ids is the most resilient way of testing
И мат:
QA's and developers should define explicit test ids
Вы просто выдрали из контекста и пытаетесь выдать это за истину. Очевидно никто не будет в самой первой странице доки сразу грузить про тестовые идентификаторы, PageObject, PageFactory, PageComponent и прочие прелести. Это очевидно.
По итогу. Вы поднимаете понятные, но давно разобранные вопросы. Ваш опыт — это ваш опыт, но он не универсален. Реальный масштаб и зрелость QA-инфраструктуры как раз и проявляются в таких деталях, как data-test-id
. Это вопрос культуры качества, а не вкусовщины.
Конечно, надо. Если текст влияет на поведение пользователя — он часть функциональности, и как любая функциональность, должен покрываться тестами. Но вот что важно: тестировать по тексту — не значит привязываться к нему. Тексты меняются, локализуются, управляются вне продуктовой команды — и именно поэтому привязка к тексту делает тесты хрупкими. Это не про "хотелки", это про устойчивость автотестов и здравую архитектуру.
Как это управляются вне продуктовой команды? Они продуктовой командой управляются.
Что значит не привязываться к нему? И почему тогда нельзя так же не привязываться при выборке? Что значит устойчивость автотестов и здравая архитектура в данном случае?
Приведите пример в случае с тем же заголовком. Мне действительно интересно узнать, что тут имеется в виду относительно всего того, что вы написали.
Во-первых, "не нужно для продакшена" — это спорное утверждение.
Да? А какие тут спорные моменты?
Автотесты — это часть продукта, обеспечивающая его качество.
И что из этого следует? Например, юнит тесты тоже часть продукта обеспечивающие его качество.
Во-вторых, если вы опасаетесь, что
data-test-id
могут быть использованы злоумышленниками — тогда стоит обеспокоиться всем HTML-кодом. Это публичная часть системы, и для защиты от парсинга или сканирования есть отдельные механизмы (например, Cloudflare, WAF и т.д.), а не отказ от удобств для QA.
Я в данном случае просто поставил вопросы. Я так и не увидел зачем это в проде. А оставлять рудементы разработки, просто, зачем?
Согласен. Именно поэтому в статье и написано, как выстраивать этот процесс. Удивительно, что вы, видимо, этого не заметили.
Именно как выстраивать процесс в статье очень мало. Есть пример каких-то техник, которые крайне слабо детализированы. И в таком виде не могут служить руководством. А вот как информация к размышлению вполне.
Вопрос не в том, чтобы "накидать кода", а в том, чтобы договориться в команде, зачем и как использовать
data-test-id
— с учётом архитектуры, CI/CD и нужд тестирования.
Да, если использовать, то договориться нужно. Но это не выстроенный процесс.
То, что вы этого не видели — не делает это редкостью. В мобильной разработке, например, это повсеместная практика. Во многих веб-проектах — тоже. Всё зависит от культуры команды. Если у вас доступы к Postman дают через 2 месяца, а к репозиторию — через 6, это не аргумент, это сигнал о проблемах в организации, а не в
data-test-id
.
Вы путаете онбординг и вот эту вашу инициативу. Всем ответственным доступы дают сразу. А тестеру в исходном коде делать нечего. И по моему, это уже больше похоже на бардак, если локаторы в исходный код добавляет тестер.
Всё это уже рассмотрено в статье. Упомянуты варианты установки, необходимость обсуждений с фронтендом и чтение
README.md
. Если вы это не заметили — возможно, стоит перечитать внимательнее.
Нет там этого, поэтому и предложил. Вы просто предложили сказать с сайта ноды.
Это статья не про сами тесты, а про то, как сделать проект удобным для написания устойчивых тестов. Не нужно подменять тему статьи.
А почему тогда на месте не привести пример этого самого устойчивого теста. Ну, т.е. вот вы ввели свой тест айди и получился вот такой вот тест. А то в вашем примере мне не понятно, что вы собрались тестировать и как. А отсюда непонятно, зачем вам тогда в данном примере тест айди.
Я именно поэтому предложил. Это точно приводит к устойчивому тесту? Просто, по тому что в статье это совсем не очевидно. Теста то нет.
Если вы действительно озабочены доступностью, то да, используйте aria-labels, роли и тесты с user-facing локаторами. Но это никак не отменяет использования
data-test-id
— это не конкурирующие подходы, а взаимодополняющие.
Использование тест айди действительно дополняет семантичное тестирование. Но само семантичное тестирование - это прямой конкурент тестирования только с помощью тест айди.
У использования тест айди сейчас есть своя ниша - это применение тогда, когда другие способы исчерпаны.
Playwright рекомендует в зависимости от целей: если вам важен текст — используйте текст. Если вы хотите стабильные тесты — используйте
data-test-id
. Это не противопоставление, это инструмент под нужду. Просто откройте правильный раздел документации. И там четко написано:Шах:
Testing by test ids is the most resilient way of testing
И мат:
QA's and developers should define explicit test ids
Так а вы внимательно это все прочитали? Там же ясно написано, что если вам нужны тесты ориентированные на пользователя ваш рекомендуется подход рассчитанный на семантичные локаторы. Вот тестируете вы пользовательский интерфейс как если бы его использовал пользователь и рекомендуются семантичные локаторы.
Вот же вся история целиком, зачем ее на части дробить?
Testing by test ids is the most resilient way of testing as even if your text or role of the attribute changes, the test will still pass. QA's and developers should define explicit test ids and query them with page.get_by_test_id(). However testing by test ids is not user facing. If the role or text value is important to you then consider using user facing locators such as role and text locators.
Для тестирования синтетики для которой не важна семантика никакого смысла использовать семантичные локаторы нет. А вот когда вы тестируете бизнес логику семантика элементов на экране важна. Собственно вы ее и тестируете.
Поэтому никаких шах и матов тут нет. Если вам при постановке задачи прямо написали, что семантика не важна тогда вам нужны несемантичные локаторы.
Вы просто выдрали из контекста и пытаетесь выдать это за истину. Очевидно никто не будет в самой первой странице доки сразу грузить про тестовые идентификаторы, PageObject, PageFactory, PageComponent и прочие прелести. Это очевидно.
Простите, а почему? Если это основная практика как вы заявляете, значит ей место на первой странице. Это специфические случаи можно оставить для отдельных разделов документации, а на поверхности всегда общие случаи. Если дока, конечно, в мясину не устарела.
По итогу. Вы поднимаете понятные, но давно разобранные вопросы. Ваш опыт — это ваш опыт, но он не универсален. Реальный масштаб и зрелость QA-инфраструктуры как раз и проявляются в таких деталях, как
data-test-id
. Это вопрос культуры качества, а не вкусовщины.
Тогда, наверное, стоило копать глубже. И не на словах, а на примерах показать конкурентные подходы. Мне теперь вообще тогда непонятно, а когда стоит использовать семантичный подход по вашему? И что конкретно тогда вы тестируете, если для вас судя по тому, что написано в документации на которую Вы же и дали ссылку сказано, что ваш подход нужен для когда тесты не ориентированы на пользователя, т.е. не тестируют то как пользователь взаимодействует с системой. Вы что тестируете?
Интересный стиль у вас — вы сперва ставите под сомнение очевидные вещи, а потом доказываете, что они действительно очевидны.
В любом случае. Спасибо за поток мыслей — местами занятно, но всё же давайте на этом остановимся. У меня нет времени на бесконечные теоретические споры. Если вы действительно знаете, как правильно — покажите это делом: кодом, подходом, опытом, проектом, статьей "как надо". Пока что всё это выглядит как пустой трёп с претензией на истину.
На этом предлагаю поставить точку.
Я поставил под сомнение ваше предложение. И оно не очевидно. Есть узкий круг задач для которых ваше решение подходит. По ссылке которую вы дали, эти задачи обозначены. В вашей статье вообще непонятно что и как вы тестируете, т.е. прямо вот вообще.
И причем тут теория? Вот ссылка на локаторы плэйрайта Locators | Playwright Python которую вы дали. Там полно локаторов и резонно возникает вопрос, почему в статье о них ни слова? Хотя бы намеком обозначили почему они вам не подошли.
Если вам все это не интересно, ну, ладно.
Спасибо за статью!
Идея добавления тестовых атрибутов напрямую силами AQA действительно интересная, но, на мой взгляд, слабо применима в условиях enterprise-проектов. В таких компаниях команды разработки и тестирования, как правило, разделены, и внесение изменений в кодовую базу (особенно фронта или монорепозитория) требует утверждения и ревью, на которое вряд ли кто-то согласится — не из вредности, а из-за процессов и приоритетов.
Как альтернатива — можно формализовать необходимость добавления таких атрибутов на этапе постановки требований. Например, на основании макетов или заранее подготовленных тест-кейсов закрепить требование на добавление подобных атрибутов как часть спецификации. В таком случае реализация ляжет на разработчика, и всё будет прозрачно и официально.
P.S.
Безопасно ли это?
Также из интересных причин, по которым не хотят внедрять подобный подход, которые я слышал - это "мы упростим работу ботам, которые парсят наш сайт"))
Идея добавления тестовых атрибутов напрямую силами AQA действительно интересная, но, на мой взгляд, слабо применима в условиях enterprise-проектов. В таких компаниях команды разработки и тестирования, как правило, разделены, и внесение изменений в кодовую базу (особенно фронта или монорепозитория) требует утверждения и ревью, на которое вряд ли кто-то согласится — не из вредности, а из-за процессов и приоритетов.
Согласен, в условиях enterprise-проектов часто бывают серьёзные ограничения на любые изменения в кодовой базе, особенно если фронт — это монорепозиторий, с отдельной очередью на ревью, приоритетами и безопасностью. Бывает, что на пользование курлом нужно два месяца доступ ждать. Именно поэтому я в статье и акцентировал, что можно договориться с разработчиками: договориться — ключевое слово.
Как альтернатива — можно формализовать необходимость добавления таких атрибутов на этапе постановки требований. Например, на основании макетов или заранее подготовленных тест-кейсов закрепить требование на добавление подобных атрибутов как часть спецификации. В таком случае реализация ляжет на разработчика, и всё будет прозрачно и официально.
Да, это хороший способ. Такой подход работает хорошо в продуктовых командах, где требования и UI-дизайн формализуются заранее. При этом даже если QA не правит код напрямую, он может быть инициатором таких изменений и участником обсуждения, вплоть до постановки задач фронтам.
Также из интересных причин, по которым не хотят внедрять подобный подход, которые я слышал - это "мы упростим работу ботам, которые парсят наш сайт"))
Это классика. Но если кто-то действительно захочет парсить сайт — наличие или отсутствие data-test-id
вообще ни на что не повлияет. Это ложное чувство безопасности. А вот от настоящих угроз спасают инструменты вроде Cloudflare, WAF и капч.
с Playwright понятно. а как использовать эти аттрибуты в Java/Python + Selenium? мне пока приходится писать xpath'ы типа
//div[@data-testid='username_textfield']
Спасибо за вопрос!
Да, в Selenium нет нативной поддержки data-testid
— это просто кастомный атрибут, как и любой data-*
. Но обращаться к нему можно абсолютно спокойно, обычными средствами:
driver.find_element(By.CSS_SELECTOR, "[data-testid='username_textfield']")
Или:
driver.findElement(By.xpath("//div[@data-testid='username_textfield']"));
Если надоело писать XPath руками — просто оберните в helper:
def get_by_test_id(driver, test_id):
return driver.find_element(By.CSS_SELECTOR, f"[data-testid='{test_id}']")
Да, не Playwright, но работает. Либо можно использовать подход с PageFactory и инкапсулировать все это безобразие на уровне элементов. У меня было несколько статей на эту тему:
Пишем UI авто тесты на TypeScript с использованием Page Object, Page Factory
UI автотесты на Python с запуском на CI/CD и Allure отчетом. PageObject, PageComponent, PageFactory
Там везде используется Playwright, но и для Selenium с PageFactory пример имеется https://github.com/Nikita-Filonov/selenium_python
так и в чем проблема? если есть уникальный атрибут, то неважно через css или xpath вы его напишете. только одно замечание: удалить div! автор почему-то этого не сделал, что снижает доверие.//*[@data-testid='username_textfield']
вот так супер.
по поводу статьи, идея совсем не новая как и практика. хорошая практика: делать исследование и сбор источников прежде чем публиковаться. если вдруг используется "аи", тоже можно попросить найти источники, правда не каждая сдюжит
Пожалуйста, не вводите людей в заблуждение. НИКОГДА нельзя использовать xpath, сss selectors, data-attributes при тестировании. Это больше подходит под создание быстрых автоматизаций. на сайте playwright даже об этом говориться. Лучше и правильнее тестировать поведение, видимое пользователю. Например, вместо xpath до кнопки использовать page.getByRole - это гарантирует то, что мы пытаемся найти кнопку на которую может кликнуть пользователь (она видна, она доступна), и не важно где она находится.
Не тестируйте свои кнопки, тестируйте поведение пользователя этими кнопками
Я вот тоже до сих пор так и не понял, что и как автор там у себя тестирует. Никаких внятных ответов до сих пор не получил. А жаль, было бы интересно.
Вижу, что моего виртуального совеседника не отпускает даже спустя почти неделю — и это трогательно. Видимо, статья задела не только старые взгляды, но и внутреннего архитектора из 2015-го, который до сих пор воюет с CSS-селекторами в тестах.
Но, пожалуйста, давайте всё-таки различать: разбор технических практик — это не приглашение к бесконечным эмоциям, токсичности и логическим кульбитам. Особенно когда спорят не с темой статьи, а с выдуманным врагом.
И да, если вас интересует мой личный процесс тестирования — он уже давно делегирован. Моё дело — обучать и направлять. Но учеников я всё-таки подбираю осознанно: те, кто пытается вести диалог с позиции «комнатного гангстера», в команду не попадают.
На этом, пожалуй, и закончим. Возвращаться к обсуждению снова через три дня не обязательно.
Нет. Серьезно смешно. Вся ваша статья про войну с СиЭсЭс селекторами, а воюю где-то у себя в фантазиях значит я XD
А теперь по поводу разбора технических практик. Ниже, есть ваша цитата в которой вы претендуете на куда большее. А после ваших откровений что реальным тестированием вы не занимаетесь, я понимаю почему статья получилась настолько искусственной, устаревшей и без реальных примеров кода тестов. Вы явно не понимаете, когда нужно использовать тестовые идентификаторы. Отсюда у вас и примеры, где вы на заголовок вешаете идишник. Иными словами, вы написали статью о вещах, которые не знаете когда это нужно применять.
п.с.: я здесь не на зарплате, поэтому захожу и отвечаю когда мне удобно XD А вы даже тут какими-то инфантильными категориями мыслите: "... не отпускает даже спустя неделю" - серьезно, очень забавно все это выглядит особенно на фоне качества статьи.
Понимаю, что неприятно, когда аргументы закончились, а самолюбие всё ещё требует продолжения. Но увы — тема статьи вам не по зубам, а перейти на личности — единственный инструмент, который у вас остался.
Всё остальное — это нервная самозащита, не аргументация. Удачи вам в воображаемой борьбе с устаревшими статьями, которую вы сами же и начали.
В смысле закончились? Вы же сами все игнорируете. И причем тут переход на личности с моей стороны, если вы сами начали эту телегу, как меня все задело и Только в этом все дело. Блин, серьезно, я как с ИИ беседую.
Кстати, впервые вижу, что бы на неновые статьи голоса к комментариям росли чуть ли не в реальном времени. Вы там своих ботов подключили что ли? XD Это к теме про самолюбие кстати))
Наблюдал весь спор со стороны. Сначала думал ну ок, просто мнение
А потом понял простую штуку когда у человека нет ни статей, ни кейсов, ни аудитории, ни хоть какого-то опыта писать публично ему остаётся просто заходить в комменты раз в три дня, цепляться к словам и таким образом как бы доказывать что он есть
Автор пишет, делится опытом, объясняет, а вы просто обесцениваете при этом не предоставив ничего в ответ. И продолжаете что-то еще вбрасывать
Весь ваш разбор полетов по факту свёлся к нападкам и слову инфантильный. Это не аргументы. Это просто обида, завёрнутая в псевдорациональность
Спасибо, кстати, что напомнили - токсичность и экспертность вообще не одно и то же. Иногда даже противоположности.
Ну, это уже какая то лень и откровенная халтура в ответах. Во первых, в ответ предоставлено много чего и по существу. А во вторых, не надо ничего выдумывать, а просто пройдите в профиль и посмотрите есть статьи или нет.
У вас получилось пустое и ложное выступление. Зачем?
Окей, заглянул в профиль - увидел.
Честно я ожидал статьи уровня "вот как мы реализовали стратегию тестирования сложного UI без data-testid
", с кодом, с кейсами, с практикой, со ссылками и скриншотами. А не "счётчики шаблонов строк в TypeScript" на 1.2k просмотров, просто ухх, как сильно.
Всё это конечно имеет право на существование. Но вы сами выставили планку и делали заявления вроде "я так всегда в продакшене", "data-testid это говнокод" и т.д. А теперь оказывается, что вы болтун, увы.
А на деле у вас статьи уровня заметок для новичков и ни одного проекта, где видно, как вы решаете те реальные задачи про которые спорите. Просто раз за разом заходите в комменты и рассказываете, как все делают неправильно.
Вот в этом и есть разница: одни делятся рабочими решениями, другие рассказывают что всё это плохо, но своих решений не показывают.
Вы называете это "ленью и халтурой"? Ну что ж, судя по вашим статьям, вы вряд ли понимаете, что такое production UI, CI/CD или стабильные тесты. Мы просто о разном.
Честно я ожидал статьи уровня "вот как мы реализовали стратегию тестирования сложного UI без
data-testid
", с кодом, с кейсами, с практикой, со ссылками и скриншотами. А не "счётчики шаблонов строк в TypeScript" на 1.2k просмотров, просто ухх, как сильно.
Тем не менее, это полностью отменяет ту ленивую ерунду, которую вы ранее выдали. А то что вы уже предвзяты и вас не интересуют мои статьи я понял.
Всё это конечно имеет право на существование. Но вы сами выставили планку и делали заявления вроде "я так всегда в продакшене", "data-testid это говнокод" и т.д. А теперь оказывается, что вы болтун, увы.
Простите пожалуйста, а из чего это следует? Где тот конфликт между тем, что я говорю и, например, целями и заявлениями авторов фреймворков, которыми сейчас пользуются для тестирования масса людей и автор статьи в том числе?
По сути, это опять ленивая попытка отменить мои предложения. Но получилось еще более лениво чем в первый раз.
А на деле у вас статьи уровня заметок для новичков и ни одного проекта, где видно, как вы решаете те реальные задачи про которые спорите. Просто раз за разом заходите в комменты и рассказываете, как все делают неправильно.
Не надо обобщать. Я говорю как надо правильно. И не я один. Доберутся руки, напишу заметку и про тестирование.
Вот в этом и есть разница: одни делятся рабочими решениями, другие рассказывают что всё это плохо, но своих решений не показывают.
Ну, я могу и вам вопрос задать. А чем не рабочие решения, которые продвигают создатели РТЛ и Плейрайта? Что с ними не так?
Причем, это действительно любопытно. Вы готовы плодить кучу уникальных идентификаторов, а вложить усилия в создание уникального описания элемента не можете. Причем, выше я даже дал рабочее решение, т.е. уникальным делать родительский блок, а общие элементы не специфицировать раз вам лень. Это сократит количество требуемых уникальных идентификаторов в десятки раз. И при этом сделать приложение понятным более широкой аудитории. И почему это плохо?
Вы называете это "ленью и халтурой"? Ну что ж, судя по вашим статьям, вы вряд ли понимаете, что такое production UI, CI/CD или стабильные тесты. Мы просто о разном.
До сих пор не увидел никаких аргументов почему тесты использующие семантику элементов менее стабильные?
Спасибо за мнение! Напомню, что статья посвящена техническим аспектам расстановки test-id
, а не подходам к тестированию UI — вы, похоже, спорите с темой, которой в статье даже не было.
Будет здорово увидеть вашу статью, примеры кода и аргументацию на тему "как правильно тестировать". Пока её нет — позволю себе отнестись к вашему комментарию как к пустому трёпу, не более.
Но если появится содержательный материал — рад обсудить по делу.
Напомню, что статья посвящена техническим аспектам расстановки
test-id
, а не подходам к тестированию UI
Да? А это тогда что?
И давайте скажем это вслух: если ваши автотесты сыпятся из‑за смены классов, цвета, или позиции элемента — виноваты не разработчики, не продукт, не космос, не ретроградный Меркурий. Виноваты вы. Да‑да, вы, QA Automation инженер, который решил «ну тут же можно взять по
div:nth-child(42)
, норм же работает». Нет, не норм. Вы создали флак, вы допустили нестабильность, вы наплодили технический долг в автотестах. Хотите стабильности? Учитесь писать тесты правильно. Хотите гордиться своими автотестами, а не прятать их отчеты под стол? Добро пожаловать — сейчас научим.
Тут как бы все ясно, без как бы. Вы учите как писать тесты, если они "сыпяться". Учите писать тесты "правильно". Но на самом деле нет.
Как бы на эту тему выше высказались, но добавлю акцента на доступности (a11y которая).
Тестируя UI через роли и доступные лейблы, мы сразу автоматом проверяем, что затронутая часть интерфейса доступна (ну, как минимум, отчасти).
А если по умолчанию тестировать через test-id, то тесты доступности надо как-то придумать отдельно сбоку.
Утрированный пример - сверстали всю страницу div-ами, на которые навешаны обработчики кликов. Тесты через test-id работают - ура. Инструменты типа axe
тоже ошибок не найдут (разве что - отсутствие h1) - ведь у нас тут нет элементов со спец ролями, на которые заточены проверки в таковых инструментах. А со скрин-ридера - да или просто с клавиатуры без мышки - пользоваться этой страницей невозможно.
Комментарий про role
и aria-label
абсолютно по делу — и в идеале UI-тесты действительно должны быть ориентированы на доступные элементы.
Но в реальных условиях этого недостаточно для стабильных автотестов. Представим типичную страницу CRUD-интерфейса: список сущностей, у каждой — кнопки «Edit», «Delete», «Details». И вот у вас уже 25 кнопок с role="button"
и aria-label="Edit"
. Все кнопки визуально отличаются и работают — но для автотеста они неразличимы:
<button role="button" aria-label="Edit">
<svg><!-- edit icon --></svg>
</button>
А если ещё и aria-label одинаковый — всё, вы возвращаетесь к хакам типа nth-child(25)
или getAllByRole("button")[17]
, что уже и нестабильно, и небезопасно.
То же самое в случае со списками, таблицами, карточками: компоненты повторяются, а смысл различия — только в данных или окружении.
Поэтому data-testid
или data-qa
остаются ключевыми якорями для стабильных UI тестов. Они отделяют техническую точку входа от пользовательской, и позволяют чётко указать: «я хочу эту кнопку, у этой сущности».
К тому же, никто не мешает в UI-тестах проверять тексты. Даже если вы используете data-testid
как точку входа, внутри теста можно (и нужно!) проверять, что у элемента есть правильный текст, aria-label
, role
, title
— всё, что важно для пользователя и доступности:
button = page.get_by_test_id("edit-user-button")
expect(button).to_have_text('Edit user')
expect(button).to_have_attribute('aria-label', 'edit-user')
Такой подход — это компромисс между стабильностью и доступностью:
data-testid
даёт стабильный селектор;Проверки текста, ролей и атрибутов — покрытие доступности и бизнес-смысла;
Плюс можно использовать snapshot-тесты для валидации всей разметки блока.
В итоге: Да, обсуждения про role
, aria-label
и доступность — это важно. Но зачастую они звучат из академической или теоретической плоскости. В реальных проектах, где десятки однотипных кнопок с иконками и динамически меняющиеся интерфейсы, надежные и поддерживаемые UI-тесты без data-testid
просто невозможны.
Мы тестируем не HTML-структуру ради структуры, а пользовательский сценарий: что-то должно отработать, когда пользователь нажал нужную кнопку — и тест должен это гарантировать. Упор идет на бизнес-логику.
Поэтому:
data-testid
— наш якорь в хаосе;Проверки
aria-*
,role
,innerText
— проверка смысла;A11y — это отдельный слой, и он заслуживает своих тестов.
А когда кто-то говорит “тестируйте только по ролям”, хочется спросить — а вы в продакшене так уже делали?
Но в реальных условиях этого недостаточно для стабильных автотестов. Представим типичную страницу CRUD-интерфейса: список сущностей, у каждой — кнопки «Edit», «Delete», «Details». И вот у вас уже 25 кнопок с role="button" и aria-label="Edit". Все кнопки визуально отличаются и работают — но для автотеста они неразличимы:
Давайте разберемся, что вы тут написали.
Имеем: aria-label="Edit"
. Для начала вспомним, что же такое aria-label
. Думаю, будет полезно для тех кто забыл или нет знал.
The aria-label attribute defines a string value that can be used to name an element, as long as the element's role does not prohibit naming.
Речь идет о так называемом "accessible name". А теперь вспомним что это такое:
An accessible name is the name of a user interface element; it is the text associated with an HTML element that provides users of assistive technology with a label for the element.
Accessible names convey the purpose or intent of the element. This helps users understand what the element is for and how they can interact with it. In general, accessible names for elements should be unique to a page. This helps users distinguish an element from other elements and helps users identify the element they want to interact with.
Иными словами, по смыслу, в хорошем приложении не может быть двух элементов с одинаковым именем, потому что тогда теряется назначение данного элемента.
Таким образом получается, что вы говорите не про "реальные условия", а про говнокод или про легаси в котором не учитывалась семантика элементов.
А если ещё и aria-label одинаковый — всё, вы возвращаетесь к хакам типа nth-child(25) или getAllByRole("button")[17], что уже и нестабильно, и небезопасно.
Вообще, необязательно. Опять же по смыслу, можно добавить семантики контейнеру который содержит все эти похожие элементы. И вместо навешивания десятка тестовых идентификаторов достаточно будет добавить семантики контейнеру. Выбрать этот контейнер, а потом использовать его как контекст для всех таких вот кнопочек используя семантичные локаторы.
Таким образом получается, что даже в таких случаях использование тестовых идентификаторов - это самое последнее ленивое и неоптимальное дело.
То же самое в случае со списками, таблицами, карточками: компоненты повторяются, а смысл различия — только в данных или окружении.
Тут опять имеет смысл сделать замечание, что речь идет о говнокоде или легаси. Но как мы выяснили, вместо десятка тестовых идентификаторов будет достаточно одного явно обозначенного контейнера.
Поэтому data-testid или data-qa остаются ключевыми якорями для стабильных UI тестов. Они отделяют техническую точку входа от пользовательской, и позволяют чётко указать: «я хочу эту кнопку, у этой сущности».
Опять же хочется повторить, это если речь идет о говнокоде и таком же подходе к тестированию. Лучше, все таки, подумать и посмотреть нельзя ли добавить семантики контейнеру, а не наваливать идентификаторов всему до чего руки дотянутся.
И вопрос, если есть возможность добавлять уникальные тестовые идентификаторы, почему тогда нет возможности добавлять уникальную семантику? Ведь по смыслу, любая часть приложения имеет свой собственный смысл, который отличает ее от других частей.
button = page.get_by_test_id("edit-user-button")
expect(button).to_have_text('Edit user')
expect(button).to_have_attribute('aria-label', 'edit-user')
Как раз в том числе, что бы не писать лишний мусорный код и придумали подход с семантичными локаторами, где вместо трех используется одна строка кода.
В итоге: Да, обсуждения про role, aria-label и доступность — это важно. Но зачастую они звучат из академической или теоретической плоскости. В реальных проектах, где десятки однотипных кнопок с иконками и динамически меняющиеся интерфейсы, надежные и поддерживаемые UI-тесты без data-testid просто невозможны.
Как я показал выше - это полная туфта. И характерна она только для говнокода и легаси проектов.
А когда кто-то говорит “тестируйте только по ролям”, хочется спросить — а вы в продакшене так уже делали?
Я делал только так в продакшене. Тестовые идентификаторы приходилось использовать только в легаси, где все это использовалось с самого начала да и то, недолго.
Слежу за дискуссией. Интересно, а можно увидеть пример вашего production-проекта, где всё тестируется только по ролям без test-id? Просто хочется понять, как именно вы решаете проблему, когда на странице 10 кнопок “Edit”, и все с одинаковым aria-label.
Вы как-то через getByRole
с фильтрацией по данным внутри контейнера? Или у вас все aria-label действительно уникальны?
Тестовые идентификаторы приходилось использовать только в легаси
А ещё забавно, что вы называете data-testid
признаком легаси, в то время как React Testing Library и Playwright официально рекомендуют его для стабильного таргетинга, особенно в сложных UI. Видимо, им тоже надо “разобраться в семантике”.
Слежу за дискуссией. Интересно, а можно увидеть пример вашего production-проекта, где всё тестируется только по ролям без test-id? Просто хочется понять, как именно вы решаете проблему, когда на странице 10 кнопок “Edit”, и все с одинаковым aria-label.
Вы как-то через
getByRole
с фильтрацией по данным внутри контейнера? Или у вас все aria-label действительно уникальны?
Сам стараюсь делать так, что бы имя было уникальным, потому что так должно быть по определению. Если этого нет, это признак говно кода. Но если, имею дело с чужим кодом, где этого может не быть, то ничто не мешает выбирать контейнет и использовать его как контекст. Так же, этот подход можно использовать для оптимизации производительности, что бы искать в ограниченном месте, а не по всей странице, если конечно на странице несколько областей.
А ещё забавно, что вы называете
data-testid
признаком легаси, в то время как React Testing Library и Playwright официально рекомендуют его для стабильного таргетинга, особенно в сложных UI.
Ну давайте посмотрим что написано по ссылке на РТЛ:
In the spirit of the guiding principles, it is recommended to use this only after the other queries don't work for your use case. Using data-testid attributes do not resemble how your software is used and should be avoided if possible. That said, they are way better than querying based on DOM structure or styling css class names. Learn more about
data-testid
s from the blog post "Making your UI tests resilient to change"
Как я и говорил с самого начала, только когда все остальные способы исчерпаны используется тестовый идентификатор. В статье, на которую тут дана ссылка обозначено ровно все тоже самое. Действительно, есть специфические случаи когда имеет смысл помечать элемент метаданными. Наиболее частные из них - это работа с говнокодом и легаси.
В плейрайт написали тоже самое.
However testing by test ids is not user facing. If the role or text value is important to you then consider using user facing locators such as role and text locators.
Они прямо там так и пишут, что если вам не важна семантика должны использовать тестовые идентификаторы. Вопрос, когда вам не важна семантика?
Откуда вы взяли пассаж про "сложные UI" я не очень понял. И что это за "сложные UI"? Я вполне допускаю, что могут быть специфические задачи, но об этом нужно говорить явно. И четко понимать, что это специфические задачи.
Понял. То есть конкретного примера рабочего проекта, где это реализовано нет?
Просто я задал практический вопрос "как именно вы решаете типичную проблему с однотипными элементами". Но вместо ответа снова теория, оценочные суждения и ссылки на "как должно быть", без живого примера.
Это напоминает диалоги с недо-архитекторами, которые объясняют что весь код должен быть идеален, но сами ничего не пишут и не могут. Вы говорите "так нельзя", но не показываете, как можно)
Ничего личного. Просто мне ближе инженеры, такие как автор, которые показывают решения, а не обесценивают чужие. При этом судя по этому треду и треду ниже, вам то особо и нечего предоставить, типичный слив)
Это действительно забавно. Если вы не заметили, в статье нет ни одного кода теста. Т.е. что и как автор тестирует вообще непонятно. Какой вы "внимательны" я уже понял по первому вашему выступлению.
Все таки, могу посоветовать, читайте то на что отвечаете и статью за которой "следите". А то получается, вот такая вот ерунда как сейчас.
Вы либо не видите, либо не хотите видеть. Автор скинул и статью и проект с примерами кода всё по делу, как и что тестируется.
А от вас пока только слив и уход от темы. Где ваши проекты? Где ваши примеры, как вы делаете и тестируете в проде? Реальные проекты в студию. Пока их нет, вообще сложно воспринимать ваши аргументы в серьез, как будто реально просто задели за живое
Я делал только так в продакшене.
Спасибо, что вы действительно внимательно прочитали и отнеслись к теме объективно — это очень ценно.
Кажется, что продолжать обсуждение с ним уже не имеет смысла: ни одного конкретного примера, при этом постоянная агрессия, обесценивание и токсичность. Думаю, на этом разумно завершить дискуссию.
Это просто волшебно)
И так. Я поставил вопрос: "Зачем все это нужно, если есть современные фреймворки с семантичным подходом к выбору и тестированию функциональности" И к чему мы пришли?)
Отвечать на него вообще никто не хочет. Просто его рассмотреть тоже никто не хочет. Были какие-то вялые попытки, но после первой же критики молчание.
И так, пришли к следующему. Данный вопрос, имеет право задавать только тот кто напишет свою статью в которой полностью на него ответит. Все это дело подкрепит некими реальными проектами.
У меня просто нет слов, господа.
И второй момент, все что я тут писал, разумеет относилось и относится к данной статье. В ней действительно нет тестов.
А вы сами по этим ссылка следовали? Я интереса ради открыл первую. И это прям класс. Давайте на это посмотрим:
class Input(BaseElement):
"""
Класс для работы с полями ввода на странице. Наследует базовые методы от BaseElement
и добавляет специфичные методы для работы с полями ввода, такие как заполнение значений
и проверка значений в поле.
"""
@property
def type_of(self) -> str:
"""
Возвращает тип элемента, в данном случае "input".
Это полезно для унификации работы с различными типами элементов.
"""
return "input"
def get_locator(self, nth: int = 0, **kwargs) -> Locator:
"""
Получает локатор для поля ввода с возможностью параметризации и выбором индекса.
"""
# Вызываем родительский метод для получения базового локатора и добавляем локатор для input
# Может быть необходимо если на странице нужно как-то хитро получать поле ввода
return super().get_locator(nth, **kwargs).locator('input')
О-фи-геть.
А оказывается по порядковому номеру идентичных тестовых идишников вполне себе можно обращаться. А как там, с надежностью и удобством точно все норм будет?
А вот тут ничего не смутило?
class RegistrationFormComponent(BaseComponent):
"""
Компонент формы регистрации. Содержит поля: Email, Username, Password.
Предоставляет методы для заполнения и проверки отображения формы.
"""
def __init__(self, page: Page):
"""
Инициализирует элемент формы регистрации.
:param page: Экземпляр Playwright Page
"""
super().__init__(page)
# Поле ввода email
self.email_input = Input(page, "registration-form-email-input", "Email")
# Поле ввода username
self.username_input = Input(page, "registration-form-username-input", "Username")
# Поле ввода password
self.password_input = Input(page, "registration-form-password-input", "Password")
@allure.step("Fill registration form")
def fill(self, email: str, username: str, password: str):
"""
Заполняет форму регистрации заданными значениями.
:param email: Email пользователя
:param username: Имя пользователя
:param password: Пароль
"""
# Заполнение email и проверка, что значение введено корректно
self.email_input.fill(email)
self.email_input.check_have_value(email)
# Заполнение username и проверка, что значение введено корректно
self.username_input.fill(username)
self.username_input.check_have_value(username)
# Заполнение password и проверка, что значение введено корректно
self.password_input.fill(password)
self.password_input.check_have_value(password)
@allure.step("Check that registration form is visible")
def check_visible(self, email: str, username: str, password: str):
"""
Проверяет, что форма регистрации отображается корректно и содержит указанные значения.
:param email: Ожидаемое значение email
:param username: Ожидаемое значение username
:param password: Ожидаемое значение пароля
"""
# Проверка email-поля
self.email_input.check_visible()
self.email_input.check_have_value(email)
# Проверка username-поля
self.username_input.check_visible()
self.username_input.check_have_value(username)
# Проверка password-поля
self.password_input.check_visible()
self.password_input.check_have_value(password)
Метод Fill и заполняет и проверяет элемент
Метод check_visible содержит копипасту из Fill
А вот что творится под капотом у check_have_value
def check_have_value(self, value: str, nth: int = 0, **kwargs):
"""
Проверяет, что поле ввода содержит заданное значение.
:param value: Ожидаемое значение в поле ввода.
:param nth: Индекс, если на странице несколько одинаковых элементов.
:param kwargs: Дополнительные аргументы для параметризации локатора.
:raises AssertionError: Если значение в поле не соответствует ожидаемому.
"""
step = f'Checking that {self.type_of} "{self.name}" has a value "{value}"'
with allure.step(step):
locator = self.get_locator(nth, **kwargs)
logger.info(step)
expect(locator).to_have_value(value)
Знаете, после вот таких вот примеров реальных тестов и кода разговор действительно окончен. Я не знаю Питон, может там и в самом деле такая дрянь творится, но даже тут проблема не только в Питоне.
Знаете, если вы и в самом деле считаете, что можно ссылаться на такое в рамках вопросов которые я поставил тогда все вопросы снимаются. Копаться в чужом говно-коде мне не интересно.
А ещё забавно, что вы называете
data-testid
признаком легаси, в то время как React Testing Library и Playwright официально рекомендуют его для стабильного таргетинга, особенно в сложных UI. Видимо, им тоже надо “разобраться в семантике”.
Уффф. Вот это прям хороший панчлайн. Прям по голове документацией :)
Спасибо, но он уже сам себя закапывает с этими ссылками на доку)
У вас очень годная статья, сам как Full Stack разработчик могу подтвердить, что такие практики с data-test-id часто используются и я много где их встречал. Как минимум на прошлом проекте у нас был QA архитект из гугла, который помогал выстраивать нашим QA процессы тестирования. И тестовые идентификаторы была одна из первых практик
Тоже слежу за дискуссией. Два чела кидаются друг в друга какашками, споря чем лучше забивать гвозди: микроскопом или отвёрткой. И оба проигнорировали предложенный выше молоток.
Удаляю из трекера. Уже скучно.
Так вы предложили решение, которое работает только в вашей экосистеме. Или нет? Ваш молоток, это переписать все приложение на ваш фреймворк?
А почему нет? Вы же предлагаете внедрить решение, которое тянет за собой решение вопросов среди которых тестирование занимает в лучшем случае место десятое. Это не молоток - это целый комбайн, который к целям тестирования имеет опосредованное отношение.
И из вашего комментария выше не очень понятно, а что там генерируется? Этот идентификатор является "accessible name"? Или у вас там свои инструменты тестирования?
Не понял. Еще раз, вы предлагаете взять возможности реакта, и заменить их частично или полностью другой библиотекой. Это влечет за собой огромное количество задач. Вы же это предлагаете?
Наконец-то. Так тут же все тоже самое. Там нет ни слова о выборе элементов по семантике. Вот мне и любопытно, почему вы отказываетесь от этой практики? И даже ее не рассматриваете. Или все таки, где-то в недрах там есть материал по этому?
И плюс к тому, вы все еще предлагаете внедрять свой фреймворк вместо имеющегося для всего приложения. А это уже по определению не молоток, а комбайн.
У вас дурная привычка читать по диагонали и потом нести чушь. Ни к чему хорошему она вас не приведёт.
А где чушь?
Вам задают ясные вопросы. А вы тут какой то саморекламой неуместной занимаетесь.
Спасибо за столь подробное объяснение терминов.
Но давайте по делу. То, что вы описываете — это действительно красиво, академично, теоретично и правильно в идеальном мире. В котором все dev-команды религиозно следят за aria-атрибутами и являются accessibility-евангелистами, дизайны никогда не меняются, и всё подчинено a11y-практикам. Это мечта.
В реальности же: продукт должен работать, тесты — быть стабильными, а команда — успевать в сроки. И вот тут как раз появляется data-testid
, как технический механизм стабильности, а не "симптом говнокода", как вы пытаетесь это преподнести.
Вы говорите, что «делал только так в продакшене». Прекрасно. Правда, мы не видим ни ссылки на проект, ни кода, ни статьи — только агрессию, токсичность, лекции и обесценивание.
Поэтому это даже не спор — это просто ваш стиль общения: токсичный и снисходительный. Вы же не обсуждаешь идею — вы пытаетесь читать нотации. Если вам это приносит радость — без проблем.
Но на всякий случай: мой опыт, код, и подходы — лежат в открытом доступе. Показал, как тестируется реальный продукт, с реальными людьми, задачами и ошибками. А не с теорией “как должно быть”.
Так что давайте так: кому нужны реальные, стабильные решения — они их найдут у меня.
Но давайте по делу. То, что вы описываете — это действительно красиво, академично, теоретично и правильно в идеальном мире. В котором все dev-команды религиозно следят за aria-атрибутами и являются accessibility-евангелистами, дизайны никогда не меняются, и всё подчинено a11y-практикам. Это мечта.
Угу. А скажите пожалуйста, чем ваш подход с говоря вашим языком где "все дев-команды религиозно следять за тестовыми идишниками, являются ид-евангелистами и дизайны никогда не меняются отличается от "красиво, академично, теоретично"? Как видите такую туфту кто угодно сказать может.
А теперь по делу. То о чем я пишу, не я придумал. Это реальный подход из реального мира. И все современные средства на него ориентированы. А я об этом говорю, потому что последние 5 лет это использую.
Вот только что вы написали всякой муры уничижительной про этот подход и ровно ни одного аргумента, а почему вы его не используете. Мне с самого начала любопытно, почему вы решили отказаться от лучших практик РТЛ и Плэйрайта? Ни в статье, ни в комментариях об этом ни слова. И вот это уже действительно отдает какой-то религиозностью. Кроме, разве что описания частного случая говнокода, где вы сразу решили не делать правильно, а навалить еще больше говнокода.
В реальности же: продукт должен работать, тесты — быть стабильными, а команда — успевать в сроки. И вот тут как раз появляется
data-testid
, как технический механизм стабильности, а не "симптом говнокода", как вы пытаетесь это преподнести.
А вот создатели РТЛ и Плейрайта считают, что тесты должны отражать то как программу используют. И именно в этом видят стабильный, предсказуемый и надежный подход. И с этой целью продвигают свои инструменты. И уже не первый год. Которые покрывают не только их основной кей, но еще и специфические для которых может потребоваться тестовый идентификатор.
Или вы хотите сказать, что все это разработано для идеального мира? Очень интересно. А почему?
Но на всякий случай: мой опыт, код, и подходы — лежат в открытом доступе. Показал, как тестируется реальный продукт, с реальными людьми, задачами и ошибками. А не с теорией “как должно быть”.
Ну, плейрайт и РТЛ тоже лежат в открытом доступе. Там тоже полно примеров как надо тестировать РЕАЛЬНЫЙ продукт, а не какой-то мифический из идеального мира.
И кстати, после таких вот выступлений, вам про токсичность вообще не стоило бы даже заикаться.
хочется спросить — а вы в продакшене так уже делали?
Да, делал. В нашем случае - бОльшая часть сценариев хорошо закрывалась стратегией "тестируем через роли". В сложных / запущенных случаях прибегаем к test-id.
Также могу заметить, что
где десятки однотипных кнопок с иконками
вызовет трудности не только для тестов, но и для живых людей (особенно со скрин ридером).
Тестовые идентификаторы: как и где расставлять правильно