{"id":458030,"date":"2025-04-29T09:37:58","date_gmt":"2025-04-29T09:37:58","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=458030"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=458030","title":{"rendered":"<span>UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0430 Python \u0441 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u043d\u0430 CI\/CD \u0438 Allure \u043e\u0442\u0447\u0435\u0442\u043e\u043c. PageObject, PageComponent, PageFactory<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0430 Python, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u0438 \u043b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a PageObject, PageComponent \u0438 PageFactory, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u044f, \u043a\u043e\u0433\u0434\u0430 \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0447\u0435\u043c \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430.<\/p>\n<p>\u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u044d\u0442\u0438\u043c\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438, \u0430 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u00ab\u043d\u0430 \u0430\u0442\u043e\u043c\u044b\u00bb \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u043e\u043d\u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/auth\/login\" rel=\"noopener noreferrer nofollow\"><strong>UI Course<\/strong><\/a>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043c\u043e\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 GitHub: <a href=\"https:\/\/github.com\/Nikita-Filonov\/qa-automation-engineer-ui-course\" rel=\"noopener noreferrer nofollow\">UI Course GitHub<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/CI\/CD\" rel=\"noopener noreferrer nofollow\">CI\/CD<\/a> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/features\/actions\" rel=\"noopener noreferrer nofollow\"><strong>GitHub Actions<\/strong><\/a>, \u043d\u043e \u0432\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <a href=\"https:\/\/www.jenkins.io\/\" rel=\"noopener noreferrer nofollow\">Jenkins<\/a>, <a href=\"https:\/\/docs.gitlab.com\/ci\/\" rel=\"noopener noreferrer nofollow\">GitLab CI<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/circleci.com\/\" rel=\"noopener noreferrer nofollow\">CircleCI<\/a> \u2014 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043a\u0430\u0441\u0430\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u043d\u0435 \u043d\u0430 \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b PageObject, PageComponent \u0438 PageFactory \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.<\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/auth\/registration\" rel=\"noopener noreferrer nofollow\">\/#\/auth\/registration<\/a><\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: <code>Email<\/code>, <code>Username<\/code>, <code>Password<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 <strong>&#171;Registration&#187;<\/strong> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <strong>&#171;Dashboard&#187;<\/strong>: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/dashboard\" rel=\"noopener noreferrer nofollow\">\/#\/dashboard<\/a><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0432\u0441\u0435\u0445 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <strong>&#171;Dashboard&#187;.<\/strong><\/p>\n<\/li>\n<\/ol>\n<h2>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer nofollow\"><strong>Python 3.12<\/strong><\/a>\u00a0\u2014 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\"><strong>Playwright<\/strong><\/a> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 UI.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.pytest.org\/en\/stable\/\" rel=\"noopener noreferrer nofollow\"><strong>Pytest<\/strong><\/a>\u00a0\u2014 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/python\/docs\/intro\" rel=\"noopener noreferrer nofollow\"><strong>Pytest Playwright<\/strong><\/a> \u2014 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f Playwright \u0441 pytest, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u0441 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0430\u043c\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 Playwright.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.pydantic.dev\/latest\/concepts\/pydantic_settings\/\" rel=\"noopener noreferrer nofollow\"><strong>Pydantic Settings<\/strong><\/a> \u2014 \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 <code>.env<\/code> \u0444\u0430\u0439\u043b\u044b.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/allurereport.org\/\" rel=\"noopener noreferrer nofollow\"><strong>Allure<\/strong><\/a>\u00a0\u2014 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0447\u0451\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 Playwright, \u0430 \u043d\u0435 Selenium?<\/h4>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u0431\u043e\u0440 \u043c\u0435\u0436\u0434\u0443 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0438 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u2014 \u044d\u0442\u043e \u0432\u044b\u0431\u043e\u0440 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Playwright.<\/p>\n<p><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 Playwright:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0441\u0442\u044c.<\/strong> <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/chromedevtools.github.io\/devtools-protocol\/\" rel=\"noopener noreferrer nofollow\">DevTools Protocol<\/a>, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443 <a href=\"https:\/\/www.selenium.dev\/documentation\/webdriver\/\" rel=\"noopener noreferrer nofollow\">WebDriver<\/a>. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 Playwright \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u0434\u0432\u0435\u0440\u0436\u0435\u043d\u043d\u044b\u043c \u0444\u043b\u0430\u043a\u0438-\u0442\u0435\u0441\u0442\u0430\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430.<\/strong> \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u2014 \u044d\u0442\u043e \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e <a href=\"https:\/\/playwright.dev\/python\/docs\/intro\" rel=\"noopener noreferrer nofollow\">\u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/a>: <code>pip install playwright pytest-playwright<\/code>, <code>playwright install<\/code>. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u0432\u0441\u0451 \u043a\u0443\u0434\u0430 \u0441\u043b\u043e\u0436\u043d\u0435\u0435: \u043d\u0443\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0438\u0434\u0435\u043e \u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b &#171;\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187;.<\/strong> Playwright <a href=\"https:\/\/playwright.dev\/python\/docs\/videos\" rel=\"noopener noreferrer nofollow\">\u0443\u043c\u0435\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0435\u043e<\/a> \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f.<\/strong> \u041a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 Playwright \u0443\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (waits). \u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0438 \u201c\u043a\u043e\u0441\u0442\u044b\u043b\u0438\u201d, \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u0431\u044b\u0432\u0430\u0435\u0442 \u0432 Selenium.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/docs\/trace-viewer\" rel=\"noopener noreferrer nofollow\"><strong>Playwright Trace Viewer.<\/strong><\/a> \u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u0438 CI-\u043e\u0448\u0438\u0431\u043a\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c.<\/strong> Playwright \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio.html\" rel=\"noopener noreferrer nofollow\">asyncio<\/a>), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0415\u0441\u0442\u044c \u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430, \u043d\u043e \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <\/strong><a href=\"https:\/\/webkit.org\/\" rel=\"noopener noreferrer nofollow\"><strong>WebKit<\/strong><\/a><strong>.<\/strong> \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Selenium, Playwright \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 <a href=\"https:\/\/webkit.org\/\" rel=\"noopener noreferrer nofollow\">WebKit<\/a> (\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u0430\u043d <a href=\"https:\/\/www.apple.com\/safari\/\" rel=\"noopener noreferrer nofollow\">Safari<\/a>), \u0447\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043a\u0440\u043e\u0441\u0441-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u0438 \u043c\u043e\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/strong> <a href=\"https:\/\/playwright.dev\/python\/docs\/network#mock-apis\" rel=\"noopener noreferrer nofollow\">Playwright \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u043e\u043a\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b,<\/a> \u0447\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 UI-\u0441\u043b\u043e\u044f \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u043e\u0432.<\/strong> \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c\u0438 \u0438 <a href=\"https:\/\/www.w3schools.com\/html\/html_iframe.asp\" rel=\"noopener noreferrer nofollow\">iframes<\/a> \u0432 Playwright \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u0447\u0435\u043c \u0432 Selenium.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u044b\u0439 API.<\/strong> API \u0443 Playwright \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u044b\u0439 \u2014 \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Selenium, \u0433\u0434\u0435 \u043a\u043e\u0434 \u0447\u0430\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 Selenium \u0432\u0441\u0451 \u0435\u0449\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442?<\/h4>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u0435, <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0435\u043e\u0441\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u043e\u0441\u0442\u044c. <\/strong>\u041c\u043d\u043e\u0433\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u043f\u0435\u043b\u0438 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0441\u043b\u0435\u0434\u0438\u0435.<\/strong> \u0412 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\u0445 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0441\u043e\u0442\u043d\u0438 \u0438 \u0442\u044b\u0441\u044f\u0447\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a>. \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u2014 \u0434\u043e\u0440\u043e\u0433\u043e, \u0434\u043e\u043b\u0433\u043e \u0438 \u0441\u0442\u0440\u0430\u0448\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. <\/strong>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0443\u0436\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e\u0442 \u0438\u043b\u0438 \u043d\u0430\u0447\u0430\u043b\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u043d\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0435\u0431\u044b\u0441\u0442\u0440\u044b\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u044b\u043d\u043e\u043a \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439.<\/strong> <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u0432\u0441\u0451 \u0435\u0449\u0451 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u0445, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 legacy-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u041d\u043e\u0432\u0438\u0447\u043a\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0432\u044b\u0431\u043e\u0440 \u0432 \u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u0443 \u0438\u0437-\u0437\u0430 &#171;\u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0441\u0442\u0438&#187;, \u043d\u0435 \u0437\u043d\u0430\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u043c\u0443. <\/strong>\u0415\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f &#171;\u0435\u0441\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u2014 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0439&#187;, \u0438 \u043d\u0435 \u0441\u043f\u0435\u0448\u0430\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<\/li>\n<\/ol>\n<h4>\u0412\u044b\u0432\u043e\u0434<\/h4>\n<p>Playwright \u2014 \u044d\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439, \u043c\u043e\u0449\u043d\u044b\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u044b\u0442\u0435\u0441\u043d\u044f\u0435\u0442 Selenium \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0438\u043b\u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u2014 \u0441\u043c\u0435\u043b\u043e \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0432\u044b\u0431\u043e\u0440 \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Playwright. \u0415\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u0441\u0430\u043c\u0438 \u0437\u0430 \u0441\u0435\u0431\u044f.<\/p>\n<h2>\u041f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 UI-\u0442\u0435\u0441\u0442\u043e\u0432<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438, \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442-\u043a\u0435\u0439\u0441\u044b &#171;\u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f&#187;, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u2014 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9F%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b<\/a> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430: PageObject, PageComponent \u0438 PageFactory. \u0412\u043c\u0435\u0441\u0442\u0435 \u043e\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0447\u043d\u0443\u044e, \u0433\u0438\u0431\u043a\u0443\u044e \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h3>PageObject<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/pages\" rel=\"noopener noreferrer nofollow\"><strong>PageObject<\/strong><\/a> \u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0439 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432 UI-\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0421\u0443\u0442\u044c \u0435\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (\u0438\u043b\u0438 \u044d\u043a\u0440\u0430\u043d, \u0435\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438) \u0432 \u0432\u0438\u0434\u0435 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<ul>\n<li>\n<p>\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u2014 \u044d\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u043a\u043d\u043e\u043f\u043a\u0438, \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u2014 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u0442\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 (\u043a\u043b\u0438\u043a, \u0432\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0442\u0435\u0441\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 &#171;\u0440\u0430\u0437\u043c\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f&#187; \u043f\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c \u0438 \u0441\u044b\u0440\u044b\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c, \u0430 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043a\u0430\u043a \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443:<\/p>\n<pre><code class=\"python\">registration_page.fill_email(\"test@example.com\") registration_page.submit()<\/code><\/pre>\n<p>Page Object \u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446, \u043d\u043e \u043e\u043d \u043d\u0435 \u0434\u0430\u0451\u0442 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445.<\/p>\n<h3>PageComponent<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/components\" rel=\"noopener noreferrer nofollow\"><strong>PageComponent<\/strong><\/a> \u2014 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438. \u041e\u043d \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043c\u0435\u043d\u044e (<a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Navbar<\/strong><\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c (<a href=\"https:\/\/www.w3schools.com\/w3css\/w3css_sidebar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Sidebar<\/strong><\/a>)<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043a\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0431\u043b\u043e\u043a\u0438 \u0438 \u0441\u0435\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 PageObject, \u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0438: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 <a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Navbar<\/strong><\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443, \u0445\u043e\u0442\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0443 \u043d\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435.<\/p>\n<p><strong>PageComponent<\/strong> \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0444\u043e\u0440\u043c\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u044d\u0442\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u044c PageObject&#8217;\u043e\u0432 \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Composition_over_inheritance\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">class DashboardPage:     def __init__(self, page):         self.navbar = NavbarComponent(page)         self.sidebar = SidebarComponent(page)<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043b\u043e\u0433\u0438\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0438 \u043c\u043e\u0436\u043d\u043e \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435.<\/p>\n<h3>PageFactory<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/elements\" rel=\"noopener noreferrer nofollow\"><strong>PageFactory<\/strong><\/a> \u2014 \u043c\u0435\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 Python-\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435. \u0427\u0430\u0449\u0435 \u043e\u043d \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 Java-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u043d\u043e \u0441 \u043b\u0451\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043f\u043e\u0434 Python.<\/p>\n<p>\u0415\u0441\u043b\u0438 PageObject \u2014 \u043f\u0440\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, PageComponent \u2014 \u043f\u0440\u043e <strong>\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/strong>, \u0442\u043e PageFactory \u2014 \u043f\u0440\u043e \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0421\u0443\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u2014 \u0431\u0443\u0434\u044c \u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430, \u0438\u043d\u043f\u0443\u0442, \u0438\u043a\u043e\u043d\u043a\u0430, \u0442\u0435\u043a\u0441\u0442, \u0447\u0435\u043a\u0431\u043e\u043a\u0441 \u2014 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0441 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c.<\/p>\n<pre><code class=\"python\">class Input:     def __init__(self, locator):         self.locator = locator      def fill(self, text): ...     def clear(self): ...     def is_disabled(self): ...<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0438\u043d\u043f\u0443\u0442 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u2014 \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043c\u0435\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c DOM.<\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0443\u0431\u0440\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430, \u043e\u0447\u0438\u0441\u0442\u043a\u0443, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e),<\/p>\n<\/li>\n<li>\n<p>\u0438, \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043b\u044e\u0431\u044b\u0445 PageObject \u0438\u043b\u0438 PageComponent.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u043e?<\/h3>\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 \u0442\u0440\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043c\u043d\u043e\u0433\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u0443\u044e \u043a \u043b\u044e\u0431\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u043c:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">\u0423\u0440\u043e\u0432\u0435\u043d\u044c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Object<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438\u043b\u0438 \u044d\u043a\u0440\u0430\u043d<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Component<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u044b<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Factory<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438: \u0438\u043d\u043f\u0443\u0442\u0430\u043c\u0438, \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438, \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430:<\/p>\n<ul>\n<li>\n<p>\u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u043a\u0430\u043a \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435),<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0447\u0435\u0440\u0435\u0437 Appium, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440),<\/p>\n<\/li>\n<li>\n<p>\u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b.<\/p>\n<\/li>\n<\/ul>\n<h2>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e PageObject, PageComponent \u0438 PageFactory, \u0432\u0430\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c <strong>\u0435\u0434\u0438\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/strong>. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u0439,<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 CI\/CD,<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <a href=\"https:\/\/docs.python.org\/3\/library\/logging.html\" rel=\"noopener noreferrer nofollow\">\u043b\u043e\u0433\u0433\u0435\u0440<\/a>&#8212;<a href=\"https:\/\/refactoring.guru\/design-patterns\/builder\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043b\u0434\u0435\u0440<\/a> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0442\u0435\u0441\u0442\u0430: \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/tools\/logger.py\" rel=\"noopener noreferrer nofollow\"><strong>\/tools\/logger.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import logging   def get_logger(name: str) -&gt; logging.Logger:     \"\"\"     \u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043b\u043e\u0433\u0433\u0435\u0440 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c.      \u041b\u043e\u0433\u0433\u0435\u0440:     - \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DEBUG     - \u0412\u044b\u0432\u043e\u0434\u0438\u0442 \u043b\u043e\u0433\u0438 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c (stdout)     - \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442: \"\u0434\u0430\u0442\u0430 | \u0438\u043c\u044f \u043b\u043e\u0433\u0433\u0435\u0440\u0430 | \u0443\u0440\u043e\u0432\u0435\u043d\u044c | \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"      :param name: \u0418\u043c\u044f \u043b\u043e\u0433\u0433\u0435\u0440\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441\u0430)     :return: \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 logging.Logger     \"\"\"     logger = logging.getLogger(name)  # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043b\u043e\u0433\u0433\u0435\u0440 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c     logger.setLevel(logging.DEBUG)  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DEBUG      handler = logging.StreamHandler()  # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0448\u0435\u0442 \u0432 stdout     handler.setLevel(logging.DEBUG)  # \u0422\u043e\u0436\u0435 \u0443\u0440\u043e\u0432\u0435\u043d\u044c DEBUG      formatter = logging.Formatter(         '%(asctime)s | %(name)s | %(levelname)s | %(message)s'     )  # \u0424\u043e\u0440\u043c\u0430\u0442 \u043b\u043e\u0433\u043e\u0432: \u0432\u0440\u0435\u043c\u044f | \u0438\u043c\u044f \u043b\u043e\u0433\u0433\u0435\u0440\u0430 | \u0443\u0440\u043e\u0432\u0435\u043d\u044c | \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435      handler.setFormatter(formatter)  # \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443     logger.addHandler(handler)  # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a \u043b\u043e\u0433\u0433\u0435\u0440\u0443      return logger  # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043b\u043e\u0433\u0433\u0435\u0440 <\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u0435 \u043c\u043e\u0436\u0435\u0448\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043b\u043e\u0433\u0433\u0435\u0440 \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">from tools.logger import get_logger  logger = get_logger(\"NAME_OF_MY_LOGGER\")<\/code><\/pre>\n<p>\u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<pre><code class=\"python\">logger.info(\"\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438\") logger.debug(\"\u0412\u0432\u043e\u0434\u0438\u043c email test@example.com\") logger.error(\"\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u043a\u043d\u043e\u043f\u043a\u0443 'Submit'\")<\/code><\/pre>\n<h2>PageFactory<\/h2>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d PageFactory \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u043d\u0438\u0436\u043d\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b (\u043f\u043e\u0441\u043b\u0435 PageObject \u0438 PageComponent), \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u043d\u0435\u0433\u043e. \u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0430 \u2014 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u043a\u043d\u043e\u043f\u043e\u043a, \u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u0438 \u0442.\u0434.), \u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0436\u0435 \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/p>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b:<\/h4>\n<ul>\n<li>\n<p><code>Button<\/code> \u2014 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u043d\u043e\u043f\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>Input<\/code> \u2014 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p><code>Text<\/code> \u2014 \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/p>\n<\/li>\n<li>\n<p><code>Image<\/code> \u2014 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p><code>Link<\/code> \u2014 \u0441\u0441\u044b\u043b\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<h3>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 BaseElement<\/h3>\n<p>\u0412\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 (\u0431\u0443\u0434\u044c \u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430, \u0442\u0435\u043a\u0441\u0442 \u0438\u043b\u0438 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430) \u0438\u043c\u0435\u044e\u0442 \u043e\u0431\u0449\u0443\u044e \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c: \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043b\u0438\u043a, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0434\u0440\u0443\u0433\u043e\u0435. \u0412\u044b\u043d\u0435\u0441\u0435\u043c \u044d\u0442\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code>BaseElement<\/code>, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/base_element.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/base_element.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import Page, Locator, expect  from tools.logger import get_logger  logger = get_logger(\"BASE_ELEMENT\")   class BaseElement:     \"\"\"     \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.      \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043b\u044e\u0431\u044b\u043c UI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c,     \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043a\u043b\u0438\u043a, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430.     \"\"\"     def __init__(self, page: Page, locator: str, name: str) -&gt; None:         \"\"\"         :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright         :param locator: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 data-testid \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 (\u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b)         :param name: \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 (\u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0430\u043b\u043b\u044e\u0440\u0430)         \"\"\"         self.page = page         self.name = name         self.locator = locator      @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043c\u043a\u0430\u0445.         \"\"\"         return \"base element\"      def get_locator(self, nth: int = 0, **kwargs) -&gt; Locator:         \"\"\"         \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043f\u043e data-testid \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432.          :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445         :param kwargs: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430         :return: \u041b\u043e\u043a\u0430\u0442\u043e\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         \"\"\"         locator = self.locator.format(**kwargs)         step = f'Getting locator with \"data-testid={locator}\" at index \"{nth}\"'          with allure.step(step):             logger.info(step)             return self.page.get_by_test_id(locator).nth(nth)      def click(self, nth: int = 0, **kwargs):         \"\"\"         \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043b\u0438\u043a \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443.          :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e 0)         :param kwargs: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430         \"\"\"         step = f'Clicking {self.type_of} \"{self.name}\"'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             locator.click()      def check_visible(self, nth: int = 0, **kwargs):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u0438\u0434\u0438\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.          :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         :param kwargs: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430         \"\"\"         step = f'Checking that {self.type_of} \"{self.name}\" is visible'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             expect(locator).to_be_visible()      def check_have_text(self, text: str, nth: int = 0, **kwargs):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442.          :param text: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442         :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         :param kwargs: \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430         \"\"\"         step = f'Checking that {self.type_of} \"{self.name}\" has text \"{text}\"'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             expect(locator).to_have_text(text) <\/code><\/pre>\n<ul>\n<li>\n<p><strong>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <\/strong>\u2014 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u043b\u043e\u043a\u0430\u0442\u043e\u0440 (<code>data-testid<\/code>) \u0438 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><code><strong>type_of<\/strong><\/code><strong> <\/strong>\u2014 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c &#171;\u0442\u0438\u043f&#187; \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u043b\u043e\u0433\u043e\u0432 \u0438 \u0430\u043b\u043b\u044e\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><code><strong>get_locator<\/strong><\/code><strong> <\/strong>\u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 Locator \u0447\u0435\u0440\u0435\u0437 <code>data-testid<\/code>, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u0446\u0438\u044e \u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u044b<\/p>\n<\/li>\n<li>\n<p><code><strong>click<\/strong><\/code><strong> <\/strong>\u2014<strong> <\/strong>\u043a\u043b\u0438\u043a\u0430\u0435\u0442 \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443<\/p>\n<\/li>\n<li>\n<p><code><strong>check_visible<\/strong><\/code><strong> <\/strong>\u2014<strong> <\/strong>\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/p>\n<\/li>\n<li>\n<p><code><strong>check_have_text<\/strong><\/code><strong> <\/strong>\u2014<strong> <\/strong>\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <code><strong>BaseElement<\/strong><\/code> \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b: <code><strong>Button<\/strong><\/code>, <code><strong>Input<\/strong><\/code>, <code><strong>Text<\/strong><\/code>, <code><strong>Image<\/strong><\/code>. \u041e\u043d\u0438 \u0434\u043e\u0431\u0430\u0432\u044f\u0442 \u0441\u0432\u043e\u044e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0442\u043e\u0434 <code>fill()<\/code> \u0434\u043b\u044f \u0438\u043d\u043f\u0443\u0442\u0430) \u0438 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<h4>\u0412\u0430\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 data-testid \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432<\/h4>\n<p>\u041f\u0440\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u0436\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u043a \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043a\u043e\u0434\u0430: <code>self.page.get_by_test_id(locator).nth(nth)<\/code>. \u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <code>data-testid<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a data-testid?<\/h4>\n<p>\u041d\u0430\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0442\u0438\u043f\u0430 <code>data-testid<\/code>, <code>qa-id<\/code>, <code>data-test-id<\/code>, <code>qa-data-id<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435. \u0412\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2014 \u044d\u0442\u043e \u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435: \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <a href=\"https:\/\/www.w3schools.com\/cssref\/css_selectors.php\" rel=\"noopener noreferrer nofollow\">CSS-\u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.w3schools.com\/xml\/xpath_syntax.asp\" rel=\"noopener noreferrer nofollow\">XPath<\/a>, \u0438\u043c\u0435\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432:<\/p>\n<ul>\n<li>\n<p><strong>\u0421\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/strong>: \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <a href=\"https:\/\/www.w3schools.com\/xml\/xpath_syntax.asp\" rel=\"noopener noreferrer nofollow\">XPath<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.w3schools.com\/cssref\/css_selectors.php\" rel=\"noopener noreferrer nofollow\">CSS-\u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u0432<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u043e\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b HTML \u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <code>data-testid<\/code> \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b \u043e\u0442 \u0434\u0438\u0437\u0430\u0439\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0440\u0435\u0434\u0438\u0437\u0430\u0439\u043d\u043e\u0432. \u0415\u0441\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0441\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0432\u0438\u0434\u0430 \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u0442\u0435\u0441\u0442\u044b \u0441 <code>data-testid<\/code> \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>\u0427\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0441\u0442\u044c<\/strong>: \u0422\u0435\u0441\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u043b\u0435\u0433\u043a\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b. \u0412\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 <a href=\"https:\/\/www.w3schools.com\/xml\/xpath_syntax.asp\" rel=\"noopener noreferrer nofollow\">XPath<\/a> \u0438\u043b\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442\u0435. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u043a \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u0441\u043f\u043e\u0440\u043e\u0432 \u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u0445<\/strong>: \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u2014 <a href=\"https:\/\/www.w3schools.com\/cssref\/css_selectors.php\" rel=\"noopener noreferrer nofollow\">CSS<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.w3schools.com\/xml\/xpath_syntax.asp\" rel=\"noopener noreferrer nofollow\">XPath<\/a>? \u041e\u0442\u0432\u0435\u0442: \u043d\u0438 \u043e\u0434\u043d\u043e, \u043d\u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c. \u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <code>qa-id<\/code> \u0438\u043b\u0438 <code>data-testid<\/code> \u2014 \u044d\u0442\u043e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u041e\u043d\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u043e\u043b\u0433\u0438\u0445 \u0441\u043f\u043e\u0440\u043e\u0432 \u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0417\u0430\u0447\u0435\u043c \u044d\u0442\u043e \u043d\u0443\u0436\u043d\u043e?<\/h4>\n<p>\u0417\u0430\u0434\u0443\u043c\u0430\u0439\u0442\u0435\u0441\u044c: \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u2014 \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0435\u0434\u0435\u043b\u044e \u0438\u043b\u0438 \u0434\u0432\u0435 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u0438\u043b\u0438 \u0436\u0435 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438?<\/p>\n<p>\u0411\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b \u0432 \u0432\u0438\u0434\u0435 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 <a href=\"https:\/\/www.w3schools.com\/cssref\/css_selectors.php\" rel=\"noopener noreferrer nofollow\">CSS-\u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u0432<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.w3schools.com\/xml\/xpath_syntax.asp\" rel=\"noopener noreferrer nofollow\">XPath<\/a> \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u0434\u0432\u0435\u0440\u0436\u0435\u043d\u044b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0440\u0435\u0434\u0438\u0437\u0430\u0439\u043d\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u042d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u0438 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0447\u0442\u043e \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0438\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0432 \u043d\u0435\u0434\u0435\u043b\u044e \u0438\u043b\u0438 \u0434\u0432\u0435 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 <code>data-testid<\/code> \u0438\u043b\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0445 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u0442\u0435 \u043d\u0430\u0434\u0435\u0436\u043d\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0440\u0435\u0434\u0438\u0437\u0430\u0439\u043d\u0430.<\/p>\n<h4>\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c data-testid?<\/h4>\n<p>\u0414\u043b\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u043f\u0443\u0442\u0438:<\/p>\n<ol>\n<li>\n<p><strong>\u041f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432<\/strong>: \u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438, \u0431\u0443\u0434\u044c \u0442\u043e <a href=\"https:\/\/react.dev\/\" rel=\"noopener noreferrer nofollow\">React<\/a>, <a href=\"https:\/\/vuejs.org\/\" rel=\"noopener noreferrer nofollow\">Vue<\/a>, <a href=\"https:\/\/angular.dev\/\" rel=\"noopener noreferrer nofollow\">Angular<\/a> \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u044e\u0442 \u0432\u0430\u0436\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432. \u041f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u0438\u0445 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e<\/strong>: \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e, \u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u0430\u043c\u0438. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0438\u0445 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<\/li>\n<\/ol>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 \u0432\u0430\u0436\u043d\u043e?<\/h4>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 <code>qa-id<\/code> \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u2014 \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u0445\u043e\u0440\u043e\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f UI. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044e\u0442 \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u0438 \u043f\u044b\u0442\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0431\u0435\u0437 \u043d\u0435\u0433\u043e, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043d\u0435\u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0438 \u0442\u0440\u0443\u0434\u043d\u044b\u0445 \u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0442\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u043c\u0438, \u0430 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0438\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0440\u0430\u0441\u0442\u0435\u0442.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u043f\u0438\u0448\u0443\u0442\u0441\u044f. \u042d\u0442\u043e \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u043c \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h4>\u0418\u0442\u043e\u0433<\/h4>\n<p>\u0418\u0442\u0430\u043a, \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u043f\u0446\u0438\u044f, \u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0431\u0430\u0437\u0430 \u0434\u043b\u044f \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>data-testid<\/code> \u0438\u043b\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0447\u0435\u0442\u043a\u0443\u044e \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0437\u0431\u0430\u0432\u0438\u0442 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0434\u0438\u0437\u0430\u0439\u043d\u0430. \u041f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0435\u0434\u0435\u043b\u044e \u043d\u0430 \u0438\u0445 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u2014 \u044d\u0442\u043e \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u043c\u0435\u043d\u044c\u0448\u0438\u0439 \u0440\u0435\u0441\u0443\u0440\u0441, \u0447\u0435\u043c \u043f\u043e\u0442\u043e\u043c \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043c\u0435\u0441\u044f\u0446\u044b \u043d\u0430 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f.<\/p>\n<h3>\u041a\u043b\u0430\u0441\u0441 Button<\/h3>\n<p>\u041a\u043b\u0430\u0441\u0441 <code><strong>Button<\/strong><\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 <code><strong>BaseElement<\/strong><\/code>. \u0412 \u044d\u0442\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u044b, \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438 (\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0438\u043b\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0430). \u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b \u043a\u043b\u0430\u0441\u0441\u0443 <code><strong>BaseElement<\/strong><\/code>.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/button.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/button.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import expect  from elements.base_element import BaseElement from tools.logger import get_logger  logger = get_logger(\"BUTTON\")   class Button(BaseElement):     \"\"\"     \u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 BaseElement \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442     \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430\/\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0430).     \"\"\"        @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \"button\".         \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u043d\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         \"\"\"         return \"button\"      def check_enabled(self, nth: int = 0, **kwargs):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0430 (\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430). \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432,         \u043a\u043e\u0433\u0434\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u043a\u043b\u0438\u043a\u0430.          :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u043a\u043d\u043e\u043f\u043a\u0438, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         :param kwargs: \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430.         :raises AssertionError: \u0415\u0441\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0430.         \"\"\"         step = f'Checking that {self.type_of} \"{self.name}\" is enabled'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             expect(locator).to_be_disabled()      def check_disabled(self, nth: int = 0, **kwargs):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u0430 (\u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0430). \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432,         \u043a\u043e\u0433\u0434\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u043a\u043b\u0438\u043a\u0430.          :param nth: \u0418\u043d\u0434\u0435\u043a\u0441 \u043a\u043d\u043e\u043f\u043a\u0438, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         :param kwargs: \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430.         :raises AssertionError: \u0415\u0441\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u0430\u043a\u0442\u0438\u0432\u043d\u0430.         \"\"\"         step = f'Checking that {self.type_of} \"{self.name}\" is disabled'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             expect(locator).to_be_disabled() <\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 <code><strong>Button<\/strong><\/code> \u2014 \u044d\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code><strong>BaseElement<\/strong><\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u043d\u043e\u043f\u043a\u0438. \u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p>\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430, \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u2014 \u044d\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438 \u0438\u043b\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430).<\/p>\n<h3>Input<\/h3>\n<p>\u041a\u043b\u0430\u0441\u0441 <code><strong>Input<\/strong><\/code> \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <code><strong>BaseElement<\/strong><\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0432\u0432\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/input.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/input.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import expect, Locator  from elements.base_element import BaseElement from tools.logger import get_logger  logger = get_logger(\"INPUT\")   class Input(BaseElement):     \"\"\"     \u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0432\u0432\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 BaseElement     \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0432\u0432\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439     \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u043e\u043b\u0435.     \"\"\"        @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \"input\".         \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0443\u043d\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         \"\"\"         return \"input\"      def get_locator(self, nth: int = 0, **kwargs) -&gt; Locator:         \"\"\"         \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0430.         \"\"\"         # \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f input         # \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0445\u0438\u0442\u0440\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430         return super().get_locator(nth, **kwargs).locator('input')      def fill(self, value: str, nth: int = 0, **kwargs):         \"\"\"         \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c.          :param value: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u0432 \u043f\u043e\u043b\u0435.         :param nth: \u0418\u043d\u0434\u0435\u043a\u0441, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         :param kwargs: \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430.         :raises AssertionError: \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u0435 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0438\u043b\u0438 \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430.         \"\"\"         step = f'Fill {self.type_of} \"{self.name}\" to value \"{value}\"'          with allure.step(step):             locator = self.get_locator(nth, **kwargs)             logger.info(step)             locator.fill(value)      def check_have_value(self, value: str, nth: int = 0, **kwargs):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.          :param value: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430.         :param nth: \u0418\u043d\u0434\u0435\u043a\u0441, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.         :param kwargs: \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430.         :raises AssertionError: \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043f\u043e\u043b\u0435 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443.         \"\"\"         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) <\/code><\/pre>\n<h3>Text<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/text.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/text.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from elements.base_element import BaseElement   class Text(BaseElement):     \"\"\"     \u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 BaseElement, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c     \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u043a\u0430\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \"\"\"          @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \"text\".         \"\"\"         return \"text\" <\/code><\/pre>\n<h3>Image<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/image.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/image.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from elements.base_element import BaseElement   class Image(BaseElement):     \"\"\"     \u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 BaseElement, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c     \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u0430\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \"\"\"        @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \"image\".         \"\"\"         return \"image\" <\/code><\/pre>\n<h3>Link<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/elements\/link.py\" rel=\"noopener noreferrer nofollow\"><strong>\/elements\/link.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from elements.base_element import BaseElement   class Link(BaseElement):     \"\"\"     \u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 BaseElement, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c     \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043a\u0430\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.     \"\"\"         @property     def type_of(self) -&gt; str:         \"\"\"         \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \"link\".         \"\"\"         return \"link\" <\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 (<code><strong>Text<\/strong><\/code>, <code><strong>Image<\/strong><\/code>, \u0438 <code><strong>Link<\/strong><\/code>) \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0442 <code><strong>BaseElement<\/strong><\/code>. \u041e\u043d\u0438 \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043c\u0435\u0442\u043e\u0434 <code><strong>type_of<\/strong><\/code>, \u0447\u0442\u043e\u0431\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c, \u043e\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0442\u0435\u0441\u0442\u0430\u0445, \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<h3>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f PageFactory \u0432 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<h4>1. \u0421\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435<\/h4>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 PageFactory \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u044f\u0441\u043d\u044b\u043c\u0438 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438, \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0432\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438, \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u043e\u0434 \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>: \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 &#171;Submit&#187;, \u0432\u044b \u043f\u0440\u044f\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439, \u0430 \u043d\u0435 \u0441 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u043c. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0447\u0438\u0442\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u043b\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a.<\/p>\n<h4>2. \u0418\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u044f<\/h4>\n<p>PageFactory \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u041a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>click<\/code> \u0438\u043b\u0438 <code>check_visible<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0432\u0441\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c\u0441\u044f \u043e \u043c\u0435\u043b\u043a\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u044f\u0445, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u043a. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e, \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u044b\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u0438\u0441\u0442\u0438\u043d\u044b.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>: \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432:<\/p>\n<ul>\n<li>\n<p><code>assert locator.is_visible()<\/code><\/p>\n<\/li>\n<li>\n<p><code>expect(locator).to_be_visible()<\/code><\/p>\n<\/li>\n<li>\n<p><code>locator.wait_for(state='visible')<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u044d\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0435\u043b\u0430\u044e\u0442 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435, \u043d\u043e \u0432\u0435\u0440\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 <code>expect(locator).to_be_visible()<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0415\u0441\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 <code>AssertionError<\/code>. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f PageFactory, \u043c\u044b \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438 \u043d\u0435\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0411\u0435\u0437 PageFactory \u0442\u0430\u043a\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0445\u0430\u043e\u0441\u0443 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435: \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0434\u0438\u0441\u043a\u0443\u0441\u0441\u0438\u044f\u043c \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430. \u0412 PageFactory \u043b\u043e\u0433\u0438\u043a\u0430 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430, \u0438 \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u0447\u0442\u043e \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<h4>3. \u0420\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432<\/h4>\n<p>\u0412 PageFactory \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0435\u0433\u043e \u0442\u0438\u043f\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u2014 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430. \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>: \u0415\u0441\u043b\u0438 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u043f\u043e\u043b\u0435\u043c \u0432\u0432\u043e\u0434\u0430, \u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0442\u043e\u0434\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044e \u0432\u0432\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>fill()<\/code>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u0430, \u044d\u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h4>4. \u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 Allure \u0448\u0430\u0433\u0438<\/h4>\n<p>PageFactory \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0448\u0430\u0433\u043e\u0432 \u0432 <a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u0447\u0435\u0442 Allure<\/a>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0435 \u0448\u0430\u0433\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438, \u0434\u0435\u043b\u0430\u044f \u043e\u0442\u0447\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u043c.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>: \u041f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, Allure \u0448\u0430\u0433 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">Checking that button \"Login\" is visible<\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u044f\u0432\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0441 \u043a\u0430\u043a\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0442\u0447\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432 \u0438 \u0434\u0430\u0436\u0435 \u0431\u0438\u0437\u043d\u0435\u0441-\u0430\u043d\u0430\u043b\u0438\u0441\u0442\u043e\u0432. \u041f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>type_of<\/code> \u0438 \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Allure \u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c.<\/p>\n<h4>5. \u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/h4>\n<p>PageFactory \u0434\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430, \u0442\u0440\u0435\u0431\u0443\u044e\u0449\u0435\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>get_locator<\/code>.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>: \u0415\u0441\u043b\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0435\u0441\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0447\u0430\u0442\u044c \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <code>KeyboardInput<\/code>, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>fill()<\/code> \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043d\u044b\u043c \u0432\u0432\u043e\u0434\u043e\u043c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.<\/p>\n<pre><code class=\"python\">class KeyboardInput(Input):     def fill(self, value: str, nth: int = 0, **kwargs):         # \u0421\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u044b         pass<\/code><\/pre>\n<h4>6. \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432<\/h4>\n<p>PageFactory \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432, \u0447\u0442\u043e \u0440\u0435\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0438\u043b\u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0438\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440<\/strong>:<\/p>\n<pre><code class=\"python\">dynamic_input = Input(page, \"dynamic-input-{index}\", \"Dynamic input\") dynamic_input.fill(index=100)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c <code>index<\/code> \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0443\u0436\u043d\u044b\u0439 \u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>dynamic-input-100<\/code>.<\/p>\n<h4>7. \u0412\u0435\u0440\u0431\u043e\u0437\u043d\u043e\u0441\u0442\u044c \u0438 \u044f\u0441\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0447\u0435\u0442\u043e\u0432<\/h4>\n<p>PageFactory \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0448\u0430\u0433\u0438 \u0432 Allure, \u043d\u043e \u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u0442\u0447\u0435\u0442\u044b \u0438 \u043b\u043e\u0433\u0438 \u0431\u0443\u0434\u0443\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">Click \"Submit\" button Fill input \"Username\" with value \"test_user\"<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0442\u0447\u0435\u0442\u044b \u0438 \u043b\u043e\u0433\u0438 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u2014 \u043a\u0430\u043a \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432 \u0438\u043b\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u0430\u043d\u0430\u043b\u0438\u0441\u0442\u043e\u0432.<\/p>\n<h4>8. \u0424\u043e\u043a\u0443\u0441 \u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443<\/h4>\n<p>\u0412\u0441\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0430\u043c \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438, \u0430 \u043d\u0435 \u043d\u0430 \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0438\u043b\u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u0412\u0441\u0435 \u044d\u0442\u043e \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c PageFactory, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h4>9. \u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c, \u043d\u043e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0432\u0430\u0436\u043d\u044b\u043c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 PageFactory. \u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a \u0438\u043b\u0438 \u043c\u0430\u0433\u0438\u0438, \u0432\u0441\u0435 \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u0432 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5\" rel=\"noopener noreferrer nofollow\">\u041e\u041e\u041f<\/a>. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u0438 \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0431\u0443\u0434\u044c \u0442\u043e Python, Java \u0438\u043b\u0438 JavaScript, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h2>PageComponent<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432. \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0430\u0442\u0442\u0435\u0440\u043d PageComponent \u2014 \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u044f \u0435\u0451 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435, \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 (\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b). \u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PageFactory.<\/p>\n<p>\u0422\u0430\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438. \u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0422\u0443\u043b\u0431\u0430\u0440 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\/\u0447\u0430\u0440\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c (<a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\">Navbar<\/a>)<\/p>\n<\/li>\n<\/ul>\n<h3>BaseComponent<\/h3>\n<p>\u0412\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 <code><strong>BaseComponent<\/strong><\/code>. \u042d\u0442\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0434\u0430\u0451\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043e\u0431\u0449\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445. \u041a\u0430\u043a \u0438 \u043b\u044e\u0431\u043e\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, PageComponent \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<p>BaseComponent \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0443\u0447\u0430\u0441\u0442\u043e\u043a \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043e\u043d \u0441\u043b\u0443\u0436\u0438\u0442 \u043e\u0441\u043d\u043e\u0432\u043e\u0439 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/components\/base_component.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/base_component.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from typing import Pattern  import allure from playwright.sync_api import Page, expect  from tools.logger import get_logger  logger = get_logger(\"BASE_COMPONENT\")   class BaseComponent:     \"\"\"     \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.     \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.     \"\"\"     def __init__(self, page: Page):         \"\"\"         \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.          :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright.         \"\"\"         self.page = page      def check_current_url(self, expected_url: Pattern[str]):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 URL \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0443.          :param expected_url: \u0428\u0430\u0431\u043b\u043e\u043d (\u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435), \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c URL.         \"\"\"         step = f'Checking that current url matches pattern \"{expected_url.pattern}\"'          # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0448\u0430\u0433 \u0432 Allure \u043e\u0442\u0447\u0451\u0442         with allure.step(step):             # \u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0448\u0430\u0433 \u0432 \u043b\u043e\u0433             logger.info(step)             # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e URL \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0443             expect(self.page).to_have_url(expected_url) <\/code><\/pre>\n<ul>\n<li>\n<p><code>BaseComponent<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 <a href=\"https:\/\/playwright.dev\/python\/docs\/pages\" rel=\"noopener noreferrer nofollow\">Page<\/a> \u043e\u0442 Playwright \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a <code>self.page<\/code>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043b\u044e\u0431\u043e\u043c\u0443 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u043c\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>check_current_url<\/code> \u2014 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 URL \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u043d\u0443\u0436\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>Allure \u0434\u043b\u044f \u043e\u0442\u0447\u0451\u0442\u0430:<a href=\"https:\/\/allurereport.org\/docs\/pytest\/#divide-a-test-into-steps\" rel=\"noopener noreferrer nofollow\"> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0448\u0430\u0433<\/a> \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c.<\/p>\n<\/li>\n<li>\n<p>Playwright <a href=\"https:\/\/playwright.dev\/python\/docs\/test-assertions#list-of-assertions\" rel=\"noopener noreferrer nofollow\">expect()<\/a> \u0434\u043b\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f URL.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>RegistrationForm<\/h3>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u2014 <code><strong>RegistrationFormComponent<\/strong><\/code>. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 \u0432\u0432\u043e\u0434\u0430 <code>email<\/code>, <code>username<\/code> \u0438 <code>password<\/code>. \u042d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d \u043e\u0442 <code>BaseComponent<\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0442\u0438\u043f\u0430 <code>Input<\/code>, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 PageFactory.<\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><code>fill<\/code> \u2014 \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u044b<\/p>\n<\/li>\n<li>\n<p><code>check_visible<\/code> \u2014 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0430\u0441\u044c \u0438 \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/865\/0e3\/19a\/8650e319a5432fb285edfd99daef9a3a.png\" width=\"3020\" height=\"1506\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/865\/0e3\/19a\/8650e319a5432fb285edfd99daef9a3a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/865\/0e3\/19a\/8650e319a5432fb285edfd99daef9a3a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/components\/registration_form_component.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/registration_form_component.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import Page  from components.base_component import BaseComponent from elements.input import Input   class RegistrationFormComponent(BaseComponent):     \"\"\"     \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u043b\u044f: Email, Username, Password.     \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0444\u043e\u0440\u043c\u044b.     \"\"\"          def __init__(self, page: Page):         \"\"\"         \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.          :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Playwright Page         \"\"\"                super().__init__(page)          # \u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 email         self.email_input = Input(page, \"registration-form-email-input\", \"Email\")         # \u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 username         self.username_input = Input(page, \"registration-form-username-input\", \"Username\")         # \u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 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):         \"\"\"         \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0444\u043e\u0440\u043c\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438.          :param email: Email \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f         :param username: \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f         :param password: \u041f\u0430\u0440\u043e\u043b\u044c         \"\"\"         # \u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 email \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e         self.email_input.fill(email)         self.email_input.check_have_value(email)           # \u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 username \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e         self.username_input.fill(username)         self.username_input.check_have_value(username)          # \u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 password \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e         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):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.          :param email: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 email         :param username: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 username         :param password: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f         \"\"\"         # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 email-\u043f\u043e\u043b\u044f         self.email_input.check_visible()         self.email_input.check_have_value(email)          # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 username-\u043f\u043e\u043b\u044f         self.username_input.check_visible()         self.username_input.check_have_value(username)          # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 password-\u043f\u043e\u043b\u044f         self.password_input.check_visible()         self.password_input.check_have_value(password) <\/code><\/pre>\n<p><strong>\u0412\u0430\u0436\u043d\u043e!<\/strong> \u0412 \u043c\u0435\u0442\u043e\u0434\u0430\u0445 <code>fill<\/code> \u0438 <code>check_visible<\/code> \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u042d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0444\u043e\u0440\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u0435\u0439 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435, \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u043b\u043e\u0436\u0435\u043d\u044b, \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/docs.python.org\/3\/library\/dataclasses.html\" rel=\"noopener noreferrer nofollow\">@dataclass<\/a> \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432:<\/p>\n<pre><code class=\"python\">from dataclasses import dataclass  @dataclass class RegistrationFormFillParams:     email: str     username: str     password: str<\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 \u043c\u0435\u0442\u043e\u0434 <code>fill<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">def fill(self, params: RegistrationFormFillParams):     self.email_input.fill(params.email)     self.username_input.fill(params.username)     self.password_input.fill(params.password)<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434:<\/p>\n<ul>\n<li>\n<p>\u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u044d\u0442\u043e \u043d\u0435 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e, \u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438.<\/p>\n<h3>DashboardToolbarViewComponent<\/h3>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0442\u0443\u043b\u0431\u0430\u0440\u0430 (\u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432) \u043d\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0435\u0433\u043e \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u2014 \u0442\u0435\u043a\u0441\u0442\u0430 Dashboard.<\/p>\n<p>\u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438\u043b\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043d\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dcd\/321\/54c\/dcd32154c52a721ba7c37e967cd12749.png\" width=\"3024\" height=\"1506\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/dcd\/321\/54c\/dcd32154c52a721ba7c37e967cd12749.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dcd\/321\/54c\/dcd32154c52a721ba7c37e967cd12749.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/components\/dashboard_toolbar_view_component.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/dashboard_toolbar_view_component.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import Page  from components.base_component import BaseComponent from elements.text import Text   class DashboardToolbarViewComponent(BaseComponent):     \"\"\"     \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435.     \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 'Dashboard'.     \"\"\"        def __init__(self, page: Page):         \"\"\"         \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432.          :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright         \"\"\"         super().__init__(page)          # \u042d\u043b\u0435\u043c\u0435\u043d\u0442, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0449\u0438\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432         self.title = Text(page, 'dashboard-toolbar-title-text', 'Dashboard')      @allure.step(\"Check visible dashboard toolbar view\")     def check_visible(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e:         - \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u0432\u0438\u0434\u0435\u043d         - \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u0435\u043a\u0441\u0442 'Dashboard'         \"\"\"         # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432\u0438\u0434\u0435\u043d \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435         self.title.check_visible()         # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442         self.title.check_have_text('Dashboard') <\/code><\/pre>\n<ul>\n<li>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>Text<\/code>, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 <code>BaseElement<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u044b <a href=\"https:\/\/allurereport.org\/docs\/pytest\/#divide-a-test-into-steps\" rel=\"noopener noreferrer nofollow\">\u0448\u0430\u0433\u0438 Allure<\/a> \u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>check_visible<\/code> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0434\u0432\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/p>\n<\/li>\n<li>\n<p>\u0442\u0435\u043a\u0441\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e &#171;Dashboard&#187;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u2014 \u0445\u043e\u0440\u043e\u0448\u0430\u044f \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/Smoke_test\" rel=\"noopener noreferrer nofollow\">smoke-\u0442\u0435\u0441\u0442\u0430\u0445<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Sanity_check#:~:text=A%20sanity%20check%20or%20sanity,thinking%20rationally%2C%20applying%20sanity).\" rel=\"noopener noreferrer nofollow\">sanity-check&#8217;\u0430\u0445<\/a> \u043f\u043e\u0441\u043b\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<h3>ChartViewComponent<\/h3>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0433\u0440\u0430\u0444\u0438\u043a (\u0447\u0430\u0440\u0442) \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 <code>identifier<\/code> \u0438 <code>chart_type<\/code>.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e52\/1fc\/d97\/e521fcd972ebd15abbd0b0097316b6f2.png\" width=\"3024\" height=\"1508\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e52\/1fc\/d97\/e521fcd972ebd15abbd0b0097316b6f2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e52\/1fc\/d97\/e521fcd972ebd15abbd0b0097316b6f2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/components\/chart_view_component.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/chart_view_component.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import Page  from components.base_component import BaseComponent from elements.image import Image from elements.text import Text   class ChartViewComponent(BaseComponent):     \"\"\"     \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 (\u0447\u0430\u0440\u0442\u0430), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435 \u0438\u043b\u0438 \u0432 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0435.      :param identifier: \u0411\u0430\u0437\u043e\u0432\u044b\u0439 ID \u0432\u0438\u0434\u0436\u0435\u0442\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \"students\", \"scores\", \"courses\")     :param chart_type: \u0422\u0438\u043f \u0433\u0440\u0430\u0444\u0438\u043a\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \"bar\", \"line\", \"pie\")     \"\"\"        def __init__(self, page: Page, identifier: str, chart_type: str):         super().__init__(page)          # \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0433\u0440\u0430\u0444\u0438\u043a\u0430         self.title = Text(page, f'{identifier}-widget-title-text', 'Title')         # \u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0430         self.chart = Image(page, f'{identifier}-{chart_type}-chart', 'Chart')      @allure.step('Check visible chart view \"{title}\"')     def check_visible(self, title: str):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0447\u0430\u0440\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e:         - \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432\u0438\u0434\u0435\u043d \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442         - \u0413\u0440\u0430\u0444\u0438\u043a (image) \u0432\u0438\u0434\u0435\u043d \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435          :param title: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0433\u0440\u0430\u0444\u0438\u043a\u0430         \"\"\"         self.title.check_visible()         self.title.check_have_text(title)          self.chart.check_visible() <\/code><\/pre>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>identifier<\/code> \u0438 <code>chart_type<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>check_visible<\/code> \u043c\u044b \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u0435\u043c \u0434\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430: \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0438 \u0441\u0430\u043c \u0433\u0440\u0430\u0444\u0438\u043a.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/allurereport.org\/docs\/pytest\/#divide-a-test-into-steps\" rel=\"noopener noreferrer nofollow\">\u0428\u0430\u0433 allure<\/a> \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>title<\/code>, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c.<\/p>\n<\/li>\n<\/ul>\n<h3>NavbarComponent<\/h3>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u0438. \u041e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4c9\/c7e\/d9f\/4c9c7ed9f9758ae1cbead653b091ade2.png\" width=\"3024\" height=\"1520\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4c9\/c7e\/d9f\/4c9c7ed9f9758ae1cbead653b091ade2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4c9\/c7e\/d9f\/4c9c7ed9f9758ae1cbead653b091ade2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/components\/navbar_component.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/navbar_component.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure from playwright.sync_api import Page  from components.base_component import BaseComponent from elements.text import Text   class NavbarComponent(BaseComponent):     \"\"\"     \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u043c\u0435\u043d\u044e (navbar), \u0433\u0434\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f:     - \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f     - \u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     \"\"\"        def __init__(self, page: Page):         super().__init__(page)          # \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f         self.app_title = Text(page, 'navigation-navbar-app-title-text', 'App title')         # \u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f         self.welcome_title = Text(page, 'navigation-navbar-welcome-title-text', 'Welcome title')      @allure.step(\"Check visible navbar\")     def check_visible(self, username: str):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e navbar \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e:         - \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u043d\u043e \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 'UI Course'         - \u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f          :param username: \u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438         \"\"\"         self.app_title.check_visible()         self.app_title.check_have_text('UI Course')          self.welcome_title.check_visible()         self.welcome_title.check_have_text(f'Welcome, {username}!') <\/code><\/pre>\n<ul>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438, \u0447\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>Text<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0441 \u043b\u043e\u0433\u0430\u043c\u0438 \u0438 \u0448\u0430\u0433\u0430\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<h2>PageObject<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0435\u043a\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0430\u0442\u0442\u0435\u0440\u043d Page Object Model (POM) \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 UI.<\/p>\n<p>PageObject \u2014 \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0435\u0451 \u0447\u0430\u0441\u0442\u044c. \u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b: \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e, \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u043f\u0440\u043e\u0449\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0443\u0434\u0435\u0442 \u0434\u0432\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<ol>\n<li>\n<p><code>RegistrationPage<\/code> \u2014 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code>DashboardPage<\/code> \u2014 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435.<\/p>\n<h3>BasePage<\/h3>\n<p>\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043e\u0431\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 URL, \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e URL.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/pages\/base_page.py\" rel=\"noopener noreferrer nofollow\"><strong>\/pages\/base_page.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from typing import Pattern  import allure from playwright.sync_api import Page, expect  from tools.logger import get_logger  logger = get_logger(\"BASE_PAGE\")   class BasePage:     \"\"\"     \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 PageObject-\u0441\u0442\u0440\u0430\u043d\u0438\u0446.      \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0449\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:     - \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043f\u043e URL     - \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b     - \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e URL     \"\"\"        def __init__(self, page: Page):         \"\"\"         :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright         \"\"\"         self.page = page      def visit(self, url: str):         \"\"\"         \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c\u0443 URL \u0438 \u0436\u0434\u0451\u0442 \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.          :param url: URL \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b         \"\"\"         step = f'Opening the url \"{url}\"'          with allure.step(step):             logger.info(step)             # \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 URL             self.page.goto(url, wait_until='networkidle')      def reload(self):         \"\"\"         \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0436\u0434\u0451\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 DOM.         \"\"\"         step = f'Reloading page with url \"{self.page.url}\"'          with allure.step(step):             logger.info(step)             # \u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b             self.page.reload(wait_until='domcontentloaded')      def check_current_url(self, expected_url: Pattern[str]):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0447\u0442\u043e \u0442\u0435\u043a\u0443\u0449\u0438\u0439 URL \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u043c\u0443 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044e.          :param expected_url: \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 URL \u043a\u0430\u043a \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 (Pattern)         \"\"\"         step = f'Checking that current url matches pattern \"{expected_url.pattern}\"'          with allure.step(step):             logger.info(step)             # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e URL             expect(self.page).to_have_url(expected_url) <\/code><\/pre>\n<ul>\n<li>\n<p><code>visit(url)<\/code> \u2014 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0438 \u0436\u0434\u0451\u0442, \u043f\u043e\u043a\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u0441\u044f \u0432\u0441\u0435 \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p><code>reload()<\/code> \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 DOM.<\/p>\n<\/li>\n<li>\n<p><code>check_current_url()<\/code> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 (<a href=\"https:\/\/docs.python.org\/3\/library\/re.html\" rel=\"noopener noreferrer nofollow\">Pattern[str]<\/a>), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0433\u0438\u0431\u043a\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c URL (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u0442\u043e\u043a\u0435\u043d\u0430\u043c\u0438 \u0438 \u0442.\u043f.).<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043e\u0431\u0451\u0440\u043d\u0443\u0442\u044b \u0432 <a href=\"https:\/\/allurereport.org\/docs\/pytest\/#divide-a-test-into-steps\" rel=\"noopener noreferrer nofollow\">\u0448\u0430\u0433\u0438 allure<\/a>, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442\u044b \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0433\u0435\u0440\u0430 <code>BASE_PAGE<\/code> \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0432 \u043b\u043e\u0433\u0430\u0445.<\/p>\n<\/li>\n<\/ul>\n<h3>RegistrationPage<\/h3>\n<p>\u042d\u0442\u043e PageObject \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438. \u041e\u043d \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0444\u043e\u0440\u043c\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043a\u043d\u043e\u043f\u043a\u0438.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/862\/bd0\/79a\/862bd079a82e1bf5612df6627cc1074e.png\" width=\"3024\" height=\"1498\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/862\/bd0\/79a\/862bd079a82e1bf5612df6627cc1074e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/862\/bd0\/79a\/862bd079a82e1bf5612df6627cc1074e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/pages\/registration_page.py\" rel=\"noopener noreferrer nofollow\"><strong>\/pages\/registration_page.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import re  from playwright.sync_api import Page  from components.registration_form_component import RegistrationFormComponent from elements.button import Button from elements.link import Link from pages.base_page import BasePage   class RegistrationPage(BasePage):     \"\"\"     \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 (Registration Page).      \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b:     - \u0424\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438     - \u041a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0445\u043e\u0434\u0430     - \u041a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438      \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 BasePage.     \"\"\"        def __init__(self, page: Page):         \"\"\"         \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.          :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright         \"\"\"         super().__init__(page)          # \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b         self.registration_form = RegistrationFormComponent(page)  # \u0424\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438          # \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b         self.login_link = Link(page, \"registration-page-login-link\", \"Login\")  # \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0445\u043e\u0434\u0430         self.registration_button = Button(page, \"registration-page-registration-button\", \"Registration\")  # \u041a\u043d\u043e\u043f\u043a\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b      def click_registration_button(self):         \"\"\"         \u041a\u043b\u0438\u043a \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f\" \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.          :raises AssertionError: \u0415\u0441\u043b\u0438 URL \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443         \"\"\"         # \u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438         self.registration_button.click()         # \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f         self.check_current_url(re.compile(\".*\/#\/dashboard\")) <\/code><\/pre>\n<ul>\n<li>\n<p><strong>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <\/strong><code><strong>__init__(self, page: Page):<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043a\u043d\u043e\u043f\u043a\u0438 \u0438 \u0441\u0441\u044b\u043b\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 <code>BasePage<\/code>, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 URL.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u041c\u0435\u0442\u043e\u0434 <\/strong><code><strong>click_registration_button(self):<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u041a\u043b\u0438\u043a\u0430\u0435\u0442 \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u043b\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e URL \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u043c\u0443, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>DashboardPage<\/h3>\n<p>\u042d\u0442\u043e PageObject \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041e\u043d \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a \u043f\u0430\u043d\u0435\u043b\u0438 \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438, \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u0438 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/pages\/dashboard_page.py\" rel=\"noopener noreferrer nofollow\"><strong>\/components\/dashboard_page.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from playwright.sync_api import Page  from components.chart_view_component import ChartViewComponent from components.dashboard_toolbar_view_component import DashboardToolbarViewComponent from components.navbar_component import NavbarComponent from pages.base_page import BasePage   class DashboardPage(BasePage):     \"\"\"     \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f (Dashboard Page).      \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:     - \u041f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438 (Navbar)     - \u0413\u0440\u0430\u0444\u0438\u043a\u0438 \u043f\u043e \u043e\u0446\u0435\u043d\u043a\u0430\u043c, \u043a\u0443\u0440\u0441\u0430\u043c, \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0430\u043c \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044f\u043c     - \u041f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f      \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 BasePage.     \"\"\"        def __init__(self, page: Page):         \"\"\"         \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f.          :param page: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Playwright         \"\"\"         super().__init__(page)          # \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b         self.navbar = NavbarComponent(page)  # \u041f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438         self.scores_chart_view = ChartViewComponent(page, \"scores\", \"scatter\")  # \u0413\u0440\u0430\u0444\u0438\u043a \u043f\u043e \u043e\u0446\u0435\u043d\u043a\u0430\u043c         self.courses_chart_view = ChartViewComponent(page, \"courses\", \"pie\")  # \u0413\u0440\u0430\u0444\u0438\u043a \u043f\u043e \u043a\u0443\u0440\u0441\u0430\u043c         self.students_chart_view = ChartViewComponent(page, \"students\", \"bar\")  # \u0413\u0440\u0430\u0444\u0438\u043a \u043f\u043e \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0430\u043c         self.activities_chart_view = ChartViewComponent(page, \"activities\", \"line\")  # \u0413\u0440\u0430\u0444\u0438\u043a \u043f\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044f\u043c         self.dashboard_toolbar_view = DashboardToolbarViewComponent(page)  # \u041f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432      def check_visible_students_chart(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u043e \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u0430\u043c.          :raises AssertionError: \u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0435 \u0432\u0438\u0434\u0435\u043d \u0438\u043b\u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430         \"\"\"         self.students_chart_view.check_visible('Students')      def check_visible_courses_chart(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u043e \u043a\u0443\u0440\u0441\u0430\u043c.          :raises AssertionError: \u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0435 \u0432\u0438\u0434\u0435\u043d \u0438\u043b\u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430         \"\"\"         self.courses_chart_view.check_visible('Courses')      def check_visible_activities_chart(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u043e \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044f\u043c.          :raises AssertionError: \u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0435 \u0432\u0438\u0434\u0435\u043d \u0438\u043b\u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430         \"\"\"         self.activities_chart_view.check_visible('Activities')      def check_visible_scores_chart(self):         \"\"\"         \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u043e \u043e\u0446\u0435\u043d\u043a\u0430\u043c.          :raises AssertionError: \u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0435 \u0432\u0438\u0434\u0435\u043d \u0438\u043b\u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430         \"\"\"         self.scores_chart_view.check_visible('Scores') <\/code><\/pre>\n<ul>\n<li>\n<p><strong>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 <\/strong><code><strong>__init__(self, page: Page):<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code><strong>NavbarComponent<\/strong><\/code> \u2014 \u043f\u0430\u043d\u0435\u043b\u044c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code><strong>ChartViewComponent<\/strong><\/code> \u2014 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 (\u043e\u0446\u0435\u043d\u043a\u0438, \u043a\u0443\u0440\u0441\u044b, \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u044b, \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438).<\/p>\n<\/li>\n<li>\n<p><code><strong>DashboardToolbarViewComponent<\/strong><\/code> \u2014 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u041c\u0435\u0442\u043e\u0434\u044b <\/strong><code><strong>check_visible_*_chart(self):<\/strong><\/code><\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0432\u0438\u0434\u0438\u043c \u043b\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>check_visible<\/code> \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u043a\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432 \u2014 <code>self.students_chart_view.check_visible('Students')<\/code>).<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0433\u0440\u0430\u0444\u0438\u043a \u043d\u0435 \u0432\u0438\u0434\u0435\u043d \u0438\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u043e\u0448\u0435\u043d\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <code>AssertionError<\/code>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>\u041f\u043b\u044e\u0441\u044b \u0438 \u043c\u0438\u043d\u0443\u0441\u044b PageObject<\/h3>\n<p>\u0412 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0447\u0430\u0441\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c \u043c\u043d\u0435\u043d\u0438\u0435, \u0447\u0442\u043e PageObject \u2014 \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0438\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0434\u043b\u044f UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0438 \u0447\u0442\u043e \u043e\u043d \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0441\u043f\u0430\u0441\u0430\u0435\u0442 \u043e\u0442 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0442\u0430\u043a, \u043d\u043e, \u043a\u0430\u043a \u0438 \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, PageObject \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u0445:<\/p>\n<h4>\u041c\u0438\u043d\u0443\u0441\u044b PageObject<\/h4>\n<h4>1. \u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>PageObject \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043e\u0432\u0435\u0440\u0445\u0435\u0434, \u0438 \u0438\u043d\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432. \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c PageObject. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0441\u043e\u0431\u044b\u0445 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u0435\u0439, \u043d\u043e \u0435\u0441\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0438 \u0441\u043b\u043e\u0436\u043d\u043e\u0439, \u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439. \u0412 \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p><strong>\u0418\u0442\u043e\u0433:<\/strong> PageObject \u043d\u0435 \u043f\u043b\u043e\u0445, \u043d\u043e \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u044b\u0442, \u0438 \u044d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043b\u0435\u0433\u043a\u043e.<\/p>\n<h4>2. PageObject \u0441\u0430\u043c \u043f\u043e \u0441\u0435\u0431\u0435 \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u0435\u043d<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code><strong>LoginPage<\/strong><\/code> \u0438\u043b\u0438 <code><strong>RegistrationPage<\/strong><\/code>, \u0442\u043e PageObject \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u0435\u043d. \u041d\u043e \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u043e\u0434\u043d\u043e\u0433\u043e PageObject \u0443\u0436\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u041e\u043d \u043d\u0435 \u0440\u0435\u0448\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Navbar<\/strong><\/a> \u0438\u043b\u0438 <a href=\"https:\/\/www.w3schools.com\/w3css\/w3css_sidebar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Sidebar<\/strong><\/a>?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c Allure \u0448\u0430\u0433\u0438 \u0432 \u043e\u0442\u0447\u0435\u0442\u044b?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/docs.python.org\/3\/library\/logging.html\" rel=\"noopener noreferrer nofollow\">\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/a>?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b?<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a PageComponent \u0438\u043b\u0438 PageFactory.<\/p>\n<h4>3. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0435<\/h4>\n<p>PageObject \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u0435\u043d \u043f\u0440\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0435 \u0438 \u0440\u0435\u0434\u0438\u0437\u0430\u0439\u043d\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446. \u0415\u0441\u043b\u0438 \u0437\u0430\u0432\u0442\u0440\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u044e\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u0442 \u0434\u0438\u0437\u0430\u0439\u043d, \u0442\u043e PageObject \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u042d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0442\u0430\u043a\u0436\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 UI \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h4>\u041f\u043b\u044e\u0441\u044b PageObject<\/h4>\n<h4>1. \u0423\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432<\/h4>\n<p>PageObject \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043a\u043e\u0440\u043e\u0447\u0435, \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u0435\u0435 \u0438 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PageObject \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0447\u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h4>2. \u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u044c<\/h4>\n<p>PageObject \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043a\u0440\u0443\u043f\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u0433\u0434\u0435 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0435\u0441\u0442\u0430\u0445, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h4>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h4>\n<p>PageObject \u2014 \u044d\u0442\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u043d\u043e \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 &#171;\u0443\u043c\u0435\u043b\u044b\u0445 \u0440\u0443\u043a\u0430\u0445&#187; \u0438 \u0432 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438. \u041e\u043d \u0438\u043c\u0435\u0435\u0442 \u043a\u0430\u043a \u043f\u043b\u044e\u0441\u044b, \u0442\u0430\u043a \u0438 \u043c\u0438\u043d\u0443\u0441\u044b, \u0438 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u043e\u0431\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0447\u0442\u043e\u0431\u044b \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/h2>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u043b\u0443\u0447\u0448\u0438\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432 \u2014 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9F%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%81%D1%80%D0%B5%D0%B4%D1%8B\" rel=\"noopener noreferrer nofollow\">.env<\/a><\/p>\n<\/li>\n<li>\n<p>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (<a href=\"https:\/\/docs.pydantic.dev\/latest\/api\/networks\/#pydantic.networks.HttpUrl\" rel=\"noopener noreferrer nofollow\">HttpUrl<\/a>, <a href=\"https:\/\/DirectoryPath\" rel=\"noopener noreferrer nofollow\">DirectoryPath<\/a>)<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0443\u044e, \u043d\u043e \u0433\u0438\u0431\u043a\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/docs.pydantic.dev\/latest\/concepts\/pydantic_settings\/#settings-management\" rel=\"noopener noreferrer nofollow\">pydantic-settings<\/a> \u2014 \u044d\u0442\u043e \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043d\u0430\u0434 <a href=\"https:\/\/docs.pydantic.dev\/latest\/\" rel=\"noopener noreferrer nofollow\">Pydantic<\/a>, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/p>\n<p>\u0412\u043e\u0442 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e:<\/p>\n<ul>\n<li>\n<p><code>app_url<\/code> \u2014 URL \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code>headless<\/code> \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0432 <a href=\"https:\/\/playwright.dev\/python\/docs\/debug#headed-mode\" rel=\"noopener noreferrer nofollow\">headless-\u0440\u0435\u0436\u0438\u043c\u0435<\/a> (\u0435\u0441\u043b\u0438 true, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f &#171;\u0432 \u0444\u043e\u043d\u0435&#187;, \u0431\u0435\u0437 UI \u2014 \u0443\u0434\u043e\u0431\u043d\u043e \u0434\u043b\u044f CI)<\/p>\n<\/li>\n<li>\n<p><code>videos_dir<\/code> \u2014 \u043f\u0443\u0442\u044c, \u043a\u0443\u0434\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432\u0438\u0434\u0435\u043e \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 (\u0435\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c)<\/p>\n<\/li>\n<li>\n<p><code>tracing_dir<\/code> \u2014 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 <a href=\"https:\/\/playwright.dev\/python\/docs\/trace-viewer-intro\" rel=\"noopener noreferrer nofollow\">Playwright Trace Viewer<\/a> (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 trace \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430)<\/p>\n<\/li>\n<li>\n<p><code>expect_timeout<\/code> \u2014 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 <a href=\"https:\/\/playwright.dev\/python\/docs\/test-assertions#list-of-assertions\" rel=\"noopener noreferrer nofollow\">expect()<\/a> \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/config.py\" rel=\"noopener noreferrer nofollow\"><strong>config.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from typing import Self  from pydantic import HttpUrl, DirectoryPath from pydantic_settings import BaseSettings, SettingsConfigDict   class Settings(BaseSettings):     \"\"\"     \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \u0412\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u0438\u0437 .env \u0444\u0430\u0439\u043b\u0430 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.      :param app_url: URL \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.     :param headless: \u0424\u043b\u0430\u0433 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0432 headless-\u0440\u0435\u0436\u0438\u043c\u0435.     :param videos_dir: \u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435\u043e.     :param tracing_dir: \u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f Playwright trace-\u0444\u0430\u0439\u043b\u043e\u0432.     :param expect_timeout: \u0422\u0430\u0439\u043c\u0430\u0443\u0442 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439 Playwright \u0432 \u043c\u0438\u043b\u043b\u0438\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445.     \"\"\"        model_config = SettingsConfigDict(         env_file='.env',  # \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 .env         env_file_encoding='utf-8',         env_nested_delimiter='.'  # \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f     )      app_url: HttpUrl     headless: bool     videos_dir: DirectoryPath     tracing_dir: DirectoryPath     expect_timeout: float      @classmethod     def initialize(cls) -&gt; Self:         \"\"\"         \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Settings. \u0415\u0441\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0434\u043b\u044f \u0432\u0438\u0434\u0435\u043e \u0438 \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433\u0430 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u2014 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u0445.          :return: \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 Settings         :raises ValueError: \u0435\u0441\u043b\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u0438\u043b\u0438 \u043d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u044b         \"\"\"         videos_dir = DirectoryPath(\".\/videos\")         tracing_dir = DirectoryPath(\".\/tracing\")          videos_dir.mkdir(exist_ok=True)         tracing_dir.mkdir(exist_ok=True)          return Settings(videos_dir=videos_dir, tracing_dir=tracing_dir) <\/code><\/pre>\n<h4>\u0412\u0430\u0436\u043d\u043e: \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u0435\u043d \u043c\u0435\u0442\u043e\u0434 initialize \u0438 \u0447\u0442\u043e \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442<\/h4>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>initialize()<\/code> \u2014 \u044d\u0442\u043e <a href=\"https:\/\/docs.python.org\/3\/library\/functions.html#classmethod\" rel=\"noopener noreferrer nofollow\">\u043a\u043b\u0430\u0441\u0441\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434<\/a> \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>Settings<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0436\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<p><strong>1. \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <\/strong><code><strong>Settings<\/strong><\/code><\/p>\n<p>\u041e\u043d \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0438\u0437:<\/p>\n<ul>\n<li>\n<p><code>.env<\/code> \u0444\u0430\u0439\u043b\u0430 (\u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c);<\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f (\u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 <code>.env<\/code> \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442).<\/p>\n<\/li>\n<\/ul>\n<p><strong>2. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 <\/strong><code><strong>videos<\/strong><\/code><strong> \u0438 <\/strong><code><strong>tracing<\/strong><\/code><strong> (\u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442)<\/strong><\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>Settings<\/code>, \u043c\u0435\u0442\u043e\u0434 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0434\u0432\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<\/p>\n<pre><code class=\"python\">videos_dir = DirectoryPath(\".\/videos\") tracing_dir = DirectoryPath(\".\/tracing\")  videos_dir.mkdir(exist_ok=True) tracing_dir.mkdir(exist_ok=True)<\/code><\/pre>\n<ul>\n<li>\n<p><code>videos_dir<\/code> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f <a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html#suites\/b68d2a345d8cf81f88c2c5d2f6385b38\/95cab185a5006e76\/\" rel=\"noopener noreferrer nofollow\">\u0432\u0438\u0434\u0435\u043e-\u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/a>.<\/p>\n<\/li>\n<li>\n<p><code>tracing_dir<\/code> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f <a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html#suites\/b68d2a345d8cf81f88c2c5d2f6385b38\/95cab185a5006e76\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0440\u0435\u0439\u0441\u043e\u0432 (\u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0445 \u043b\u043e\u0433\u043e\u0432)<\/a> \u043e\u0442 Playwright, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/playwright.dev\/python\/docs\/trace-viewer-intro\" rel=\"noopener noreferrer nofollow\">Trace Viewer<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u043d\u043e \u043f\u0440\u0438 <strong>\u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/strong>, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u0438\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0435\u0449\u0451 \u043d\u0435\u0442 \u0432 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435.<\/p>\n<h3>.env \u0444\u0430\u0439\u043b<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/.env\" rel=\"noopener noreferrer nofollow\">.env<\/a> \u0444\u0430\u0439\u043b \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c:<\/p>\n<pre><code>APP_URL=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\" HEADLESS=true EXPECT_TIMEOUT=15000<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>initialize()<\/code>:<\/p>\n<pre><code class=\"python\">settings = Settings.initialize()  print(settings.app_url) print(settings.headless)  print(settings.videos_dir)  print(settings.tracing_dir)  print(settings.expect_timeout) <\/code><\/pre>\n<p><strong>\u0412\u0430\u0436\u043d\u043e!<\/strong>\u00a0\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e\u00a0<code>settings<\/code>\u00a0\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u00a0\u043d\u0435 \u0431\u0443\u0434\u0435\u043c\u00a0\u2014 \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u00a0<code>settings<\/code>\u00a0\u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0444\u0438\u043a\u0441\u0442\u0443\u0440.<\/p>\n<h2>\u0424\u0438\u043a\u0441\u0442\u0443\u0440\u044b<\/h2>\n<p>\u0412 UI-\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u0440\u0430\u0439\u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0441\u044f \u0432 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0438, \u0441 \u0447\u0438\u0441\u0442\u044b\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0438\u043c\u0435\u043b \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b:<\/p>\n<ul>\n<li>\n<p><code><strong>chromium_page<\/strong><\/code>\u00a0\u2013 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 <a href=\"https:\/\/www.chromium.org\/chromium-projects\/\" rel=\"noopener noreferrer nofollow\">Chromium<\/a> \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c, \u0441 \u0432\u0438\u0434\u0435\u043e \u0438 \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><code><strong>registration_page<\/strong><\/code>\u00a0\u2013 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><code><strong>dashboard_page<\/strong><\/code> &#8212; \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430<\/p>\n<\/li>\n<li>\n<p><code><strong>settings<\/strong><\/code>\u00a0\u2013 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043d\u0430 \u0432\u0441\u044e \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 Pytest \u043f\u043b\u0430\u0433\u0438\u043d\u044b, \u0430 \u043d\u0435 conftest.py?<\/h4>\n<p>\u0414\u043b\u044f \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u00a0<a href=\"https:\/\/docs.pytest.org\/en\/7.1.x\/how-to\/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file\" rel=\"noopener noreferrer nofollow\">Pytest \u043f\u043b\u0430\u0433\u0438\u043d\u044b<\/a>. \u041f\u043b\u0430\u0433\u0438\u043d\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0438 \u0433\u0438\u0431\u0447\u0435, \u0447\u0435\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0438\u043a\u0441\u0442\u0443\u0440 \u0432\u00a0<a href=\"http:\/\/conftest.py\" rel=\"noopener noreferrer nofollow\">conftest.py<\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438\u00a0<a href=\"http:\/\/conftest.py\" rel=\"noopener noreferrer nofollow\">conftest.py<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u0424\u0438\u043a\u0441\u0442\u0443\u0440\u044b \u0438\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u0432\u043e \u0432\u0441\u0451\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u00a0<a href=\"http:\/\/conftest.py\" rel=\"noopener noreferrer nofollow\">conftest.py<\/a>\u00a0\u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0433\u0440\u0443\u043f\u043f \u0442\u0435\u0441\u0442\u043e\u0432. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u0430\u0439\u043b\u044b\u00a0<a href=\"http:\/\/conftest.py\" rel=\"noopener noreferrer nofollow\">conftest.py<\/a>\u00a0\u0440\u0430\u0437\u0440\u0430\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0434\u043e 1000+ \u0441\u0442\u0440\u043e\u043a, \u0447\u0442\u043e \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u044f\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/fixtures\/settings.py\" rel=\"noopener noreferrer nofollow\"><strong>\/fixtures\/settings.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import pytest  from config import Settings   @pytest.fixture(scope=\"session\") def settings() -&gt; Settings:     \"\"\"     \u0424\u0438\u043a\u0441\u0442\u0443\u0440\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043d\u0430 \u0432\u0441\u044e \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0441\u0435\u0441\u0441\u0438\u044e.      :return: \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 Settings \u0441 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043c\u0438.     \"\"\"     return Settings.initialize() <\/code><\/pre>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/fixtures\/pages.py\" rel=\"noopener noreferrer nofollow\"><strong>\/fixtures\/pages.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import uuid  import allure import pytest from playwright.sync_api import Playwright, Page, expect  from config import Settings from pages.dashboard_page import DashboardPage from pages.registration_page import RegistrationPage   @pytest.fixture def chromium_page(playwright: Playwright, settings: Settings) -&gt; Page:     \"\"\"     \u0424\u0438\u043a\u0441\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 Chromium \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.      - \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b `settings`.     - \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439.     - \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0432\u0438\u0434\u0435\u043e \u0438 \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433\u0430 (screenshots, snapshots, source).     - \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430:         - \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0442\u0440\u0435\u0439\u0441 \u0432 `settings.tracing_dir`;         - \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u0442 \u0432\u0438\u0434\u0435\u043e \u0438 \u0442\u0440\u0435\u0439\u0441 \u043a Allure-\u043e\u0442\u0447\u0435\u0442\u0443;         - \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440.      :param playwright: \u041e\u0431\u044a\u0435\u043a\u0442 Playwright, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0439 pytest-playwright.     :param settings: \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.     :yield: \u041d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 `Page` \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430.     \"\"\"     expect.set_options(timeout=settings.expect_timeout)      browser = playwright.chromium.launch(headless=settings.headless)     context = browser.new_context(         base_url=f\"{settings.app_url}\/\",         record_video_dir=settings.videos_dir     )     context.tracing.start(screenshots=True, snapshots=True, sources=True)      page = context.new_page()     yield page      tracing_file = settings.tracing_dir.joinpath(f'{uuid.uuid4()}.zip')     context.tracing.stop(path=tracing_file)     browser.close()      allure.attach.file(tracing_file, name='trace', extension='zip')     allure.attach.file(page.video.path(), name='video', attachment_type=allure.attachment_type.WEBM)   @pytest.fixture def dashboard_page(chromium_page: Page) -&gt; DashboardPage:     \"\"\"     \u0424\u0438\u043a\u0441\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430.      :param chromium_page: \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 Chromium, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0430\u044f \u0447\u0435\u0440\u0435\u0437 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0443.     :return: \u041e\u0431\u044a\u0435\u043a\u0442 `DashboardPage` \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.     \"\"\"     return DashboardPage(page=chromium_page)   @pytest.fixture def registration_page(chromium_page: Page) -&gt; RegistrationPage:     \"\"\"     \u0424\u0438\u043a\u0441\u0442\u0443\u0440\u0430 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.      :param chromium_page: \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 Chromium, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0430\u044f \u0447\u0435\u0440\u0435\u0437 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0443.     :return: \u041e\u0431\u044a\u0435\u043a\u0442 `RegistrationPage` \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.     \"\"\"     return RegistrationPage(page=chromium_page) <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u043b\u0438\u0441\u044c \u0432\u043e \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u043e\u0447\u043a\u0443 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u0444\u0430\u0439\u043b <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/conftest.py\" rel=\"noopener noreferrer nofollow\">conftest.py<\/a>:<\/p>\n<pre><code class=\"python\">pytest_plugins = (     \"fixtures.pages\",     \"fixtures.settings\" )<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b <code>settings<\/code>, <code>chromium_page<\/code>, <code>registration_page<\/code>, <code>dashboard_page<\/code> \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e.<\/p>\n<h2>App routes<\/h2>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f URL-\u0440\u043e\u0443\u0442\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 \u0432\u044b\u043d\u0435\u0441\u0435\u043c \u0432\u0441\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <a href=\"https:\/\/docs.python.org\/3\/library\/enum.html\" rel=\"noopener noreferrer nofollow\">Enum<\/a>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442:<\/p>\n<ul>\n<li>\n<p>\u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a \u0441 \u043f\u0443\u0442\u044f\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432 IDE \u0438 \u043f\u043e\u0432\u044b\u0441\u0438\u0442\u044c \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/tools\/routes.py\" rel=\"noopener noreferrer nofollow\"><strong>\/tools\/routes.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">from enum import Enum   class AppRoute(str, Enum):     \"\"\"     Enum \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.     \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 str, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438.      \u041f\u0440\u0438\u043c\u0435\u0440\u044b:     - \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u0432 \u0442\u0435\u0441\u0442\u0430\u0445;     - \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e URL;     - \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u044b.     \"\"\"     LOGIN = \".\/#\/auth\/login\"  # \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u0445\u043e\u0434\u0430     REGISTRATION = \".\/#\/auth\/registration\"  # \u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438      DASHBOARD = \".\/#\/dashboard\"  # \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 (\u0434\u0430\u0448\u0431\u043e\u0440\u0434)      COURSES = \".\/#\/courses\"  # \u0421\u043f\u0438\u0441\u043e\u043a \u043a\u0443\u0440\u0441\u043e\u0432     COURSES_CREATE = \".\/#\/courses\/create\"  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430 <\/code><\/pre>\n<h2>UI \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u0443\u044e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0422\u0435\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/pages\" rel=\"noopener noreferrer nofollow\">PageObject<\/a>, <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/components\" rel=\"noopener noreferrer nofollow\">PageComponent<\/a>, <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/elements\" rel=\"noopener noreferrer nofollow\">PageFactory<\/a> \u2014 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/fixtures\" rel=\"noopener noreferrer nofollow\">\u0424\u0438\u043a\u0441\u0442\u0443\u0440\u044b<\/a> \u2014 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a (\u0447\u0435\u0440\u0435\u0437 pytest).<\/p>\n<\/li>\n<\/ul>\n<h4>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0442\u0435\u0441\u0442\u0430<\/h4>\n<ol>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/auth\/registration\" rel=\"noopener noreferrer nofollow\">#\/auth\/registration<\/a><\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: <code>Email<\/code>, <code>Username<\/code>, <code>Password<\/code><\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 Registration<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u043b\u0441\u044f Dashboard: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/dashboard\" rel=\"noopener noreferrer nofollow\">#\/dashboard<\/a><\/p>\n<\/li>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430 Dashboard \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b: <code>Navbar<\/code>, <code>Toolbar<\/code>, \u0413\u0440\u0430\u0444\u0438\u043a\u0438: <code>Scores<\/code>, <code>Courses<\/code>, <code>Students<\/code>, <code>Activities<\/code><\/p>\n<\/li>\n<\/ol>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/tests\/test_registration.py\" rel=\"noopener noreferrer nofollow\"><strong>\/tests\/test_registration.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import allure import pytest  from pages.dashboard_page import DashboardPage from pages.registration_page import RegistrationPage from tools.routes import AppRoute   @pytest.mark.regression @pytest.mark.registration class TestRegistration:     @allure.title(\"Successful registration\")     def test_successful_registration(             self,             dashboard_page: DashboardPage,             registration_page: RegistrationPage     ):         # 1. \u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438         registration_page.visit(AppRoute.REGISTRATION)                  # 2. \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430, \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f         registration_page.registration_form.check_visible(email=\"\", username=\"\", password=\"\")                  # 3. \u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438         registration_page.registration_form.fill(             email=\"user@example.com\",             username=\"Playwright\",             password=\"qwerty\"         )          # 4. \u041a\u043b\u0438\u043a \u043f\u043e \u043a\u043d\u043e\u043f\u043a\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438         registration_page.click_registration_button()          # 5. \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 Dashboard         dashboard_page.navbar.check_visible(\"Playwright\")  # Navbar \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f         dashboard_page.dashboard_toolbar_view.check_visible()  # Toolbar \u043d\u0430 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435         dashboard_page.check_visible_scores_chart()  # \u0413\u0440\u0430\u0444\u0438\u043a \u043e\u0446\u0435\u043d\u043e\u043a         dashboard_page.check_visible_courses_chart()  # \u0413\u0440\u0430\u0444\u0438\u043a \u043a\u0443\u0440\u0441\u043e\u0432         dashboard_page.check_visible_students_chart()  # \u0413\u0440\u0430\u0444\u0438\u043a \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432         dashboard_page.check_visible_activities_chart()  # \u0413\u0440\u0430\u0444\u0438\u043a \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 <\/code><\/pre>\n<ul>\n<li>\n<p><code>@pytest.mark.regression<\/code> \u0438 <code>@pytest.mark.registration<\/code> \u2014 \u043c\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><code>@allure.title<\/code> \u2014 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0451\u043d \u0432 <a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html#suites\/b68d2a345d8cf81f88c2c5d2f6385b38\/95cab185a5006e76\/\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u0447\u0451\u0442\u0435 Allure<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b <code>dashboard_page<\/code> \u0438 <code>registration_page<\/code> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/docs.pytest.org\/en\/stable\/\" rel=\"noopener noreferrer nofollow\">pytest<\/a>, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f <a href=\"https:\/\/docs.pytest.org\/en\/7.1.x\/how-to\/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file\" rel=\"noopener noreferrer nofollow\">pytest-\u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c<\/a>.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0412\u0430\u0436\u043d\u043e!<\/h4>\n<p>\u0421\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0447\u0438\u0441\u0442\u044b\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 UI \u0442\u0435\u0441\u0442\u044b \u2014 \u0431\u0435\u0437 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e &#171;\u0448\u0443\u043c\u0430&#187; \u0432 \u0432\u0438\u0434\u0435 \u0440\u0443\u0447\u043d\u044b\u0445 Allure \u0448\u0430\u0433\u043e\u0432, \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043b\u0438\u0448\u043d\u0435\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439.<\/p>\n<p>\u0412\u0435\u0441\u044c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c PageObject, PageComponent \u0438 PageFactory, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0421\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u044e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e \u043a\u0443\u0445\u043d\u044e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 UI;<\/p>\n<\/li>\n<li>\n<p>\u0421\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0424\u043e\u043a\u0443\u0441 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u043c \u2014 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0447\u0438\u0442\u0430\u0435\u043c \u0442\u0435\u0441\u0442, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:<\/p>\n<blockquote>\n<p>\u201c\u0427\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0438 \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441\u201d.<\/p>\n<\/blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u0435\u0441\u0442\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u042f\u0432\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 Allure (<code>allure.step(...)<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (<code>print<\/code>,<code> logger.info<\/code>, <code>loguru<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u0441\u0442\u0440\u0430\u043d\u0438\u0446, \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044b \u0438\u043b\u0438 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438&#8230;<\/p>\n<\/li>\n<\/ul>\n<p>\u2026\u0442\u0435\u0441\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0442\u0435\u0440\u044f\u0435\u0442 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0442\u044f\u0436\u0435\u043b\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c. \u0412 \u0442\u0430\u043a\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f &#171;\u043a\u043e\u0441\u0442\u044b\u043b\u0438&#187;, \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0434\u0443\u0431\u043b\u0438, \u0442\u0435\u0441\u0442\u044b \u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f \u043e\u0442 \u043c\u0430\u043b\u0435\u0439\u0448\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0430 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u043e\u043b\u044c.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u0441\u0442 \u2014 \u044d\u0442\u043e \u043a\u043e\u0433\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u0412\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c;<\/p>\n<\/li>\n<li>\n<p>\u041b\u0435\u0433\u043a\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0448\u0430\u0433.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041c\u0430\u0441\u0448\u0442\u0430\u0431 \u0432\u0430\u0436\u0435\u043d<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 5 \u0442\u0435\u0441\u0442\u043e\u0432 \u2014 \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0438\u0445 \u0445\u043e\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u0431\u0435\u0437 \u0444\u0438\u043a\u0441\u0442\u0443\u0440, \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440. \u041d\u043e \u0442\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u2014 \u0440\u0435\u0434\u043a\u043e\u0441\u0442\u044c. \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435:<\/p>\n<ul>\n<li>\n<p>UI-\u0442\u0435\u0441\u0442\u043e\u0432 \u043e\u0431\u044b\u0447\u043d\u043e <strong>\u0441\u043e\u0442\u043d\u0438<\/strong>;<\/p>\n<\/li>\n<li>\n<p>API-\u0442\u0435\u0441\u0442\u043e\u0432 \u2014 <strong>\u0442\u044b\u0441\u044f\u0447\u0438<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0442\u0430\u043a\u0438\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u044b.<\/p>\n<h4>\u0423\u0434\u043e\u0431\u043d\u0430\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0430 \u0447\u0435\u0440\u0435\u0437 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c\u0443 <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/tools\/logger.py\" rel=\"noopener noreferrer nofollow\">\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e<\/a>, \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0435\u0441\u0442 \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041f\u0440\u0438\u043c\u0435\u0440 \u043b\u043e\u0433\u043e\u0432:<\/p>\n<pre><code>2025-04-03 23:35:25,613 | INPUT | INFO | Checking that input \"Password\" has a value \"qwerty\" 2025-04-03 23:35:25,619 | BASE_ELEMENT | INFO | Getting locator with \"data-testid=registration-page-registration-button\" at index \"0\" 2025-04-03 23:35:25,619 | BASE_ELEMENT | INFO | Clicking button \"Registration\" 2025-04-03 23:35:25,706 | BASE_PAGE | INFO | Checking that current url matches pattern \".*\/#\/dashboard\" 2025-04-03 23:35:25,790 | BASE_ELEMENT | INFO | Getting locator with \"data-testid=navigation-navbar-app-title-text\" at index \"0\"<\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0439 \u0432\u044b\u0432\u043e\u0434:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0451\u043b \u0441\u0431\u043e\u0439;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\/runs\/14263322844\/job\/39979568202\" rel=\"noopener noreferrer nofollow\">CI-\u043f\u0440\u043e\u0433\u043e\u043d\u0435<\/a>, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f pytest-\u043c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043e\u043a<\/h4>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c pytest-\u043c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0432\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/pytest.ini\" rel=\"noopener noreferrer nofollow\"><strong>pytest.ini<\/strong><\/a>, \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435.<\/p>\n<pre><code>[pytest] addopts = -s -v python_files = *_tests.py test_*.py python_classes = Test* python_functions = test_* markers =     regression: \u041c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0434\u043b\u044f \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u043e\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432.     registration: \u041c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0445 \u0441 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/code><\/pre>\n<h2>\u0417\u0430\u043f\u0443\u0441\u043a \u043d\u0430 CI\/CD<\/h2>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u043c\u00a0<a href=\"https:\/\/docs.github.com\/en\/actions\/writing-workflows\/quickstart\" rel=\"noopener noreferrer nofollow\">workflow-\u0444\u0430\u0439\u043b<\/a>\u00a0\u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 UI-\u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u00a0<a href=\"https:\/\/github.com\/features\/actions\" rel=\"noopener noreferrer nofollow\">GitHub Actions<\/a>, \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438\u00a0<a href=\"https:\/\/allurereport.org\/\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0435\u0442\u0430<\/a>\u00a0\u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0435\u0433\u043e \u043d\u0430\u00a0<a href=\"https:\/\/pages.github.com\/\" rel=\"noopener noreferrer nofollow\">GitHub Pages<\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/.github\/workflows\/test.yml\" rel=\"noopener noreferrer nofollow\"><strong>\/.github\/workflows\/test.yml<\/strong><\/a><\/p>\n<pre><code class=\"yaml\">name: UI tests  # \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 workflow, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 GitHub Actions  on:   push:     branches:       - main  # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c workflow \u043f\u0440\u0438 \u043f\u0443\u0448\u0435 \u0432 \u0432\u0435\u0442\u043a\u0443 main   pull_request:     branches:       - main  # \u0418 \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 pull request'\u0430 \u0432 main  jobs:   run-tests:  # \u0414\u0436\u043e\u0431 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432     runs-on: ubuntu-latest  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0432\u0435\u0440\u0441\u0438\u044e Ubuntu \u043a\u0430\u043a CI-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435      steps:       - name: Check out repository         uses: actions\/checkout@v4  # \u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 CI-\u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435        - name: Set up Python         uses: actions\/setup-python@v5  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Python         with:           python-version: '3.12'  # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0435\u0440\u0441\u0438\u044e Python        - name: Install dependencies         run: |           python -m pip install --upgrade pip  # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c pip           pip install -r requirements.txt  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430           playwright install --with-deps  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Playwright \u0438 \u0435\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438        - name: Run UI tests with pytest and generate Allure results         run: |           pytest -m regression --alluredir=allure-results --numprocesses 2           # \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0441 \u043c\u0435\u0442\u043a\u043e\u0439 \"regression\"           # --alluredir=allure-results \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432 \u043f\u0430\u043f\u043a\u0443 allure-results           # --numprocesses 2 - \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0432 2 \u043f\u043e\u0442\u043e\u043a\u0430 (\u0443\u0441\u043a\u043e\u0440\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435)        - name: Upload Allure results         if: always()  # \u0412\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c (\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0448\u0430\u0433 \u0443\u043f\u0430\u043b)         uses: actions\/upload-artifact@v4  # \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442 \u0432 CI         with:           name: allure-results  # \u0418\u043c\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430           path: allure-results  # \u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 Allure    publish-report:  # \u0414\u0436\u043e\u0431 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442\u0447\u0451\u0442\u0430     needs: [ run-tests ]  # \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e (\u0438\u043b\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u043e\u0433\u043e) run-tests     runs-on: ubuntu-latest  # \u0422\u043e\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 Ubuntu      steps:       - name: Check out repository         uses: actions\/checkout@v4  # \u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439         with:           ref: gh-pages  # \u041a\u043b\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0432\u0435\u0442\u043a\u0443 gh-pages           path: gh-pages  # \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0443\u0442\u044c, \u043a\u0443\u0434\u0430 \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c        - name: Download Allure results         uses: actions\/download-artifact@v4  # \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b         with:           name: allure-results  # \u0418\u043c\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430           path: allure-results  # \u041f\u0443\u0442\u044c \u043a\u0443\u0434\u0430 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c        - name: Allure Report action from marketplace         uses: simple-elf\/allure-report-action@v1.12  # \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c Allure-\u043e\u0442\u0447\u0451\u0442         if: always()  # \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0435         with:           allure_results: allure-results  # \u041f\u0443\u0442\u044c \u043a \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c           allure_history: allure-history  # \u041f\u0430\u043f\u043a\u0430 \u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u043e\u0442\u0447\u0451\u0442\u043e\u0432 (\u0434\u043b\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0432 \u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f)        - name: Deploy report to Github Pages         if: always()  # \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0448\u0430\u0433\u0438 \u0443\u043f\u0430\u043b\u0438         uses: peaceiris\/actions-gh-pages@v4  # \u0414\u0435\u043f\u043b\u043e\u0439 \u043d\u0430 GitHub Pages         with:           github_token: ${{ secrets.GITHUB_TOKEN }}  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 GitHub \u0442\u043e\u043a\u0435\u043d           publish_branch: gh-pages  # \u0412\u0435\u0442\u043a\u0430 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043e\u0442\u0447\u0451\u0442\u0430           publish_dir: allure-history  # \u041f\u0430\u043f\u043a\u0430 \u0441 \u0433\u043e\u0442\u043e\u0432\u044b\u043c HTML \u043e\u0442\u0447\u0451\u0442\u043e\u043c <\/code><\/pre>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 actions \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0438\u0436\u0435:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/marketplace?type=actions\" rel=\"noopener noreferrer nofollow\">GitHub Actions Marketplace<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/actions\/setup-python\" rel=\"noopener noreferrer nofollow\">GitHub Action \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 python<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/actions\/checkout\" rel=\"noopener noreferrer nofollow\">GitHub Action \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/actions\/upload-artifact\" rel=\"noopener noreferrer nofollow\">GitHub Action \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/actions\/download-artifact\" rel=\"noopener noreferrer nofollow\">GitHub Action \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/simple-elf\/allure-report-action\" rel=\"noopener noreferrer nofollow\">GitHub Actioin \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 Allure \u043e\u0442\u0447\u0435\u0442\u0430 \u0441 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0438\u0441\u0442\u043e\u0440\u0438\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/peaceiris\/actions-gh-pages\" rel=\"noopener noreferrer nofollow\">GitHubActions \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 GitHub Pages<\/a><\/p>\n<\/li>\n<\/ul>\n<h4>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u043b\u044f Workflow<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 GitHub Actions \u0442\u043e, \u0431\u0443\u0434\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430, \u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0430\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0443 github token \u0438\u0437 workflow \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0435\u0442 \u043f\u0440\u0430\u0432 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0442\u044c \u0432 \u0440\u0435\u043f\u0437\u043e\u0438\u0442\u043e\u0440\u0438\u0439<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24d\/f9a\/420\/24df9a420e2f4372e3b572726e9d17e9.png\" width=\"1968\" height=\"90\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/24d\/f9a\/420\/24df9a420e2f4372e3b572726e9d17e9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24d\/f9a\/420\/24df9a420e2f4372e3b572726e9d17e9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0430\u0432 workflow:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443\u00a0Settings\u00a0\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 GitHub.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c6a\/329\/4cc\/c6a3294ccb27a566b3e284c88fa8503f.png\" width=\"3024\" height=\"248\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c6a\/329\/4cc\/c6a3294ccb27a566b3e284c88fa8503f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c6a\/329\/4cc\/c6a3294ccb27a566b3e284c88fa8503f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u00a0Actions\u00a0\u2192\u00a0General.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dae\/bf9\/898\/daebf9898c4b50d45b6f4746abb66f33.png\" width=\"690\" height=\"208\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/dae\/bf9\/898\/daebf9898c4b50d45b6f4746abb66f33.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/dae\/bf9\/898\/daebf9898c4b50d45b6f4746abb66f33.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u043a\u0440\u0443\u0442\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u043d\u0438\u0437 \u0434\u043e \u0431\u043b\u043e\u043a\u0430\u00a0Workflow permissions.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u043f\u0446\u0438\u044e\u00a0Read and write permissions.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443\u00a0Save\u00a0\u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/374\/394\/530\/3743945307efbb4caf6004daa0afd349.png\" width=\"1560\" height=\"622\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/374\/394\/530\/3743945307efbb4caf6004daa0afd349.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/374\/394\/530\/3743945307efbb4caf6004daa0afd349.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0448\u0430\u0433\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0434 \u0441 UI-\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0432 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<\/p>\n<h4>\u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Allure-\u043e\u0442\u0447\u0451\u0442\u0430<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432\u043e \u0432\u043a\u043b\u0430\u0434\u043a\u0435\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\" rel=\"noopener noreferrer nofollow\">Actions<\/a>\u00a0\u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\/runs\/14263322844\" rel=\"noopener noreferrer nofollow\">workflow<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u044f\u0442\u0441\u044f \u0442\u0435\u0441\u0442\u044b.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5c9\/0af\/7f1\/5c90af7f130eb6440feb1648e9e007b0.png\" width=\"3024\" height=\"906\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5c9\/0af\/7f1\/5c90af7f130eb6440feb1648e9e007b0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5c9\/0af\/7f1\/5c90af7f130eb6440feb1648e9e007b0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0439\u0434\u0443\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e,\u00a0<a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442<\/a>\u00a0\u0431\u0443\u0434\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0432 \u0432\u0435\u0442\u043a\u0443\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/gh-pages\" rel=\"noopener noreferrer nofollow\">gh-pages<\/a>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f workflow\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\/runs\/14338928833\" rel=\"noopener noreferrer nofollow\">pages build and deployment<\/a>. \u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u00a0<a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442<\/a>\u00a0\u043d\u0430 GitHub Pages, \u0434\u0435\u043b\u0430\u044f \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e!<\/strong>\u00a0\u041f\u0435\u0440\u0435\u0434 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c workflow \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0435\u0442\u043a\u0430\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/gh-pages\" rel=\"noopener noreferrer nofollow\">gh-pages<\/a>. \u0415\u0441\u043b\u0438 \u0432\u0435\u0442\u043a\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0435\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0438\u043d\u0430\u0447\u0435 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f\u00a0<a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442\u0430<\/a>\u00a0\u043d\u0430 GitHub Pages \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<h4>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a GitHub Pages<\/h4>\n<p>\u0415\u0441\u043b\u0438 workflow\u00a0pages <a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\/runs\/14338928833\" rel=\"noopener noreferrer nofollow\">build and deployment<\/a>\u00a0\u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0441\u044f, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 GitHub Pages:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443\u00a0Settings\u00a0\u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u00a0Pages\u00a0\u2192\u00a0Build and deployment.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u044d\u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u0438\u0434\u0436\u0435\u0442 \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u043e\u0439 \u043d\u0430 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442.<\/a><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/398\/c8a\/1a9\/398c8a1a927994b7b6e5f2c66ff9b0e8.png\" width=\"3024\" height=\"1250\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/398\/c8a\/1a9\/398c8a1a927994b7b6e5f2c66ff9b0e8.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/398\/c8a\/1a9\/398c8a1a927994b7b6e5f2c66ff9b0e8.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h4>\u0414\u043e\u0441\u0442\u0443\u043f \u043a Allure-\u043e\u0442\u0447\u0451\u0442\u0430\u043c<\/h4>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u0447\u0451\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f \u043d\u0430 GitHub Pages \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c workflow, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d \u0431\u044b\u043b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 Allure-\u043e\u0442\u0447\u0451\u0442\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0432\u0435\u0442\u043a\u0435\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/gh-pages\" rel=\"noopener noreferrer nofollow\">gh-pages<\/a>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u044f \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 GitHub Pages, \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439\u00a0<a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442<\/a>\u00a0\u0441 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/41b\/95f\/1e2\/41b95f1e2bd9c515d0babe018a7da0cb.png\" width=\"3024\" height=\"918\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/41b\/95f\/1e2\/41b95f1e2bd9c515d0babe018a7da0cb.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/41b\/95f\/1e2\/41b95f1e2bd9c515d0babe018a7da0cb.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443, \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043d\u043e\u0432\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u00a0<a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0451\u0442<\/a>\u00a0\u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bd2\/f52\/c59\/bd2f52c59d9b9a8b65480f51a89f51e3.png\" width=\"3024\" height=\"1496\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/bd2\/f52\/c59\/bd2f52c59d9b9a8b65480f51a89f51e3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bd2\/f52\/c59\/bd2f52c59d9b9a8b65480f51a89f51e3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0443 \u0441 PageFactory \u0438 \u0447\u0451\u0442\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 PageObject\/PageComponent, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 Allure-\u043e\u0442\u0447\u0451\u0442\u0435 \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c <code>@allure.step<\/code>.<\/p>\n<p>\u041a\u0430\u0436\u0434\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0448\u0430\u0433\u043e\u0432. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0442\u0447\u0451\u0442\u044b \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u043c\u0438 <strong>\u043d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u2014 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0435 \u0431\u0438\u0437\u043d\u0435\u0441-\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0448\u0430\u0433\u043e\u0432, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044e \u0442\u0435\u0441\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0438\u0438 \u2014 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438: \u043a\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f, \u043a\u0430\u043a\u043e\u0439 \u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u043b\u0441\u044f \u0438 \u0441 \u043a\u0430\u043a\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c \u043e\u043d \u0438\u0441\u043a\u0430\u043b\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/95e\/84c\/bd9\/95e84cbd988702dc8d09f48e3ab64bbe.png\" width=\"3024\" height=\"1498\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/95e\/84c\/bd9\/95e84cbd988702dc8d09f48e3ab64bbe.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/95e\/84c\/bd9\/95e84cbd988702dc8d09f48e3ab64bbe.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u0448\u0430\u0433\u0430\u043c, \u0432 Allure-\u043e\u0442\u0447\u0451\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u0412\u0438\u0434\u0435\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432 \u043e\u0442\u0447\u0451\u0442\u0435. \u042d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0438 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0430\u0433\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0410\u0440\u0445\u0438\u0432 trace (<code>.zip<\/code>), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e <strong>\u0441\u043a\u0430\u0447\u0430\u0442\u044c<\/strong> \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 <a href=\"https:\/\/trace.playwright.dev\/\" rel=\"noopener noreferrer nofollow\">Playwright Trace Viewer<\/a> \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0442\u0435\u0441\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/29e\/503\/c26\/29e503c2663a5fdd21438acada6cde69.png\" width=\"3022\" height=\"1494\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/29e\/503\/c26\/29e503c2663a5fdd21438acada6cde69.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/29e\/503\/c26\/29e503c2663a5fdd21438acada6cde69.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><a href=\"https:\/\/playwright.dev\/python\/docs\/trace-viewer-intro\" rel=\"noopener noreferrer nofollow\">Trace Viewer<\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: DOM-\u0441\u043d\u0438\u043c\u043a\u0438, \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u043f\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c, \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u0434\u0440\u0443\u0433\u043e\u0435.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/188\/dd6\/eb3\/188dd6eb384c0031f499136248aa97ab.png\" width=\"3024\" height=\"1492\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/188\/dd6\/eb3\/188dd6eb384c0031f499136248aa97ab.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/188\/dd6\/eb3\/188dd6eb384c0031f499136248aa97ab.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u0441\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043a\u043e\u0434, \u043e\u0442\u0447\u0435\u0442\u044b \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 CI\/CD \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 \u043c\u043e\u0435\u043c\u00a0<a href=\"https:\/\/github.com\/Nikita-Filonov\" rel=\"noopener noreferrer nofollow\">GitHub<\/a>:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\" rel=\"noopener noreferrer nofollow\">\u041f\u0440\u043e\u0435\u043a\u0442 \u0441 UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u0430\u043c\u0438<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/nikita-filonov.github.io\/python-ui-tests\/13\/index.html\" rel=\"noopener noreferrer nofollow\">Allure-\u043e\u0442\u0447\u0435\u0442 \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/actions\" rel=\"noopener noreferrer nofollow\">CI\/CD \u0437\u0430\u043f\u0443\u0441\u043a\u0438 UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/896936\/\"> https:\/\/habr.com\/ru\/articles\/896936\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u043a\u0430\u043a \u043f\u0438\u0441\u0430\u0442\u044c UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u043d\u0430 Python, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u0438 \u043b\u0443\u0447\u0448\u0438\u0435 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a PageObject, PageComponent \u0438 PageFactory, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u044f, \u043a\u043e\u0433\u0434\u0430 \u0438 \u0437\u0430\u0447\u0435\u043c \u043e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0447\u0435\u043c \u043e\u043d\u0438 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430.<\/p>\n<p>\u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u044d\u0442\u0438\u043c\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430\u043c\u0438, \u0430 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u00ab\u043d\u0430 \u0430\u0442\u043e\u043c\u044b\u00bb \u0438 \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c, \u043a\u0430\u043a \u043e\u043d\u0438 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/auth\/login\" rel=\"noopener noreferrer nofollow\"><strong>UI Course<\/strong><\/a>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f UI \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 \u043c\u043e\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 GitHub: <a href=\"https:\/\/github.com\/Nikita-Filonov\/qa-automation-engineer-ui-course\" rel=\"noopener noreferrer nofollow\">UI Course GitHub<\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/CI\/CD\" rel=\"noopener noreferrer nofollow\">CI\/CD<\/a> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/features\/actions\" rel=\"noopener noreferrer nofollow\"><strong>GitHub Actions<\/strong><\/a>, \u043d\u043e \u0432\u0441\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043f\u043e\u0434 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <a href=\"https:\/\/www.jenkins.io\/\" rel=\"noopener noreferrer nofollow\">Jenkins<\/a>, <a href=\"https:\/\/docs.gitlab.com\/ci\/\" rel=\"noopener noreferrer nofollow\">GitLab CI<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/circleci.com\/\" rel=\"noopener noreferrer nofollow\">CircleCI<\/a> \u2014 \u043e\u0442\u043b\u0438\u0447\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043a\u0430\u0441\u0430\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432.<\/p>\n<h2>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043a\u0430\u043a\u043e\u0439 \u0438\u043c\u0435\u043d\u043d\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u041d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u0432\u044b\u0431\u0435\u0440\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432, \u0430 \u043d\u0435 \u043d\u0430 \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b PageObject, PageComponent \u0438 PageFactory \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435.<\/p>\n<p>\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0433\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/auth\/registration\" rel=\"noopener noreferrer nofollow\">\/#\/auth\/registration<\/a><\/p>\n<\/li>\n<li>\n<p>\u0412\u0432\u043e\u0434 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f: <code>Email<\/code>, <code>Username<\/code>, <code>Password<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0436\u0430\u0442\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 <strong>&#171;Registration&#187;<\/strong> \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 <strong>&#171;Dashboard&#187;<\/strong>: <a href=\"https:\/\/nikita-filonov.github.io\/qa-automation-engineer-ui-course\/#\/dashboard\" rel=\"noopener noreferrer nofollow\">\/#\/dashboard<\/a><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0432\u0441\u0435\u0445 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <strong>&#171;Dashboard&#187;.<\/strong><\/p>\n<\/li>\n<\/ol>\n<h2>\u0422\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer nofollow\"><strong>Python 3.12<\/strong><\/a>\u00a0\u2014 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\"><strong>Playwright<\/strong><\/a> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 UI.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.pytest.org\/en\/stable\/\" rel=\"noopener noreferrer nofollow\"><strong>Pytest<\/strong><\/a>\u00a0\u2014 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/python\/docs\/intro\" rel=\"noopener noreferrer nofollow\"><strong>Pytest Playwright<\/strong><\/a> \u2014 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f Playwright \u0441 pytest, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u0441 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u0430\u043c\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 Playwright.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.pydantic.dev\/latest\/concepts\/pydantic_settings\/\" rel=\"noopener noreferrer nofollow\"><strong>Pydantic Settings<\/strong><\/a> \u2014 \u0443\u0434\u043e\u0431\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 <code>.env<\/code> \u0444\u0430\u0439\u043b\u044b.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/allurereport.org\/\" rel=\"noopener noreferrer nofollow\"><strong>Allure<\/strong><\/a>\u00a0\u2014 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0447\u0451\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 Playwright, \u0430 \u043d\u0435 Selenium?<\/h4>\n<p>\u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u0431\u043e\u0440 \u043c\u0435\u0436\u0434\u0443 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0438 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u2014 \u044d\u0442\u043e \u0432\u044b\u0431\u043e\u0440 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0441\u0442\u044c\u044e \u0438 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Playwright.<\/p>\n<p><strong>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 Playwright:<\/strong><\/p>\n<ul>\n<li>\n<p><strong>\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438 \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0441\u0442\u044c.<\/strong> <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/chromedevtools.github.io\/devtools-protocol\/\" rel=\"noopener noreferrer nofollow\">DevTools Protocol<\/a>, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u043b\u043e\u0439\u043a\u0443 <a href=\"https:\/\/www.selenium.dev\/documentation\/webdriver\/\" rel=\"noopener noreferrer nofollow\">WebDriver<\/a>. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 Playwright \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u043c\u0435\u043d\u0435\u0435 \u043f\u043e\u0434\u0432\u0435\u0440\u0436\u0435\u043d\u043d\u044b\u043c \u0444\u043b\u0430\u043a\u0438-\u0442\u0435\u0441\u0442\u0430\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430.<\/strong> \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u2014 \u044d\u0442\u043e \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e <a href=\"https:\/\/playwright.dev\/python\/docs\/intro\" rel=\"noopener noreferrer nofollow\">\u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b<\/a>: <code>pip install playwright pytest-playwright<\/code>, <code>playwright install<\/code>. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u0432\u0441\u0451 \u043a\u0443\u0434\u0430 \u0441\u043b\u043e\u0436\u043d\u0435\u0435: \u043d\u0443\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0438\u0434\u0435\u043e \u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b &#171;\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438&#187;.<\/strong> Playwright <a href=\"https:\/\/playwright.dev\/python\/docs\/videos\" rel=\"noopener noreferrer nofollow\">\u0443\u043c\u0435\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0435\u043e<\/a> \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u042d\u0442\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043e\u0442\u043b\u0430\u0434\u043a\u0443.<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f.<\/strong> \u041a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 Playwright \u0443\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f (waits). \u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0438 \u201c\u043a\u043e\u0441\u0442\u044b\u043b\u0438\u201d, \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u043e \u0431\u044b\u0432\u0430\u0435\u0442 \u0432 Selenium.<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/playwright.dev\/docs\/trace-viewer\" rel=\"noopener noreferrer nofollow\"><strong>Playwright Trace Viewer.<\/strong><\/a> \u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0433 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u0438 CI-\u043e\u0448\u0438\u0431\u043a\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c.<\/strong> Playwright \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"https:\/\/docs.python.org\/3\/library\/asyncio.html\" rel=\"noopener noreferrer nofollow\">asyncio<\/a>), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b. \u0415\u0441\u0442\u044c \u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u043e\u0431\u0451\u0440\u0442\u043a\u0430, \u043d\u043e \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 <\/strong><a href=\"https:\/\/webkit.org\/\" rel=\"noopener noreferrer nofollow\"><strong>WebKit<\/strong><\/a><strong>.<\/strong> \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Selenium, Playwright \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 <a href=\"https:\/\/webkit.org\/\" rel=\"noopener noreferrer nofollow\">WebKit<\/a> (\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u0430\u043d <a href=\"https:\/\/www.apple.com\/safari\/\" rel=\"noopener noreferrer nofollow\">Safari<\/a>), \u0447\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043a\u0440\u043e\u0441\u0441-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442 \u0438 \u043c\u043e\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/strong> <a href=\"https:\/\/playwright.dev\/python\/docs\/network#mock-apis\" rel=\"noopener noreferrer nofollow\">Playwright \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u043e\u043a\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b,<\/a> \u0447\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0434\u043b\u044f \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 UI-\u0441\u043b\u043e\u044f \u043f\u0440\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u043e\u0432.<\/strong> \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u043c\u0438 \u0438 <a href=\"https:\/\/www.w3schools.com\/html\/html_iframe.asp\" rel=\"noopener noreferrer nofollow\">iframes<\/a> \u0432 Playwright \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u0447\u0435\u043c \u0432 Selenium.<\/p>\n<\/li>\n<li>\n<p><strong>\u0418\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u044b\u0439 API.<\/strong> API \u0443 Playwright \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u044b\u0439 \u2014 \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Selenium, \u0433\u0434\u0435 \u043a\u043e\u0434 \u0447\u0430\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u043e\u0447\u0435\u043c\u0443 Selenium \u0432\u0441\u0451 \u0435\u0449\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442?<\/h4>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u0435, <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u041d\u0435\u043e\u0441\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u043e\u0441\u0442\u044c. <\/strong>\u041c\u043d\u043e\u0433\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 <a href=\"https:\/\/playwright.dev\/python\/\" rel=\"noopener noreferrer nofollow\">Playwright<\/a> \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u043f\u0435\u043b\u0438 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0438\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0441\u043b\u0435\u0434\u0438\u0435.<\/strong> \u0412 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\u0445 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0441\u043e\u0442\u043d\u0438 \u0438 \u0442\u044b\u0441\u044f\u0447\u0438 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a>. \u041f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u2014 \u0434\u043e\u0440\u043e\u0433\u043e, \u0434\u043e\u043b\u0433\u043e \u0438 \u0441\u0442\u0440\u0430\u0448\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. <\/strong>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0443\u0436\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e\u0442 \u0438\u043b\u0438 \u043d\u0430\u0447\u0430\u043b\u0438 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e, \u043d\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0435\u0431\u044b\u0441\u0442\u0440\u044b\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u044b\u043d\u043e\u043a \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0439.<\/strong> <a href=\"https:\/\/www.selenium.dev\/\" rel=\"noopener noreferrer nofollow\">Selenium<\/a> \u0432\u0441\u0451 \u0435\u0449\u0451 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u0445, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 legacy-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u041d\u043e\u0432\u0438\u0447\u043a\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0432\u044b\u0431\u043e\u0440 \u0432 \u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u0443 \u0438\u0437-\u0437\u0430 &#171;\u0447\u0430\u0441\u0442\u043e\u0442\u043d\u043e\u0441\u0442\u0438&#187;, \u043d\u0435 \u0437\u043d\u0430\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u043c\u0443. <\/strong>\u0415\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f &#171;\u0435\u0441\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u2014 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0439&#187;, \u0438 \u043d\u0435 \u0441\u043f\u0435\u0448\u0430\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<\/li>\n<\/ol>\n<h4>\u0412\u044b\u0432\u043e\u0434<\/h4>\n<p>Playwright \u2014 \u044d\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439, \u043c\u043e\u0449\u043d\u044b\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u044b\u0442\u0435\u0441\u043d\u044f\u0435\u0442 Selenium \u0438\u0437 \u043d\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0438\u043b\u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u2014 \u0441\u043c\u0435\u043b\u043e \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0432\u044b\u0431\u043e\u0440 \u0432 \u043f\u043e\u043b\u044c\u0437\u0443 Playwright. \u0415\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u0441\u0430\u043c\u0438 \u0437\u0430 \u0441\u0435\u0431\u044f.<\/p>\n<h2>\u041f\u0430\u0442\u0442\u0435\u0440\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 UI-\u0442\u0435\u0441\u0442\u043e\u0432<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u0442\u0435\u0441\u0442\u044b \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438, \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438, \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0442\u0435\u0441\u0442-\u043a\u0435\u0439\u0441\u044b &#171;\u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f&#187;, \u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u2014 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9F%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u044b<\/a> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430: PageObject, PageComponent \u0438 PageFactory. \u0412\u043c\u0435\u0441\u0442\u0435 \u043e\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0447\u043d\u0443\u044e, \u0433\u0438\u0431\u043a\u0443\u044e \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<h3>PageObject<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/pages\" rel=\"noopener noreferrer nofollow\"><strong>PageObject<\/strong><\/a> \u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0439 \u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432 UI-\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0421\u0443\u0442\u044c \u0435\u0433\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (\u0438\u043b\u0438 \u044d\u043a\u0440\u0430\u043d, \u0435\u0441\u043b\u0438 \u0440\u0435\u0447\u044c \u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438) \u0432 \u0432\u0438\u0434\u0435 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<ul>\n<li>\n<p>\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u2014 \u044d\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b (\u043a\u043d\u043e\u043f\u043a\u0438, \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<li>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u2014 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u0442\u0438\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 (\u043a\u043b\u0438\u043a, \u0432\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0442.\u0434.).<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0442\u0435\u0441\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 &#171;\u0440\u0430\u0437\u043c\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f&#187; \u043f\u043e \u043b\u043e\u043a\u0430\u0442\u043e\u0440\u0430\u043c \u0438 \u0441\u044b\u0440\u044b\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c, \u0430 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043a\u0430\u043a \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443:<\/p>\n<pre><code class=\"python\">registration_page.fill_email(\"test@example.com\") registration_page.submit()<\/code><\/pre>\n<p>Page Object \u0440\u0435\u0448\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446, \u043d\u043e \u043e\u043d \u043d\u0435 \u0434\u0430\u0451\u0442 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445.<\/p>\n<h3>PageComponent<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/components\" rel=\"noopener noreferrer nofollow\"><strong>PageComponent<\/strong><\/a> \u2014 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438. \u041e\u043d \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043c\u0435\u043d\u044e (<a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Navbar<\/strong><\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c (<a href=\"https:\/\/www.w3schools.com\/w3css\/w3css_sidebar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Sidebar<\/strong><\/a>)<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0440\u0442\u043e\u0447\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043a\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0431\u043b\u043e\u043a\u0438 \u0438 \u0441\u0435\u043a\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 PageObject, \u0442\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u0438: \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 <a href=\"https:\/\/www.w3schools.com\/css\/css_navbar.asp\" rel=\"noopener noreferrer nofollow\"><strong>Navbar<\/strong><\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443, \u0445\u043e\u0442\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0443 \u043d\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u0438 \u0442\u0430 \u0436\u0435.<\/p>\n<p><strong>PageComponent<\/strong> \u0440\u0435\u0448\u0430\u0435\u0442 \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0444\u043e\u0440\u043c\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u044d\u0442\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u044c PageObject&#8217;\u043e\u0432 \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Composition_over_inheritance\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">class DashboardPage:     def __init__(self, page):         self.navbar = NavbarComponent(page)         self.sidebar = SidebarComponent(page)<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043b\u043e\u0433\u0438\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0438 \u043c\u043e\u0436\u043d\u043e \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435.<\/p>\n<h3>PageFactory<\/h3>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/tree\/main\/elements\" rel=\"noopener noreferrer nofollow\"><strong>PageFactory<\/strong><\/a> \u2014 \u043c\u0435\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 Python-\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0435. \u0427\u0430\u0449\u0435 \u043e\u043d \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u0432 Java-\u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445, \u043d\u043e \u0441 \u043b\u0451\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043f\u043e\u0434 Python.<\/p>\n<p>\u0415\u0441\u043b\u0438 PageObject \u2014 \u043f\u0440\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, PageComponent \u2014 \u043f\u0440\u043e <strong>\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/strong>, \u0442\u043e PageFactory \u2014 \u043f\u0440\u043e \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0421\u0443\u0442\u044c \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u2014 \u0431\u0443\u0434\u044c \u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430, \u0438\u043d\u043f\u0443\u0442, \u0438\u043a\u043e\u043d\u043a\u0430, \u0442\u0435\u043a\u0441\u0442, \u0447\u0435\u043a\u0431\u043e\u043a\u0441 \u2014 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0441 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c.<\/p>\n<pre><code class=\"python\">class Input:     def __init__(self, locator):         self.locator = locator      def fill(self, text): ...     def clear(self): ...     def is_disabled(self): ...<\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0438\u043d\u043f\u0443\u0442 \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u2014 \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043c\u0435\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c DOM.<\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0443\u0431\u0440\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0442\u0438\u043f\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430, \u043e\u0447\u0438\u0441\u0442\u043a\u0443, \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e),<\/p>\n<\/li>\n<li>\n<p>\u0438, \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u043b\u044e\u0431\u044b\u0445 PageObject \u0438\u043b\u0438 PageComponent.<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u043e?<\/h3>\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 \u0442\u0440\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043c\u043d\u043e\u0433\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u0443\u044e \u043a \u043b\u044e\u0431\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u043c:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">\u0423\u0440\u043e\u0432\u0435\u043d\u044c<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Object<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438\u043b\u0438 \u044d\u043a\u0440\u0430\u043d<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Component<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u044b<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"179\" width=\"179\">\n<p align=\"left\">Page Factory<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438: \u0438\u043d\u043f\u0443\u0442\u0430\u043c\u0438, \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438, \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043b\u0435\u0433\u043a\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0430:<\/p>\n<ul>\n<li>\n<p>\u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u043a\u0430\u043a \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435),<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (\u0447\u0435\u0440\u0435\u0437 Appium, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440),<\/p>\n<\/li>\n<li>\n<p>\u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b.<\/p>\n<\/li>\n<\/ul>\n<h2>\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e PageObject, PageComponent \u0438 PageFactory, \u0432\u0430\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c <strong>\u0435\u0434\u0438\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/strong>. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043f\u0430\u0434\u0435\u043d\u0438\u0439,<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 CI\/CD,<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u0438 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <a href=\"https:\/\/docs.python.org\/3\/library\/logging.html\" rel=\"noopener noreferrer nofollow\">\u043b\u043e\u0433\u0433\u0435\u0440<\/a>&#8212;<a href=\"https:\/\/refactoring.guru\/design-patterns\/builder\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043b\u0434\u0435\u0440<\/a> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0442\u0435\u0441\u0442\u0430: \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430.<\/p>\n<p><a href=\"https:\/\/github.com\/Nikita-Filonov\/python-ui-tests\/blob\/main\/tools\/logger.py\" rel=\"noopener noreferrer nofollow\"><strong>\/tools\/logger.py<\/strong><\/a><\/p>\n<pre><code class=\"python\">import logging   def get_logger(name: str) -&gt; logging.Logger:     \"\"\"     \u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043b\u043e\u0433\u0433\u0435\u0440 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c.      \u041b\u043e\u0433\u0433\u0435\u0440:     - \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DEBUG     - \u0412\u044b\u0432\u043e\u0434\u0438\u0442 \u043b\u043e\u0433\u0438 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c (stdout)     - \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442: \"\u0434\u0430\u0442\u0430 | \u0438\u043c\u044f \u043b\u043e\u0433\u0433\u0435\u0440\u0430 | \u0443\u0440\u043e\u0432\u0435\u043d\u044c | \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"      :param name: \u0418\u043c\u044f \u043b\u043e\u0433\u0433\u0435\u0440\u0430 (\u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u044f \u043c\u043e\u0434\u0443\u043b\u044f \u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441\u0430)     :return: \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 logging.Logger     \"\"\"     logger = logging.getLogger(name)  # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043b\u043e\u0433\u0433\u0435\u0440 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c     logger.setLevel(logging.DEBUG)  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f DEBUG      handler = logging.StreamHandler()  # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0448\u0435\u0442 \u0432<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-458030","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/458030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=458030"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/458030\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=458030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=458030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=458030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}