[{"data":1,"prerenderedAt":73},["ShallowReactive",2],{"wiki-test-automation-ui-test-locators-ru":3},{"meta":4,"html":8,"headings":9,"words":72},{"title":5,"description":6,"published":7,"updated":7,"sourceUpdated":7},"Локаторы в UI-автотестах","Локаторы в UI-автотестах: по роли, подписи, плейсхолдеру, test id, тексту, CSS и XPath, устойчивость к изменениям, порядок выбора и ожидание элементов.","2026-11-03","\u003Cp>\u003Cstrong>Локатор\u003C/strong> (locator) - описание того, как автотест пользовательского интерфейса находит элемент: кнопку, на которую он нажимает, поле, которое заполняет, сообщение, которое проверяет. Локатор состоит из стратегии и значения: «кнопка с доступным именем Sign in», «элемент с атрибутом \u003Ccode>data-testid\u003C/code>, равным \u003Ccode>cart-count\u003C/code>», «CSS-селектор \u003Ccode>form &gt; button.primary\u003C/code>». Тест обращается к элементам только через локаторы, поэтому именно в локаторах тест зависит от разметки страницы.\u003C/p>\n\u003Cp>Стандарт автоматизации браузера W3C WebDriver определяет пять стратегий поиска; его первый уровень (Level 1) стал рекомендацией W3C 5 июня 2018 года, а Level 2 - рабочий черновик (версия от 2 июля 2026 года). Selenium поддерживает восемь традиционных стратегий, среди них id, CSS-селектор и XPath. Playwright, начиная с версии 1.27, и Testing Library предлагают локаторы по атрибутам, которые видит пользователь: роли, подписи, тексту. Документация Playwright рекомендует их вместо CSS и XPath. Роли и доступные имена, на которые они опираются, определяет WAI-ARIA 1.2 - рекомендация W3C от 6 июня 2023 года.\u003C/p>\n\u003Ch2 id=\"какую-задачу-решают-локаторы\" class=\"wiki-heading\">Какую задачу решают локаторы\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"какую-задачу-решают-локаторы\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Тест должен обращаться к элементам страницы, а страница меняется. Разработчики переименовывают CSS-классы, оборачивают элементы в новые контейнеры, переносят блоки, меняют тексты. Тест должен падать, когда ломается поведение продукта, и проходить, когда меняется только разметка вокруг этого поведения.\u003C/p>\n\u003Cp>Каждый вид локатора привязывает тест к своему свойству элемента. Длинная цепочка CSS привязывает его к структуре документа. Документация Playwright приводит такую цепочку как пример плохой практики, которая ведёт к \u003Cspan class=\"wiki-term\" tabindex=\"0\" data-wiki-term=\"flaky-test\">нестабильным тестам\u003C/span>:\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"typescript\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">typescript\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>page.locator('#tsf &gt; div:nth-child(2) &gt; div.A8SBwf &gt; div.RNNXgb &gt; div &gt; div.a4bIc &gt; input');\u003C/code>\u003C/pre>\u003C/div>\n\u003Cp>Любой новый \u003Ccode>div\u003C/code>-обёртка или переименованный класс ломает этот локатор, хотя само поле ввода по-прежнему на странице и работает. Выбор вида локатора определяет, какие изменения страницы ломают тест, а какие нет.\u003C/p>\n\u003Ch2 id=\"виды-локаторов\" class=\"wiki-heading\">Виды локаторов\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"виды-локаторов\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Примеры в этом разделе относятся к одной форме входа.\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"html\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">html\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>&lt;form&gt;\n  &lt;h1&gt;Sign in&lt;/h1&gt;\n  &lt;label for=&quot;email&quot;&gt;Email&lt;/label&gt;\n  &lt;input id=&quot;email&quot; type=&quot;email&quot; placeholder=&quot;name@example.com&quot;&gt;\n  &lt;label for=&quot;password&quot;&gt;Password&lt;/label&gt;\n  &lt;input id=&quot;password&quot; type=&quot;password&quot;&gt;\n  &lt;img src=&quot;/logo.svg&quot; alt=&quot;Shop logo&quot;&gt;\n  &lt;span title=&quot;Items in cart&quot; data-testid=&quot;cart-count&quot;&gt;0&lt;/span&gt;\n  &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary&quot;&gt;Sign in&lt;/button&gt;\n&lt;/form&gt;\u003C/code>\u003C/pre>\u003C/div>\n\u003Ch3 id=\"по-роли\" class=\"wiki-heading\">По роли\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-роли\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Локатор по роли\u003C/strong> находит элемент по его роли ARIA и \u003Cstrong>доступному имени\u003C/strong> (accessible name). Роль говорит, чем элемент является: \u003Ccode>button\u003C/code>, \u003Ccode>link\u003C/code>, \u003Ccode>textbox\u003C/code>, \u003Ccode>checkbox\u003C/code>, \u003Ccode>heading\u003C/code>. У элементов HTML есть неявные роли: по спецификации W3C ARIA in HTML элемент \u003Ccode>button\u003C/code> имеет роль \u003Ccode>button\u003C/code>, элемент \u003Ccode>a\u003C/code> с \u003Ccode>href\u003C/code> - роль \u003Ccode>link\u003C/code>, а \u003Ccode>h1\u003C/code>-\u003Ccode>h6\u003C/code> - роль \u003Ccode>heading\u003C/code>. WAI-ARIA определяет доступное имя как имя элемента пользовательского интерфейса; оно может браться из видимого текста, подписи или атрибута, например \u003Ccode>aria-label\u003C/code>.\u003C/p>\n\u003Cp>В Playwright \u003Ccode>page.getByRole('button', { name: 'Sign in' })\u003C/code> находит кнопку формы. По умолчанию \u003Ccode>name\u003C/code> сравнивается как подстрока без учёта регистра; параметр \u003Ccode>exact: true\u003C/code> требует совпадения всей строки с учётом регистра. Другие параметры фильтруют по состоянию и уровню: \u003Ccode>checked\u003C/code>, \u003Ccode>disabled\u003C/code>, \u003Ccode>expanded\u003C/code>, \u003Ccode>pressed\u003C/code>, \u003Ccode>selected\u003C/code>, \u003Ccode>level\u003C/code>. Документация Playwright отмечает, что локаторы по роли следуют спецификациям W3C для ролей, атрибутов ARIA и доступных имён, но не заменяют аудит доступности.\u003C/p>\n\u003Ch3 id=\"по-подписи\" class=\"wiki-heading\">По подписи\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-подписи\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Локатор по подписи\u003C/strong> находит поле формы по тексту его подписи (label). \u003Ccode>page.getByLabel('Email')\u003C/code> в Playwright сравнивает текст связанного элемента \u003Ccode>label\u003C/code> или элемента, на который ссылается \u003Ccode>aria-labelledby\u003C/code>, либо значение \u003Ccode>aria-label\u003C/code>. В Testing Library аналог называется \u003Ccode>getByLabelText\u003C/code>; его рекомендуют для полей форм, потому что пользователи находят поля по подписям.\u003C/p>\n\u003Ch3 id=\"по-плейсхолдеру\" class=\"wiki-heading\">По плейсхолдеру\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-плейсхолдеру\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Локатор по плейсхолдеру\u003C/strong> находит поле ввода по атрибуту \u003Ccode>placeholder\u003C/code>: \u003Ccode>page.getByPlaceholder('name@example.com')\u003C/code>. Testing Library считает его запасным вариантом, потому что плейсхолдер не заменяет подпись.\u003C/p>\n\u003Ch3 id=\"по-тексту\" class=\"wiki-heading\">По тексту\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-тексту\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Локатор по тексту\u003C/strong> находит элемент по его текстовому содержимому: \u003Ccode>page.getByText('Sign in')\u003C/code>. При сравнении текста Playwright нормализует пробелы, даже при точном совпадении, и принимает подстроку, целую строку или регулярное выражение. Документация рекомендует локаторы по тексту для неинтерактивных элементов, таких как \u003Ccode>div\u003C/code>, \u003Ccode>span\u003C/code> и \u003Ccode>p\u003C/code>, а для интерактивных, таких как \u003Ccode>button\u003C/code>, \u003Ccode>a\u003C/code> и \u003Ccode>input\u003C/code>, - локаторы по роли. В форме выше \u003Ccode>getByText('Sign in')\u003C/code> совпадает и с заголовком, и с кнопкой. Локаторы Playwright строгие: действие над локатором, который совпадает больше чем с одним элементом, вызывает исключение. Локатор по роли разделяет их: \u003Ccode>getByRole('heading', { name: 'Sign in' })\u003C/code> и \u003Ccode>getByRole('button', { name: 'Sign in' })\u003C/code>.\u003C/p>\n\u003Ch3 id=\"по-альтернативному-тексту-и-title\" class=\"wiki-heading\">По альтернативному тексту и title\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-альтернативному-тексту-и-title\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Локатор по альтернативному тексту\u003C/strong> (alt text) находит элемент, обычно изображение, по его текстовой альтернативе: \u003Ccode>page.getByAltText('Shop logo')\u003C/code>. \u003Cstrong>Локатор по title\u003C/strong> находит элемент по атрибуту \u003Ccode>title\u003C/code>: \u003Ccode>page.getByTitle('Items in cart')\u003C/code>. Testing Library предупреждает, что программы чтения с экрана читают \u003Ccode>title\u003C/code> непоследовательно и по умолчанию он не виден.\u003C/p>\n\u003Ch3 id=\"по-test-id\" class=\"wiki-heading\">По test id\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"по-test-id\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>\u003Cstrong>Test id\u003C/strong> - атрибут, который добавляют в разметку только для того, чтобы тесты могли найти элемент. \u003Ccode>page.getByTestId('cart-count')\u003C/code> в Playwright по умолчанию ищет атрибут \u003Ccode>data-testid\u003C/code>. Другое имя атрибута задаётся параметром \u003Ccode>testIdAttribute\u003C/code> в конфигурации тестов или вызовом \u003Ccode>selectors.setTestIdAttribute()\u003C/code>.\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"typescript\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">typescript\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>import { defineConfig } from '@playwright/test';\n\nexport default defineConfig({\n  use: {\n    testIdAttribute: 'data-pw',\n  },\n});\u003C/code>\u003C/pre>\u003C/div>\n\u003Cp>Документация Playwright называет тестирование по test id самым устойчивым способом: test id переживает изменения текста и роли. Она же отмечает, что test id не виден пользователю: тест, который находит элемент по test id, не проверяет то, что видит пользователь.\u003C/p>\n\u003Ch3 id=\"css-селекторы\" class=\"wiki-heading\">CSS-селекторы\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"css-селекторы\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>CSS-селектор находит элементы по тегу, id, классам, атрибутам и положению в документе: \u003Ccode>button.btn-primary\u003C/code>, \u003Ccode>#email\u003C/code>, \u003Ccode>form &gt; button\u003C/code>. В Playwright CSS передаётся в \u003Ccode>page.locator()\u003C/code> с префиксом \u003Ccode>css=\u003C/code> или без него. CSS-селектором можно выразить всё, что другие виды выражают через атрибуты, например \u003Ccode>[data-testid='cart-count']\u003C/code> или \u003Ccode>[placeholder='name@example.com']\u003C/code>. Устойчивость зависит от того, на что он ссылается: id или атрибут test id стабильны, классы и положение - нет.\u003C/p>\n\u003Ch3 id=\"xpath\" class=\"wiki-heading\">XPath\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"xpath\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h3>\n\u003Cp>XPath - язык выбора частей XML-документа; его версия 1.0 - рекомендация W3C от 16 ноября 1999 года. Выражение XPath выбирает по структуре, атрибутам и тексту: \u003Ccode>//button[normalize-space()='Sign in']\u003C/code>, \u003Ccode>//form/input[2]\u003C/code>. XPath умеет переходить от элемента к родителю и соседям. В Playwright XPath передаётся в \u003Ccode>page.locator()\u003C/code> с префиксом \u003Ccode>xpath=\u003C/code> или начинаясь с \u003Ccode>//\u003C/code>. Документация Playwright отмечает, что XPath не проникает в теневые корни (shadow roots).\u003C/p>\n\u003Ch2 id=\"локаторы-в-webdriver-и-selenium\" class=\"wiki-heading\">Локаторы в WebDriver и Selenium\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"локаторы-в-webdriver-и-selenium\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Спецификация W3C WebDriver определяет пять стратегий поиска. Клиент передаёт стратегию и значение команде Find Element, \u003Ccode>POST /session/{session id}/element\u003C/code>.\u003C/p>\n\u003Cdiv class=\"wiki-table wiki-table--cols-2\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Ключевое слово\u003C/th>\n\u003Cth>Что находит\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>\u003Ccode>css selector\u003C/code>\u003C/td>\n\u003Ctd>Элементы, подходящие под CSS-селектор\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>link text\u003C/code>\u003C/td>\n\u003Ctd>Ссылки, видимый текст которых равен значению\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>partial link text\u003C/code>\u003C/td>\n\u003Ctd>Ссылки, видимый текст которых содержит значение\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>tag name\u003C/code>\u003C/td>\n\u003Ctd>Элементы с заданным именем тега\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>\u003Ccode>xpath\u003C/code>\u003C/td>\n\u003Ctd>Элементы, выбранные выражением XPath\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Cp>Selenium поддерживает восемь традиционных стратегий: пять перечисленных и \u003Ccode>id\u003C/code>, \u003Ccode>name\u003C/code>, \u003Ccode>class name\u003C/code>. В привязке для Python это константы класса \u003Ccode>By\u003C/code>, и их строковые значения совпадают с ключевыми словами: \u003Ccode>By.CSS_SELECTOR\u003C/code> - это \u003Ccode>&quot;css selector&quot;\u003C/code>, \u003Ccode>By.ID\u003C/code> - \u003Ccode>&quot;id&quot;\u003C/code>. Стратегия \u003Ccode>class name\u003C/code> не принимает составные имена классов.\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"python\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">python\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>from selenium import webdriver\nfrom selenium.webdriver.common.by import By\n\ndriver = webdriver.Chrome()\ndriver.get(&quot;https://shop.example.com/login&quot;)\n\ndriver.find_element(By.ID, &quot;email&quot;).send_keys(&quot;user@example.com&quot;)\ndriver.find_element(By.CSS_SELECTOR, &quot;input[type='password']&quot;).send_keys(&quot;secret&quot;)\ndriver.find_element(By.XPATH, &quot;//button[normalize-space()='Sign in']&quot;).click()\u003C/code>\u003C/pre>\u003C/div>\n\u003Cp>Ни одна из восьми стратегий не ищет элемент по роли ARIA и доступному имени, поэтому в Selenium похожий на роль локатор выражается через CSS или XPath. Документация Selenium о рекомендуемых практиках даёт свой порядок: предпочтителен id, если он есть, уникален и предсказуем; иначе - хорошо написанный CSS-селектор; XPath работает не хуже CSS, но его синтаксис сложен и часто труден для отладки. Локатор по имени тега она называет опасным, потому что на странице обычно много элементов с одним тегом, и отмечает, что стратегии по тексту ссылки работают только со ссылками.\u003C/p>\n\u003Ch2 id=\"локаторы-в-playwright-и-testing-library\" class=\"wiki-heading\">Локаторы в Playwright и Testing Library\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"локаторы-в-playwright-и-testing-library\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Playwright перечисляет рекомендуемые встроенные локаторы в таком порядке: \u003Ccode>getByRole\u003C/code>, \u003Ccode>getByText\u003C/code>, \u003Ccode>getByLabel\u003C/code>, \u003Ccode>getByPlaceholder\u003C/code>, \u003Ccode>getByAltText\u003C/code>, \u003Ccode>getByTitle\u003C/code>, \u003Ccode>getByTestId\u003C/code>. Его лучшие практики советуют отдавать приоритет атрибутам, которые видит пользователь, и явным контрактам, а CSS и XPath не рекомендуют, потому что DOM часто меняется. Тест формы входа использует только рекомендуемые локаторы:\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"typescript\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">typescript\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>import { test, expect } from '@playwright/test';\n\ntest('user signs in', async ({ page }) =&gt; {\n  await page.goto('https://shop.example.com/login');\n\n  await page.getByLabel('Email').fill('user@example.com');\n  await page.getByLabel('Password').fill('secret');\n  await page.getByRole('button', { name: 'Sign in' }).click();\n\n  await expect(page.getByRole('heading', { name: 'My orders' })).toBeVisible();\n  await expect(page.getByTestId('cart-count')).toHaveText('0');\n});\u003C/code>\u003C/pre>\u003C/div>\n\u003Cp>Локаторы можно соединять в цепочки и фильтровать, чтобы сузить поиск до части страницы. \u003Ccode>page.getByRole('listitem').filter({ hasText: 'Product 2' })\u003C/code> выбирает элемент списка, который содержит текст, а следующий \u003Ccode>getByRole('button', { name: 'Add to cart' })\u003C/code> выбирает кнопку внутри него.\u003C/p>\n\u003Cp>Testing Library следует руководящему принципу: «The more your tests resemble the way your software is used, the more confidence they can give you.» - чем больше тесты похожи на то, как пользуются программой, тем больше уверенности они дают. Её документация делит запросы на три группы по приоритету. Таблица сравнивает два порядка.\u003C/p>\n\u003Cdiv class=\"wiki-table wiki-table--cols-3\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Приоритет\u003C/th>\n\u003Cth>Testing Library\u003C/th>\n\u003Cth>Playwright\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>1\u003C/td>\n\u003Ctd>Доступные всем: \u003Ccode>getByRole\u003C/code>, \u003Ccode>getByLabelText\u003C/code>, \u003Ccode>getByPlaceholderText\u003C/code>, \u003Ccode>getByText\u003C/code>, \u003Ccode>getByDisplayValue\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>getByRole\u003C/code>, \u003Ccode>getByText\u003C/code>, \u003Ccode>getByLabel\u003C/code>, \u003Ccode>getByPlaceholder\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>2\u003C/td>\n\u003Ctd>Семантические: \u003Ccode>getByAltText\u003C/code>, \u003Ccode>getByTitle\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>getByAltText\u003C/code>, \u003Ccode>getByTitle\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>3\u003C/td>\n\u003Ctd>Test id: \u003Ccode>getByTestId\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>getByTestId\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Не в списке\u003C/td>\n\u003Ctd>CSS и XPath\u003C/td>\n\u003Ctd>CSS и XPath, не рекомендуются\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Cp>Оба порядка ставят роль первой, а test id последним среди собственных методов. Различие - внутри первой группы: Testing Library ставит подпись перед текстом, Playwright - текст перед подписью.\u003C/p>\n\u003Ch2 id=\"устойчивость-к-изменениям\" class=\"wiki-heading\">Устойчивость к изменениям\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"устойчивость-к-изменениям\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Виды локаторов различаются тем, какие изменения их ломают. Таблица сравнивает их по трём свойствам: устойчивость к изменениям разметки, читаемость теста и зависимость от текстов интерфейса.\u003C/p>\n\u003Cdiv class=\"wiki-table wiki-table--cols-4\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Вид локатора\u003C/th>\n\u003Cth>Устойчивость к изменениям разметки\u003C/th>\n\u003Cth>Читаемость\u003C/th>\n\u003Cth>Зависит от текстов\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Роль и доступное имя\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Да, через имя\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Подпись\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Да\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Плейсхолдер\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Да\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Текст\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Да\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Альтернативный текст, title\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Да\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Test id\u003C/td>\n\u003Ctd>Высокая\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Нет\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Id\u003C/td>\n\u003Ctd>Высокая, если id стабилен\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Нет\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>CSS по классам и структуре\u003C/td>\n\u003Ctd>Низкая\u003C/td>\n\u003Ctd>Низкая\u003C/td>\n\u003Ctd>Нет\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>XPath по структуре\u003C/td>\n\u003Ctd>Низкая\u003C/td>\n\u003Ctd>Низкая\u003C/td>\n\u003Ctd>Нет\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>XPath или CSS по тексту или атрибуту\u003C/td>\n\u003Ctd>Средняя\u003C/td>\n\u003Ctd>Низкая\u003C/td>\n\u003Ctd>Зависит от атрибута\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Cp>Оценка следует из того, на что ссылается каждый локатор. Роль и доступное имя меняются, только когда элемент становится другим элементом управления или получает другое имя, - такое изменение замечает и пользователь. Test id меняется, только если его кто-то правит, но пользователю он не виден, поэтому тест, который на него опирается, не заметит, что кнопка потеряла подпись. Классы и положение меняются при рефакторинге и правке стилей без всякого изменения поведения.\u003C/p>\n\u003Cp>Локатор, который зависит от текстов, ломается при правке текста. Это желательно, когда текст - часть того, что проверяет тест, и нежелательно, когда текст - только способ найти элемент. Id, которые генерируются во время работы, например из счётчика, делают локаторы по id неустойчивыми: значение может отличаться между загрузками страницы.\u003C/p>\n\u003Ch2 id=\"как-выбрать-локатор\" class=\"wiki-heading\">Как выбрать локатор\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"как-выбрать-локатор\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Рекомендации Playwright, Testing Library и Selenium сводятся к общему порядку предпочтения:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Роль и доступное имя\u003C/strong> - для интерактивных элементов: кнопок, ссылок, полей, флажков.\u003C/li>\n\u003Cli>\u003Cstrong>Подпись\u003C/strong> - для полей форм; \u003Cstrong>текст\u003C/strong> - для неинтерактивных элементов.\u003C/li>\n\u003Cli>\u003Cstrong>Плейсхолдер, альтернативный текст, title\u003C/strong> - когда у элемента нет роли, подписи или текста.\u003C/li>\n\u003Cli>\u003Cstrong>Test id\u003C/strong> - когда видимых пользователю атрибутов нет, они неоднозначны или меняются по причинам, не связанным с тестом.\u003C/li>\n\u003Cli>\u003Cstrong>CSS или XPath\u003C/strong> - когда ничего другого не подходит, например в сторонней разметке, которую нельзя изменить; лучше по стабильным атрибутам, чем по структуре.\u003C/li>\n\u003C/ol>\n\u003Cp>Локатор, который совпадает с несколькими элементами, сужают цепочкой от уникального контейнера, а не по положению. Если локатор по роли написать нельзя, это сигнал о самой странице: элементом без доступного имени трудно пользоваться и с программой чтения с экрана. Генератор кода Playwright, \u003Ccode>npx playwright codegen\u003C/code>, выбирает локаторы по тому же приоритету: роль, текст и test id.\u003C/p>\n\u003Ch2 id=\"ожидание-элементов\" class=\"wiki-heading\">Ожидание элементов\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"ожидание-элементов\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Локатор описывает элемент, которого может ещё не быть. После нажатия страница отправляет запрос, получает ответ и отрисовывает новое содержимое, и тест должен этого дождаться. Способ ожидания - одна из причин тестов, которые падают без \u003Cspan class=\"wiki-term\" tabindex=\"0\" data-wiki-term=\"defect\">дефекта\u003C/span>; такие тесты описаны в статье \u003Ca href=\"/ru/wiki/test-automation/flaky-tests\" class=\"wiki-link wiki-link--article\">Нестабильные (flaky) тесты\u003C/a>.\u003C/p>\n\u003Cp>\u003Cstrong>Автоожидание\u003C/strong> (auto-waiting) в Playwright означает, что перед каждым действием инструмент ждёт, пока элемент пройдёт проверки готовности к действию (actionability checks). Для \u003Ccode>click\u003C/code> это проверки: элемент видим, стабилен, получает события и включён; для \u003Ccode>fill\u003C/code> - видим, включён и редактируем. Если проверки не проходят за время тайм-аута, действие завершается ошибкой \u003Ccode>TimeoutError\u003C/code>. Локатор Playwright разрешается в элемент при каждом использовании. Проверки вида \u003Ccode>expect(locator).toBeVisible()\u003C/code> ждут выполнения условия, а \u003Ccode>locator.isVisible()\u003C/code> возвращает результат сразу.\u003C/p>\n\u003Cp>В Selenium два механизма. \u003Cstrong>Неявное ожидание\u003C/strong> (implicit wait) - глобальная настройка на всю сессию: каждый поиск элемента повторяется до тайм-аута; значение по умолчанию 0, поэтому отсутствующий элемент сразу вызывает ошибку. \u003Cstrong>Явное ожидание\u003C/strong> (explicit wait) - цикл в коде теста, который опрашивает конкретное условие, пока оно не станет истинным или не истечёт тайм-аут. Документация Selenium предупреждает, что смешивать их нельзя: время ожидания становится непредсказуемым.\u003C/p>\n\u003Cdiv class=\"wiki-code\" data-language=\"python\">\u003Cdiv class=\"wiki-code__header\">\u003Cspan class=\"wiki-code__language\">python\u003C/span>\u003Cbutton type=\"button\" class=\"wiki-code__copy\" data-wiki-copy data-copied-label=\"Скопировано\">\u003Csvg class=\"wiki-code__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\"/>\u003C/svg>\u003Csvg class=\"wiki-code__icon wiki-code__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003Cspan class=\"wiki-code__label\">Копировать\u003C/span>\u003Cspan class=\"wiki-code__label wiki-code__label--done\">Скопировано\u003C/span>\u003C/button>\u003C/div>\u003Cpre>\u003Ccode>from selenium.webdriver.common.by import By\nfrom selenium.webdriver.support.wait import WebDriverWait\n\nwait = WebDriverWait(driver, timeout=5)\nheading = wait.until(\n    lambda d: d.find_element(By.XPATH, &quot;//h1[normalize-space()='My orders']&quot;)\n)\nassert heading.is_displayed()\u003C/code>\u003C/pre>\u003C/div>\n\u003Cp>\u003Ccode>WebDriverWait.until\u003C/code> вызывает функцию, пока она не вернёт истинное значение, и выбрасывает \u003Ccode>TimeoutException\u003C/code>, когда истекает тайм-аут; по умолчанию между попытками он игнорирует \u003Ccode>NoSuchElementException\u003C/code>. \u003Ccode>WebElement\u003C/code>, найденный Selenium, ссылается на один конкретный элемент: если страница перерисует его, ссылка устаревает, и элемент нужно найти заново. В Testing Library похожее разделение: запросы \u003Ccode>getBy\u003C/code> возвращают результат сразу, запросы \u003Ccode>findBy\u003C/code> возвращают промис и повторяют поиск до тайм-аута по умолчанию 1000 мс.\u003C/p>\n\u003Ch2 id=\"локаторы-и-локализация\" class=\"wiki-heading\">Локаторы и локализация\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"локаторы-и-локализация\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Локаторы по роли, подписи, плейсхолдеру, тексту, альтернативному тексту и title зависят от текстов интерфейса, а тексты в разных языках разные. Тест с \u003Ccode>getByRole('button', { name: 'Sign in' })\u003C/code> упадёт на немецкой версии страницы, где у кнопки другое имя. Собственный пример Playwright для test id показывает этот случай: кнопка с текстом \u003Ccode>Itinéraire\u003C/code> и атрибутом \u003Ccode>data-testid=&quot;directions&quot;\u003C/code>, которую \u003Ccode>getByTestId('directions')\u003C/code> находит независимо от языка.\u003C/p>\n\u003Cp>У набора, который выполняется на нескольких локалях, есть несколько вариантов:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>одна локаль для большинства тестов\u003C/strong>: Playwright задаёт локаль браузера параметром \u003Ccode>locale\u003C/code> в конфигурации, например \u003Ccode>locale: 'en-GB'\u003C/code>;\u003C/li>\n\u003Cli>\u003Cstrong>тексты из ресурсов перевода\u003C/strong>: тест берёт ожидаемое имя из тех же файлов перевода, что и приложение, и локатор следует за переводом;\u003C/li>\n\u003Cli>\u003Cstrong>test id для элементов, текст которых меняется\u003C/strong>: локатор не зависит от языка, а тексты проверяет отдельная проверка;\u003C/li>\n\u003Cli>\u003Cstrong>регулярные выражения\u003C/strong> в \u003Ccode>name\u003C/code> или \u003Ccode>getByText\u003C/code>, когда вариантов немного и они известны.\u003C/li>\n\u003C/ul>\n\u003Cp>Выбор зависит и от того, что проверяет тест. Тест самого перевода должен опираться на тексты; тест бизнес-сценария - не обязан.\u003C/p>\n\u003Ch2 id=\"локаторы-в-репозитории-объектов\" class=\"wiki-heading\">Локаторы в репозитории объектов\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"локаторы-в-репозитории-объектов\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Когда один элемент используется во многих тестах, его локатор записывают один раз и обращаются к нему по имени. Изменение разметки тогда исправляется в одном месте, а не в каждом тесте. Два способа так организовать локаторы - \u003Cspan class=\"wiki-term\" tabindex=\"0\" data-wiki-term=\"page-object\">объекты страниц\u003C/span> (page objects) и \u003Cspan class=\"wiki-term\" tabindex=\"0\" data-wiki-term=\"object-repository\">репозиторий объектов\u003C/span> со структурой «страницы - элементы» - описаны в статье \u003Ca href=\"/ru/wiki/test-automation/page-object-and-object-repository\" class=\"wiki-link wiki-link--article\">Репозиторий объектов и Page Object\u003C/a>. Каким уровням тестов локаторы нужны вообще, объясняет статья \u003Ca href=\"/ru/wiki/test-automation/automation-levels-and-test-pyramid\" class=\"wiki-link wiki-link--article\">Уровни автоматизации и пирамида тестов\u003C/a>.\u003C/p>\n\u003Ch2 id=\"локатор-селектор-и-ссылка-на-элемент\" class=\"wiki-heading\">Локатор, селектор и ссылка на элемент\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"локатор-селектор-и-ссылка-на-элемент\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cp>Три слова обозначают связанные, но разные вещи.\u003C/p>\n\u003Cdiv class=\"wiki-table wiki-table--cols-4\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>\u003C/th>\n\u003Cth>Селектор\u003C/th>\n\u003Cth>Локатор\u003C/th>\n\u003Cth>Ссылка на элемент\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Что это\u003C/td>\n\u003Ctd>Строка в синтаксисе CSS или XPath\u003C/td>\n\u003Ctd>Стратегия и значение для поиска элемента\u003C/td>\n\u003Ctd>Ссылка на один найденный элемент\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Пример\u003C/td>\n\u003Ctd>\u003Ccode>button.btn-primary\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>getByRole('button', { name: 'Sign in' })\u003C/code>\u003C/td>\n\u003Ctd>\u003Ccode>WebElement\u003C/code> в Selenium, \u003Ccode>ElementHandle\u003C/code> в Playwright\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Когда разрешается\u003C/td>\n\u003Ctd>При использовании\u003C/td>\n\u003Ctd>При каждом использовании (Playwright)\u003C/td>\n\u003Ctd>Один раз, при поиске\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>После перерисовки\u003C/td>\n\u003Ctd>Не применимо\u003C/td>\n\u003Ctd>Находит новый элемент\u003C/td>\n\u003Ctd>Устаревает\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Cp>Селектор - одно из возможных значений локатора: CSS- или XPath-локатор содержит селектор, локатор по роли - нет. Документация Playwright прямо формулирует разницу между двумя последними: \u003Ccode>ElementHandle\u003C/code> указывает на конкретный элемент, а \u003Ccode>Locator\u003C/code> содержит логику того, как элемент получить. Использовать \u003Ccode>ElementHandle\u003C/code> она не рекомендует и предлагает вместо него локаторы и веб-ориентированные проверки (web-first assertions).\u003C/p>\n\u003Ch2 id=\"термины\" class=\"wiki-heading\">Термины\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"термины\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cdiv class=\"wiki-table wiki-table--cols-2\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Термин\u003C/th>\n\u003Cth>Значение\u003C/th>\n\u003C/tr>\n\u003C/thead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Локатор (locator)\u003C/td>\n\u003Ctd>Описание того, как UI-автотест находит элемент: стратегия и значение\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Стратегия поиска (location strategy)\u003C/td>\n\u003Ctd>Способ найти элемент: по роли, подписи, тексту, test id, CSS, XPath и другие\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Доступное имя (accessible name)\u003C/td>\n\u003Ctd>Имя элемента пользовательского интерфейса, которое получают вспомогательные технологии\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Test id\u003C/td>\n\u003Ctd>Атрибут, который добавляют в разметку только для того, чтобы тесты могли найти элемент, по умолчанию \u003Ccode>data-testid\u003C/code>\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Автоожидание (auto-waiting)\u003C/td>\n\u003Ctd>Ожидание инструментом перед каждым действием, пока элемент не пройдёт проверки готовности к действию\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Неявное ожидание (implicit wait)\u003C/td>\n\u003Ctd>Глобальная настройка сессии, при которой каждый поиск элемента повторяется до тайм-аута\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Явное ожидание (explicit wait)\u003C/td>\n\u003Ctd>Цикл в коде теста, который опрашивает конкретное условие, пока оно не станет истинным или не истечёт тайм-аут\u003C/td>\n\u003C/tr>\n\u003Ctr>\n\u003Ctd>Устаревшая ссылка на элемент (stale element reference)\u003C/td>\n\u003Ctd>Ссылка на элемент, который был найден раньше, но больше не находится в документе\u003C/td>\n\u003C/tr>\n\u003C/tbody>\n\u003C/table>\u003C/div>\n\u003Ch2 id=\"источники\" class=\"wiki-heading\">Источники\u003Cbutton type=\"button\" class=\"wiki-heading__anchor\" data-wiki-anchor=\"источники\" aria-label=\"Скопировать ссылку на раздел\" data-copied-label=\"Ссылка на раздел скопирована\">\u003Csvg class=\"wiki-heading__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M117.18,188.74a12,12,0,0,1,0,17l-5.12,5.12A58.26,58.26,0,0,1,70.6,228h0A58.62,58.62,0,0,1,29.14,127.92L63.89,93.17a58.64,58.64,0,0,1,98.56,28.11,12,12,0,1,1-23.37,5.44,34.65,34.65,0,0,0-58.22-16.58L46.11,144.89A34.62,34.62,0,0,0,70.57,204h0a34.41,34.41,0,0,0,24.49-10.14l5.11-5.12A12,12,0,0,1,117.18,188.74ZM226.83,45.17a58.65,58.65,0,0,0-82.93,0l-5.11,5.11a12,12,0,0,0,17,17l5.12-5.12a34.63,34.63,0,1,1,49,49L175.1,145.86A34.39,34.39,0,0,1,150.61,156h0a34.63,34.63,0,0,1-33.69-26.72,12,12,0,0,0-23.38,5.44A58.64,58.64,0,0,0,150.56,180h.05a58.28,58.28,0,0,0,41.47-17.17l34.75-34.75a58.62,58.62,0,0,0,0-82.91Z\"/>\u003C/svg>\u003Csvg class=\"wiki-heading__icon wiki-heading__icon--done\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\"/>\u003C/svg>\u003C/button>\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.w3.org/TR/webdriver1/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">WebDriver, W3C Recommendation, 5 June 2018\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.w3.org/TR/webdriver2/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">WebDriver Level 2, W3C Working Draft\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.w3.org/TR/wai-aria-1.2/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Accessible Rich Internet Applications (WAI-ARIA) 1.2, W3C Recommendation, 6 June 2023\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.w3.org/TR/html-aria/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">ARIA in HTML, W3C Recommendation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.w3.org/TR/xpath-10/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">XML Path Language (XPath) Version 1.0, W3C Recommendation, 16 November 1999\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/locators\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Locators, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/best-practices\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Best Practices, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/actionability\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Auto-waiting, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/api/class-page\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Page class reference, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/api/class-elementhandle\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">ElementHandle class reference, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://playwright.dev/docs/emulation\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Emulation, Playwright documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://testing-library.com/docs/queries/about/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">About Queries, Testing Library documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://testing-library.com/docs/guiding-principles\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Guiding Principles, Testing Library documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.selenium.dev/documentation/webdriver/elements/locators/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Locator strategies, Selenium documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.selenium.dev/documentation/test_practices/encouraged/locators/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Locators, encouraged test practices, Selenium documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.selenium.dev/documentation/webdriver/waits/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Waiting strategies, Selenium documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.selenium.dev/documentation/webdriver/troubleshooting/errors/\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">Understanding common errors, Selenium documentation\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003Cli>\u003Ca href=\"https://selenium-python-api-docs.readthedocs.io/en/selenium-4.39.0/_modules/selenium/webdriver/common/by.html\" target=\"_blank\" rel=\"noopener\" class=\"wiki-link wiki-link--external\">selenium.webdriver.common.by, Selenium Python API\u003Csvg class=\"wiki-link__icon\" viewBox=\"0 0 256 256\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\u003Cpath d=\"M228,104a12,12,0,0,1-24,0V69l-59.51,59.51a12,12,0,0,1-17-17L187,52H152a12,12,0,0,1,0-24h64a12,12,0,0,1,12,12Zm-44,24a12,12,0,0,0-12,12v64H52V84h64a12,12,0,0,0,0-24H48A20,20,0,0,0,28,80V208a20,20,0,0,0,20,20H176a20,20,0,0,0,20-20V140A12,12,0,0,0,184,128Z\"/>\u003C/svg>\u003Cspan class=\"wiki-visually-hidden\">(откроется в новой вкладке)\u003C/span>\u003C/a> (на английском)\u003C/li>\n\u003C/ul>\n",[10,14,17,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69],{"id":11,"level":12,"text":13},"какую-задачу-решают-локаторы",2,"Какую задачу решают локаторы",{"id":15,"level":12,"text":16},"виды-локаторов","Виды локаторов",{"id":18,"level":19,"text":20},"по-роли",3,"По роли",{"id":22,"level":19,"text":23},"по-подписи","По подписи",{"id":25,"level":19,"text":26},"по-плейсхолдеру","По плейсхолдеру",{"id":28,"level":19,"text":29},"по-тексту","По тексту",{"id":31,"level":19,"text":32},"по-альтернативному-тексту-и-title","По альтернативному тексту и title",{"id":34,"level":19,"text":35},"по-test-id","По test id",{"id":37,"level":19,"text":38},"css-селекторы","CSS-селекторы",{"id":40,"level":19,"text":41},"xpath","XPath",{"id":43,"level":12,"text":44},"локаторы-в-webdriver-и-selenium","Локаторы в WebDriver и Selenium",{"id":46,"level":12,"text":47},"локаторы-в-playwright-и-testing-library","Локаторы в Playwright и Testing Library",{"id":49,"level":12,"text":50},"устойчивость-к-изменениям","Устойчивость к изменениям",{"id":52,"level":12,"text":53},"как-выбрать-локатор","Как выбрать локатор",{"id":55,"level":12,"text":56},"ожидание-элементов","Ожидание элементов",{"id":58,"level":12,"text":59},"локаторы-и-локализация","Локаторы и локализация",{"id":61,"level":12,"text":62},"локаторы-в-репозитории-объектов","Локаторы в репозитории объектов",{"id":64,"level":12,"text":65},"локатор-селектор-и-ссылка-на-элемент","Локатор, селектор и ссылка на элемент",{"id":67,"level":12,"text":68},"термины","Термины",{"id":70,"level":12,"text":71},"источники","Источники",2411,1793718893484]