{"id":459746,"date":"2025-05-15T15:00:04","date_gmt":"2025-05-15T15:00:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=459746"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=459746","title":{"rendered":"<span>XCUITest \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445: \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 iOS \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c \u0441 Allure<\/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<p><strong>\u041f\u0440\u0438\u0432\u0435\u0442! <\/strong><\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0442\u043e\u043d, \u0438 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Web \u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c UI-\u0442\u0435\u0441\u0442\u044b \u043f\u043e\u0434 iOS, \u0442\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0443\u00a0<strong>XCUITest<\/strong>\u00a0\u0432 \u0441\u0435\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435.<\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 XCUITest. \u0417\u0434\u0435\u0441\u044c \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 iOS-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 <a href=\"https:\/\/github.com\/browserstack\/xcuitest-sample-browserstack\" rel=\"noopener noreferrer nofollow\">Github \u043f\u0440\u043e\u0435\u043a\u0442<\/a>, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0443\u0447\u0438\u0442\u044c\u0441\u044f UI \u0442\u0435\u0441\u0442\u044b: <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <strong>Code<\/strong> -&gt; \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u0441 <strong>HTTPS<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ded\/fb9\/641\/dedfb964144d41e04e843fecf8574f46.png\" alt=\"\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" title=\"\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" width=\"2060\" height=\"898\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ded\/fb9\/641\/dedfb964144d41e04e843fecf8574f46.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ded\/fb9\/641\/dedfb964144d41e04e843fecf8574f46.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u0432 \u043d\u0435\u0439 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043a\u043b\u0430\u0441\u0441 SampleXCUITests. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043b\u0438\u0448\u043d\u0435\u0435<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/091\/082\/819\/0910828196b8586ee0c39aeb753e8f23.png\" alt=\"\u0425\u043e\u043b\u0441\u0442 iOS \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\" title=\"\u0425\u043e\u043b\u0441\u0442 iOS \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\" width=\"2526\" height=\"1342\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/091\/082\/819\/0910828196b8586ee0c39aeb753e8f23.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/091\/082\/819\/0910828196b8586ee0c39aeb753e8f23.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0425\u043e\u043b\u0441\u0442 iOS \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041c\u0435\u0442\u043e\u0434 <strong>setUp()<\/strong> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c, \u043c\u0435\u0442\u043e\u0434 <strong>tearDown()<\/strong> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430. <\/p>\n<h3>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 Alert \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043d\u0435\u0433\u043e<\/p>\n<pre><code class=\"swift\">func testAlertShouldAppearAfterButtonTap() {         let alertButton = app.buttons[\"Alert\"]             XCTAssertTrue(alertButton.waitForExistence(timeout: 3),                          \"\u041a\u043d\u043e\u043f\u043a\u0430 'Alert' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         alertButton.tap()          let alert = app.alerts.element.staticTexts[\"Alert\"]             XCTAssertTrue(alert.waitForExistence(timeout: 3),                       \"Alert \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 Alert \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 &#8216;\u041e\u043a&#8217;<\/p>\n<pre><code class=\"swift\">func testAlertShouldDisappearAfterTappingOK() {         let alertButton = app.buttons[\"Alert\"]             XCTAssertTrue(alertButton.waitForExistence(timeout: 3),                          \"\u041a\u043d\u043e\u043f\u043a\u0430 'Alert' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         alertButton.tap()          let alert = app.alerts.element.staticTexts[\"Alert\"]             XCTAssertTrue(alert.waitForExistence(timeout: 3),                       \"Alert \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")          let alertButtonOK = app.alerts.element.buttons[\"OK\"]         alertButtonOK.tap()          XCTAssertFalse(alert.waitForExistence(timeout: 3),                   \"Alert \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f OK\")     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0432 &#8216;\u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430&#8217;<\/p>\n<pre><code class=\"swift\">func testTextInputShouldDisplayCorrectly() {         let textButton = app.buttons[\"Text\"]         XCTAssertTrue(textButton.waitForExistence(timeout: 3),                       \"\u041a\u043d\u043e\u043f\u043a\u0430 'Text' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         textButton.tap()          let textField = app.textFields[\"Enter a text\"]         let displayedText = app.staticTexts[\"VK\"]         XCTAssertTrue(textField.waitForExistence(timeout: 3),                       \"\u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")         textField.tap()         textField.typeText(\"VK\")         app.keyboards.buttons[\"Return\"].tap()         if displayedText.isEnabled {             XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\") { _ in                 XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                               \"\u0422\u0435\u043a\u0441\u0442 'VK' \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")                 XCTAssertEqual(displayedText.label, \"VK\",                                \"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0442\u043e\u0447\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c\u0443\")             }         }     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0432 &#8216;\u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430&#8217;<\/p>\n<pre><code class=\"swift\">func testCheckVisibleTextWhileSwitchingBetweenScreens() {         let textButton = app.buttons[\"Text\"]         XCTAssertTrue(textButton.waitForExistence(timeout: 3),                       \"\u041a\u043d\u043e\u043f\u043a\u0430 'Text' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         textButton.tap()          let textField = app.textFields[\"Enter a text\"]         let displayedText = app.staticTexts[\"VK\"]         XCTAssertTrue(textField.waitForExistence(timeout: 3),                       \"\u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")         textField.tap()         textField.typeText(\"VK\")         app.keyboards.buttons[\"Return\"].tap()         if displayedText.isEnabled {             XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\") { _ in                 XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                               \"\u0422\u0435\u043a\u0441\u0442 'VK' \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")                 XCTAssertEqual(displayedText.label, \"VK\",                                \"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0442\u043e\u0447\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c\u0443\")             }         }         XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 WebView\") { _ in                 app.tabBars.buttons[\"Web View\"].tap()                 app.tabBars.buttons[\"UI Elements\"].tap()                                  XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                             \"\u0422\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\")                 XCTAssertEqual(displayedText.label, \"VK\",                              \"\u0422\u0435\u043a\u0441\u0442 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u043a\u0440\u0430\u043d\u043e\u0432\")         }     }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 <strong>Show the Test navigator<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d04\/5e0\/bb9\/d045e0bb992486c2cf4020fe3a2da2a0.png\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\" width=\"754\" height=\"700\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d04\/5e0\/bb9\/d045e0bb992486c2cf4020fe3a2da2a0.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d04\/5e0\/bb9\/d045e0bb992486c2cf4020fe3a2da2a0.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<hr\/>\n<h2>\u0423\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u0422\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0443\u0436\u0435 \u043d\u0435\u043f\u043b\u043e\u0445\u0438\u0435, \u043d\u043e \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c!<\/p>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435 \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c, \u044d\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u043d\u0430 <strong>Page Object \u0438 Page Element<\/strong> \u044d\u043a\u0440\u0430\u043d\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 2 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u044d\u043a\u0440\u0430\u043d\u0430: <strong><em>UI Elements(\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d)<\/em><\/strong><em> \u0438 <\/em><strong><em>Web View<\/em><\/strong><\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u043e\u0439 \u043c\u044b\u0448\u043a\u043e\u0439 \u043d\u0430 \u043f\u0430\u043f\u043a\u0443 <strong>SampleXCUITests<\/strong> -&gt; \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>New Group<\/strong> -&gt; \u041d\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e<\/p>\n<p><strong>BaseScreen<\/strong> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0432 UI-\u0442\u0435\u0441\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \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\u043e\u043c.<\/p>\n<ul>\n<li>\n<p><a href=\"\/users\/discardableResult\" rel=\"noopener noreferrer nofollow\">@discardableResult<\/a> &#8212;  \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c Self? &#8212; \u0432\u043e\u0437\u0432\u0440\u0430\u0442 Self \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u043f\u0430\u0442\u0442\u0435\u0440\u043d Chain of Responsibility)<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>BaseScreen.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  class BaseScreen {     public let app = XCUIApplication()     private lazy var uiElementsTab = app.tabBars.buttons[\"UI Elements\"]     private lazy var webViewTab = app.tabBars.buttons[\"Web View\"]     private lazy var localTestingTab = app.tabBars.buttons[\"Local Testing\"]          @discardableResult     func goToUIElements() -&gt; Self {         uiElementsTab.tap()         return self     }          @discardableResult     func goToWebView() -&gt; Self {         webViewTab.tap()         return self     }          @discardableResult     func goToLocalTesting() -&gt; Self {         localTestingTab.tap()         return self     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>Verifications<\/strong> \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b \u043a\u043b\u0430\u0441\u0441 XCUIElement (\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432 UI-\u0442\u0435\u0441\u0442\u0430\u0445), \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0442.\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>Verifications.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  extension XCUIElement {     @discardableResult     func verifyExistence(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c\" : message         XCTAssertTrue(             self.waitForExistence(timeout: timeout),             errorMessage         )         return self     }          @discardableResult     func verifyHittable(message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\" : message         XCTAssertTrue(             self.isHittable,             errorMessage         )         return self     }          @discardableResult     func verifyDisappear(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c\" : message         XCTAssertFalse(             self.waitForExistence(timeout: timeout),             errorMessage         )         return self     }          @discardableResult     func verifyAndTap(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         self.verifyExistence(timeout: timeout, message: message)             .verifyHittable(message: message)             .tap()         return self     }          @discardableResult     func verifyLabel(expected: String, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ?         \"\u0422\u0435\u043a\u0441\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 '\\(self)' \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439: '\\(self.label)', \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439: '\\(expected)'\" :         message         XCTAssertEqual(self.label, expected, errorMessage)         return self     }               @discardableResult     func typeTextSafely(_ text: String, message: String = \"\") -&gt; Self {         self.verifyExistence(message: message)             .verifyHittable(message: message)             .tap()         self.typeText(text)         XCUIApplication().keyboards.buttons[\"Return\"].tap()         return self     }          @discardableResult     func scrollToView(maxAttempts: Int = 10) -&gt; Self {         for _ in 1...maxAttempts {             if self.isHittable {                 return self             }             sleep(2)             XCUIApplication().webViews.firstMatch.swipeUp()         }         XCTFail(\"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \\(self) \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         return self     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>HomeScreen<\/strong> &#8212; \u043a\u043b\u0430\u0441\u0441 \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 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>\u041d\u0438\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043e\u043a\u043e\u043b\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <em>(_ inputMessage: String)<\/em> \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u043a\u043e\u043b\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u0438\u043c\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>HomeScreen.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  final class HomeScreen: BaseScreen {     private lazy var titleLabel = app.navigationBars.staticTexts[\"UI Elements\"]     private lazy var buttonText = app.buttons[\"Text\"]     private lazy var alertButton = app.buttons[\"Alert\"]     private lazy var alertText = app.alerts.element.staticTexts[\"\u0414\u0443\u0440\u043e\u0432 \u0432\u0435\u0440\u043d\u0438 \u0441\u0442\u0435\u043d\u0443\"]     private lazy var alertOKButton = app.alerts.element.buttons[\"\ud83d\ude14\"]     private lazy var buttonBack = app.navigationBars.buttons[\"UI Elements\"]     private lazy var textField = app.textFields[\"Enter a text\"]     private lazy var resultLabel = app.staticTexts[HomeScreenValue.textFieldInput]          lazy var baseElement = titleLabel          @discardableResult     func tapText() -&gt; Self {         buttonText             .verifyExistence()             .verifyHittable()             .tap()                  textField.verifyExistence()         return self     }          @discardableResult     func tapAlert() -&gt; Self {         alertButton             .verifyExistence()             .verifyHittable()             .tap()                  alertText             .verifyExistence()         return self     }          @discardableResult     func closeAlert() -&gt; Self {         alertOKButton             .verifyExistence()             .verifyHittable()             .tap()                  alertOKButton.verifyDisappear()         return self     }          @discardableResult     func enterText(_ inputMessage: String) -&gt; Self {         textField.typeTextSafely(inputMessage)         return self     }          @discardableResult     func checkTextAfterPushTextField(_ expectedText: String) -&gt; Self {         resultLabel.verifyLabel(expected: expectedText)         return self     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>WebViewScreen<\/strong> &#8212; \u043a\u043b\u0430\u0441\u0441 \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 \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e \u043d\u0430 WebView.<\/p>\n<details class=\"spoiler\">\n<summary>WebViewScreen.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  final class WebViewScreen: BaseScreen {     private lazy var titleLabel = app.webViews.staticTexts[\"App &amp; Browser Testing Made Easy\"]     private lazy var benefitsSection = app.webViews.staticTexts[\"Benefits\"]          lazy var baseElement = titleLabel          @discardableResult     func verifyBenefitsSectionVisible() -&gt; Self{         benefitsSection.scrollToView()         return self     }          @discardableResult     func shouldFindTextByPrefix() -&gt; Self{         let beginText = app.webViews.staticTexts.containing(NSPredicate(format: \"label BEGINSWITH %@\", \"Give your\")).firstMatch         beginText.verifyExistence()         return self     }          @discardableResult     func shouldFindTextCaseInsensitive() -&gt; Self {         let containsText = app.webViews.staticTexts.containing(NSPredicate(format: \"label CONTAINS[c] %@\", \"give your\")).firstMatch         containsText.verifyExistence()         return self     }          @discardableResult     func shouldFindTextByMultipleKeywords(_ keywords: [String]) -&gt; Self{         let keyText = app.webViews.staticTexts.containing(NSPredicate(format:                        \"label CONTAINS %@ AND label CONTAINS %@\",         keywords[0], keywords[1])).firstMatch         keyText.verifyExistence()         return self     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u043d\u0435\u0441\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b (\u0434\u043b\u044f \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u0438 \u0434\u043b\u044f \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e)<\/p>\n<pre><code class=\"swift\">public enum HomeScreenValue {     public static let textFieldHint = \"Waiting for text input.\"     public static let textFieldInput = \"XCUI Tests\" }<\/code><\/pre>\n<pre><code class=\"swift\">public enum ErrorMessageValue {     public static let loadMainScreen = \"\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f\"     public static let loadWebViewScreen = \"\u042d\u043a\u0440\u0430\u043d WebView \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0441\u044f\" }<\/code><\/pre>\n<p> <strong>BaseTests<\/strong> &#8212; \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f UI-\u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435,   \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"swift\">class BaseTests: XCTestCase {     private var baseScreen = BaseScreen()      lazy var app = baseScreen.app      open override func setUp() {         app.launch()         \/\/ \u0422\u0435\u0441\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0435         continueAfterFailure = true     }      open override func tearDown() {         app.terminate()     } }<\/code><\/pre>\n<p><strong>continueAfterFailure<\/strong> &#8212; \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430 \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043a\u0438. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 true, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u0430 \u0434\u0430\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438<\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0440:<\/em><\/p>\n<p><em>continueAfterFailure = <\/em><strong><em>false<\/em><\/strong><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ff9\/ce6\/83e\/ff9ce683e34db34998c12b833baf26f7.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c false\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c false\" width=\"2390\" height=\"848\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ff9\/ce6\/83e\/ff9ce683e34db34998c12b833baf26f7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ff9\/ce6\/83e\/ff9ce683e34db34998c12b833baf26f7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b <em>continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c false<\/em><\/figcaption><\/div>\n<\/figure>\n<p><em>continueAfterFailure = <\/em><strong><em>true<\/em><\/strong><\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1b\/bcc\/2ea\/c1bbcc2ea30ec9c4e533ee74ce53f88d.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c true\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c true\" width=\"2398\" height=\"852\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c1b\/bcc\/2ea\/c1bbcc2ea30ec9c4e533ee74ce53f88d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1b\/bcc\/2ea\/c1bbcc2ea30ec9c4e533ee74ce53f88d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b <em>continueAfterFailure \u0441 \u0444\u043b\u0430\u0433\u043e\u043c true<\/em><\/figcaption><\/div>\n<\/figure>\n<p><strong>HomeScreenTests<\/strong> &#8212; \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f UI-\u0442\u0435\u0441\u0442\u043e\u0432 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430. \u041d\u0430\u043f\u0438\u0441\u0430\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u0432 setUp() (\u043f\u043e \u0442\u0438\u043f\u0443 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 <em>LoadableComponent<\/em>)<\/p>\n<details class=\"spoiler\">\n<summary>HomeScreenTests.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  final class HomeScreenTests: BaseTests {          override func setUp() {         super.setUp()         HomeScreen().baseElement.verifyExistence(             message: ErrorMessageValue.loadMainScreen         )     }          func testAlertShouldAppearAfterButtonTap() {         HomeScreen()             .tapAlert()     }          func testAlertShouldDisappearAfterTappingOK() {         HomeScreen()             .tapAlert()             .closeAlert()     }          func testTextInputShouldDisplayCorrectly() {         HomeScreen()             .tapText()             .enterText(HomeScreenValue.textFieldInput)             .checkTextAfterPushTextField(HomeScreenValue.textFieldInput)     }          func testCheckVisibleTextWhileSwitchingBetweenScreens() {         HomeScreen()             .tapText()             .enterText(HomeScreenValue.textFieldInput)         BaseScreen()             .goToWebView()             .goToUIElements()         HomeScreen()             .checkTextAfterPushTextField(HomeScreenValue.textFieldInput)     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>WebViewScreenTests<\/strong> &#8212; \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f UI-\u0442\u0435\u0441\u0442\u043e\u0432 WebView \u044d\u043a\u0440\u0430\u043d\u0430<\/p>\n<details class=\"spoiler\">\n<summary>WebViewScreenTests.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation  final class WebViewScreenTests: BaseTests {          override func setUp() {         super.setUp()         BaseScreen()             .goToWebView()         WebViewScreen()             .baseElement             .verifyExistence(message: ErrorMessageValue.loadWebViewScreen)     }          func testScrollToTextBenefits() {         WebViewScreen()             .verifyBenefitsSectionVisible()     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 \u0442\u0435\u043a\u0441\u0442\u0430     func testShouldFindTextByPrefix() {         WebViewScreen()             .shouldFindTextByPrefix()     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u0441 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430     func testShouldFindTextCaseInsensitive() {         WebViewScreen()             .shouldFindTextCaseInsensitive()     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c     func testShouldFindTextByMultipleKeywords() {         WebViewScreen()             .shouldFindTextByMultipleKeywords([\"users\", \"seamless\"])     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9ac\/242\/571\/9ac242571ac67f278dfff1a9737550f6.png\" alt=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" title=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" width=\"734\" height=\"880\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/9ac\/242\/571\/9ac242571ac67f278dfff1a9737550f6.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9ac\/242\/571\/9ac242571ac67f278dfff1a9737550f6.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p><strong>[\u041b\u0430\u0439\u0444\u0445\u0430\u043a]<\/strong> \u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043a\u043e\u0434, \u0442\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0435 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 (Command + A) -&gt; Editor -&gt; Re-Indent<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2ff\/cab\/f74\/2ffcabf74d1823e81e5a99b28f7748a9.png\" alt=\"\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0432 Xcode\" title=\"\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0432 Xcode\" width=\"1220\" height=\"1306\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2ff\/cab\/f74\/2ffcabf74d1823e81e5a99b28f7748a9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2ff\/cab\/f74\/2ffcabf74d1823e81e5a99b28f7748a9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u0432 Xcode<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<hr\/>\n<h2>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Allure<\/h2>\n<p>\u041a\u0430\u043a \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c Allure \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u2014 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u043b\u0438 \u0432 <a href=\"https:\/\/habr.com\/ru\/amp\/publications\/686448\/#chapter2\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a><\/p>\n<p>\u0420\u0430\u0441\u0448\u0438\u0440\u0438\u043b XCTest \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438\u00a0<strong>Allure-\u043e\u0442\u0447\u0435\u0442\u043e\u0432<\/strong>, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043f\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u043b\u043e\u0433\u0438\u044f\u043c BDD (Epic, Feature, Story) \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0438\u0445 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>epic(_ values:String&#8230;) &#8212; <\/strong>\u0412\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>feature(_ values:String&#8230;) <\/strong>&#8212; \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c<\/p>\n<\/li>\n<li>\n<p><strong>story(_ values: String&#8230;)<\/strong> &#8212; \u042e\u0437\u0435\u0440-\u0441\u0442\u043e\u0440\u0438 \u0438\u043b\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>displayName(_ name: String)<\/strong> &#8212; \u0418\u043c\u044f \u0442\u0435\u0441\u0442\u0430 \u0432 \u043e\u0442\u0447\u0435\u0442\u0435<\/p>\n<\/li>\n<li>\n<p><strong>severity(_ values: String&#8230;)<\/strong> &#8212; \u041a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong>owner(_ values: String&#8230;)<\/strong>&#8212; \u041e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0437\u0430 \u0442\u0435\u0441\u0442<\/p>\n<\/li>\n<li>\n<p><strong>step(_ name: String, step: () -&gt; Void)<\/strong> &#8212; \u0428\u0430\u0433 \u0442\u0435\u0441\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>AllureXCTestExtensions.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  extension XCTest {     func epic(_ values:String...) {         label(name: \"epic\", values: values)     }          func feature(_ values:String...) {         label(name: \"feature\", values: values)     }          func story(_ values: String...) {         label(name: \"story\", values: values)     }          func displayName(_ name: String) {         addTestCaseName(value: name)     }          func severity(_ values: String...) {         label(name: \"severity\", values: values)     }          func owner(_ values: String...) {         label(name: \"owner\", values: values)     }          func step(_ name: String, step: () -&gt; Void) {         XCTContext.runActivity(named: name) { _ in             step()         }     }          private func label(name: String, values: [String]) {         for value in values {             XCTContext.runActivity(named: \"allure.label.\\(name):\\(value)\", block: { _ in })         }     }          private func addTestCaseName(value: String) {         XCTContext.runActivity(named: \"allure.name:\\(value)\") { _ in }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u043e\u0432\u0435\u043b\u0438 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0434\u043e\u0431\u0430\u0432\u0438\u0432\u00a0<strong>Allure-\u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438<\/strong>\u00a0\u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u041c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0413\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430<\/p>\n<details class=\"spoiler\">\n<summary>HomeScreenTests.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest   final class HomeScreenTests: BaseTests {          override func setUp() {         super.setUp()         step(\"\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\") {             HomeScreen().baseElement.verifyExistence(                 message: ErrorMessageValue.loadMainScreen             )         }     }          \/\/ MARK: - Alert     func testAlertShouldAppearAfterButtonTap() {         epic(\"\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\")         feature(\"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 Alert\")         story(\"\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 Alert\")         displayName(\"\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 Alert \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u0422\u0430\u043f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Alert \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0430\u043b\u0435\u0440\u0442\u0430\") {             HomeScreen()                 .tapAlert()         }              }          func testAlertShouldDisappearAfterTappingOK() {         epic(\"\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\")         feature(\"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 Alert\")         story(\"\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 Alert\")         displayName(\"\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 Alert \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 'OK'\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u0422\u0430\u043f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 Alert \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0430\u043b\u0435\u0440\u0442\u0430\") {             HomeScreen().tapAlert()         }                  step(\"\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 'OK' \u0432 Alert \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0433\u043e \u0438\u0441\u0447\u0435\u0437\u043d\u043e\u0432\u0435\u043d\u0438\u0435\") {             HomeScreen().closeAlert()         }     }          \/\/ MARK: - \u0412\u0432\u043e\u0434 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432     func testTextInputShouldDisplayCorrectly() {         epic(\"\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\")         feature(\"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c \u043f\u043e\u043b\u0435\u043c\")         story(\"\u0412\u0432\u043e\u0434 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0430\")         displayName(\"\u041a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043a\u043d\u043e\u043f\u043a\u0443 'Text'\") {             HomeScreen().tapText()         }                  step(\"\u0412\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u043a\u0441\u0442 '\\(HomeScreenValue.textFieldInput)' \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\") {             HomeScreen()                 .enterText(HomeScreenValue.textFieldInput)         }                  step(\"\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0434 \u043f\u043e\u043b\u0435\u043c \u0432\u0432\u043e\u0434\u0430\") {             HomeScreen().checkTextAfterPushTextField(HomeScreenValue.textFieldInput)         }     }          func testCheckVisibleTextWhileSwitchingBetweenScreens() {         epic(\"\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\")         feature(\"\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u043c \u043f\u043e\u043b\u0435\u043c\")         story(\"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u043c\u0435\u0436\u0434\u0443 \u044d\u043a\u0440\u0430\u043d\u0430\u043c\u0438\")         displayName(\"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u043a\u0440\u0430\u043d\u043e\u0432\")         severity(\"NORMAL\")         owner(\"Anton Moskovsky\")                  step(\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043a\u043d\u043e\u043f\u043a\u0443 'Text'\") {             HomeScreen().tapText()         }                  step(\"\u0412\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u043a\u0441\u0442 '\\(HomeScreenValue.textFieldInput)' \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\") {             HomeScreen()                 .enterText(HomeScreenValue.textFieldInput)         }                  step(\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 WebView \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\") {             BaseScreen()                 .goToWebView()                 .goToUIElements()         }                  step(\"\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d\") {             HomeScreen()                 .checkTextAfterPushTextField(HomeScreenValue.textFieldInput)         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0418 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u0430 WebView<\/p>\n<details class=\"spoiler\">\n<summary>WebViewScreenTests.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation  final class WebViewScreenTests: BaseTests {          override func setUp() {         super.setUp()         step(\"\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d WebView \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e\") {             BaseScreen()                 .goToWebView()         }         step(\"\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u044d\u043a\u0440\u0430\u043d\u0430 WebView\") {             WebViewScreen()                 .baseElement                 .verifyExistence(message: ErrorMessageValue.loadWebViewScreen)         }     }          func testScrollToTextBenefits() {         epic(\"\u042d\u043a\u0440\u0430\u043d WebView\")         feature(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430\")         story(\"\u041d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ScrollView\")         displayName(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043a\u0440\u043e\u043b\u043b\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")         step(\"\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043a\u0440\u043e\u043b\u043b \u0434\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430 Benefits\") {             WebViewScreen()                 .verifyBenefitsSectionVisible()         }     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 \u0442\u0435\u043a\u0441\u0442\u0430     func testShouldFindTextByPrefix() {         epic(\"\u042d\u043a\u0440\u0430\u043d WebView\")         feature(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430\")         story(\"\u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u0443 \u0442\u0435\u043a\u0441\u0442\u0430\")         displayName(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0443\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u0418\u0449\u0435\u043c \u0442\u0435\u043a\u0441\u0442 \u043f\u043e \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\") {             WebViewScreen()                 .shouldFindTextByPrefix()         }     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u0441 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430     func testShouldFindTextCaseInsensitive() {         epic(\"\u042d\u043a\u0440\u0430\u043d WebView\")         feature(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430\")         story(\"\u041f\u043e\u0438\u0441\u043a \u0441 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\")         displayName(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u0418\u0449\u0435\u043c \u0442\u0435\u043a\u0441\u0442, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432\") {             WebViewScreen()                 .shouldFindTextCaseInsensitive()         }     }          \/\/ \u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c     func testShouldFindTextByMultipleKeywords() {         epic(\"\u042d\u043a\u0440\u0430\u043d WebView\")         feature(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430\")         story(\"\u041f\u043e\u0438\u0441\u043a \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c\")         displayName(\"\u041f\u043e\u0438\u0441\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c\")         severity(\"MINOR\")         owner(\"Anton Moskovsky\")                  step(\"\u0418\u0449\u0435\u043c \u0442\u0435\u043a\u0441\u0442 \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0441\u043b\u043e\u0432\u0430\u043c\") {             WebViewScreen()                 .shouldFindTextByMultipleKeywords([\"users\", \"seamless\"])         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432\u00a0<strong>cmd<\/strong> \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430: <\/p>\n<pre><code class=\"bash\">allure serve allure-results<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0442\u0447\u0435\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0442\u0447\u0435\u0442 Allure<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/657\/5d2\/aa1\/6575d2aa1aaf7a0e4b0ae0e402174289.png\" alt=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0442\u0447\u0435\u0442\u0430\" title=\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0442\u0447\u0435\u0442\u0430\" width=\"2940\" height=\"1470\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/657\/5d2\/aa1\/6575d2aa1aaf7a0e4b0ae0e402174289.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/657\/5d2\/aa1\/6575d2aa1aaf7a0e4b0ae0e402174289.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0442\u0447\u0435\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<hr\/>\n<h2>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b<\/h2>\n<ul>\n<li>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0432\u043c\u0435\u0441\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432: <a href=\"https:\/\/github.com\/moskkovsky\/ui-tests-xcui\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/moskkovsky\/ui-tests-xcui<\/a><\/p>\n<\/li>\n<li>\n<p>\u0420\u0443\u0441\u0441\u043a\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0439 \u0433\u0430\u0439\u0434 \u043f\u043e <strong>XCUITest<\/strong>: <a href=\"https:\/\/testengineer.ru\/bolshoj-gajd-po-avtomatizacii-xcuitest\/\" rel=\"noopener noreferrer nofollow\">https:\/\/testengineer.ru\/bolshoj-gajd-po-avtomatizacii-xcuitest\/<\/a><\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 <strong>Allure<\/strong> (\u043e\u0442\u0447\u0451\u0442\u043d\u043e\u0441\u0442\u044c) \u0432 UI-\u0442\u0435\u0441\u0442\u044b (swift, <strong>XCTest<\/strong>): <a href=\"https:\/\/habr.com\/ru\/companies\/rtlabs\/articles\/686448\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/companies\/rtlabs\/articles\/686448\/<\/a><\/p>\n<\/li>\n<li>\n<p>\u0415\u0449\u0435 \u043f\u0440\u043e <strong>Allure<\/strong> \u0441 iOS: <a href=\"https:\/\/kolesa.group\/media\/posts\/tech-papers\/kak-dzhun-vnedryal-allure-s-xctest-opyt-avtomatizacii-testirovaniya-ios\" rel=\"noopener noreferrer nofollow\">https:\/\/kolesa.group\/media\/posts\/tech-papers\/kak-dzhun-vnedryal-allure-s-xctest-opyt-avtomatizacii-testirovaniya-ios<\/a><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <strong>Allure<\/strong>: <a href=\"https:\/\/habr.com\/ru\/companies\/sberbank\/articles\/359302\/\" rel=\"noopener noreferrer nofollow\">https:\/\/habr.com\/ru\/companies\/sberbank\/articles\/359302\/<\/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\/909558\/\"> https:\/\/habr.com\/ru\/articles\/909558\/<\/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<p><strong>\u041f\u0440\u0438\u0432\u0435\u0442! <\/strong><\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u043d\u0442\u043e\u043d, \u0438 \u044f \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0441\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Web \u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c UI-\u0442\u0435\u0441\u0442\u044b \u043f\u043e\u0434 iOS, \u0442\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0447\u0442\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0443\u00a0<strong>XCUITest<\/strong>\u00a0\u0432 \u0441\u0435\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c \u044f\u0437\u044b\u043a\u0435.<\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043a\u0440\u0430\u0442\u043a\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 XCUITest. \u0417\u0434\u0435\u0441\u044c \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0432\u0430\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0435 \u0448\u0430\u0433\u0438 \u0432 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 iOS-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0435 \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0430 <a href=\"https:\/\/github.com\/browserstack\/xcuitest-sample-browserstack\" rel=\"noopener noreferrer nofollow\">Github \u043f\u0440\u043e\u0435\u043a\u0442<\/a>, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0443\u0447\u0438\u0442\u044c\u0441\u044f UI \u0442\u0435\u0441\u0442\u044b: <\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 <strong>Code<\/strong> -&gt; \u041a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u0441 <strong>HTTPS<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0430\u043f\u043a\u0443 \u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u0432 \u043d\u0435\u0439 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u043a\u043b\u0430\u0441\u0441 SampleXCUITests. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043b\u0438\u0448\u043d\u0435\u0435<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\">\n<div><figcaption>\u0425\u043e\u043b\u0441\u0442 iOS \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<p>\u041c\u0435\u0442\u043e\u0434 <strong>setUp()<\/strong> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0442\u0435\u0441\u0442\u043e\u043c, \u043c\u0435\u0442\u043e\u0434 <strong>tearDown()<\/strong> \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430. <\/p>\n<h3>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 Alert \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043d\u0435\u0433\u043e<\/p>\n<pre><code class=\"swift\">func testAlertShouldAppearAfterButtonTap() {         let alertButton = app.buttons[\"Alert\"]             XCTAssertTrue(alertButton.waitForExistence(timeout: 3),                          \"\u041a\u043d\u043e\u043f\u043a\u0430 'Alert' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         alertButton.tap()          let alert = app.alerts.element.staticTexts[\"Alert\"]             XCTAssertTrue(alert.waitForExistence(timeout: 3),                       \"Alert \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 Alert \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 &#8216;\u041e\u043a&#8217;<\/p>\n<pre><code class=\"swift\">func testAlertShouldDisappearAfterTappingOK() {         let alertButton = app.buttons[\"Alert\"]             XCTAssertTrue(alertButton.waitForExistence(timeout: 3),                          \"\u041a\u043d\u043e\u043f\u043a\u0430 'Alert' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         alertButton.tap()          let alert = app.alerts.element.staticTexts[\"Alert\"]             XCTAssertTrue(alert.waitForExistence(timeout: 3),                       \"Alert \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")          let alertButtonOK = app.alerts.element.buttons[\"OK\"]         alertButtonOK.tap()          XCTAssertFalse(alert.waitForExistence(timeout: 3),                   \"Alert \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f OK\")     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0432 &#8216;\u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430&#8217;<\/p>\n<pre><code class=\"swift\">func testTextInputShouldDisplayCorrectly() {         let textButton = app.buttons[\"Text\"]         XCTAssertTrue(textButton.waitForExistence(timeout: 3),                       \"\u041a\u043d\u043e\u043f\u043a\u0430 'Text' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         textButton.tap()          let textField = app.textFields[\"Enter a text\"]         let displayedText = app.staticTexts[\"VK\"]         XCTAssertTrue(textField.waitForExistence(timeout: 3),                       \"\u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")         textField.tap()         textField.typeText(\"VK\")         app.keyboards.buttons[\"Return\"].tap()         if displayedText.isEnabled {             XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\") { _ in                 XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                               \"\u0422\u0435\u043a\u0441\u0442 'VK' \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")                 XCTAssertEqual(displayedText.label, \"VK\",                                \"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0442\u043e\u0447\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c\u0443\")             }         }     }<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u043f\u043e\u0441\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0432 &#8216;\u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430&#8217;<\/p>\n<pre><code class=\"swift\">func testCheckVisibleTextWhileSwitchingBetweenScreens() {         let textButton = app.buttons[\"Text\"]         XCTAssertTrue(textButton.waitForExistence(timeout: 3),                       \"\u041a\u043d\u043e\u043f\u043a\u0430 'Text' \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         textButton.tap()          let textField = app.textFields[\"Enter a text\"]         let displayedText = app.staticTexts[\"VK\"]         XCTAssertTrue(textField.waitForExistence(timeout: 3),                       \"\u041f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438\")         textField.tap()         textField.typeText(\"VK\")         app.keyboards.buttons[\"Return\"].tap()         if displayedText.isEnabled {             XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430\") { _ in                 XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                               \"\u0422\u0435\u043a\u0441\u0442 'VK' \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")                 XCTAssertEqual(displayedText.label, \"VK\",                                \"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0442\u043e\u0447\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c\u0443\")             }         }         XCTContext.runActivity(named: \"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u043d\u0430 WebView\") { _ in                 app.tabBars.buttons[\"Web View\"].tap()                 app.tabBars.buttons[\"UI Elements\"].tap()                                  XCTAssertTrue(displayedText.waitForExistence(timeout: 3),                             \"\u0422\u0435\u043a\u0441\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\")                 XCTAssertEqual(displayedText.label, \"VK\",                              \"\u0422\u0435\u043a\u0441\u0442 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u043a\u0440\u0430\u043d\u043e\u0432\")         }     }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 <strong>Show the Test navigator<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u0438\u043d \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/summary>\n<div class=\"spoiler__content\">\n<figure class=\"full-width\">\n<div><figcaption>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<\/div>\n<\/details>\n<hr\/>\n<h2>\u0423\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u0443\u0435\u043c \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u0422\u0430\u043a\u0438\u0435 \u0442\u0435\u0441\u0442\u044b \u0443\u0436\u0435 \u043d\u0435\u043f\u043b\u043e\u0445\u0438\u0435, \u043d\u043e \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c!<\/p>\n<p>\u041f\u0435\u0440\u0432\u043e\u0435 \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c, \u044d\u0442\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u043d\u0430 <strong>Page Object \u0438 Page Element<\/strong> \u044d\u043a\u0440\u0430\u043d\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<p>\u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 2 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u044d\u043a\u0440\u0430\u043d\u0430: <strong><em>UI Elements(\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d)<\/em><\/strong><em> \u0438 <\/em><strong><em>Web View<\/em><\/strong><\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043f\u0440\u0430\u0432\u043e\u0439 \u043c\u044b\u0448\u043a\u043e\u0439 \u043d\u0430 \u043f\u0430\u043f\u043a\u0443 <strong>SampleXCUITests<\/strong> -&gt; \u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <strong>New Group<\/strong> -&gt; \u041d\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e<\/p>\n<p><strong>BaseScreen<\/strong> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0432 UI-\u0442\u0435\u0441\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \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\u043e\u043c.<\/p>\n<ul>\n<li>\n<p><a href=\"\/users\/discardableResult\" rel=\"noopener noreferrer nofollow\">@discardableResult<\/a> &#8212;  \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043a\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0447\u0435\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c Self? &#8212; \u0432\u043e\u0437\u0432\u0440\u0430\u0442 Self \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u043f\u0430\u0442\u0442\u0435\u0440\u043d Chain of Responsibility)<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>BaseScreen.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  class BaseScreen {     public let app = XCUIApplication()     private lazy var uiElementsTab = app.tabBars.buttons[\"UI Elements\"]     private lazy var webViewTab = app.tabBars.buttons[\"Web View\"]     private lazy var localTestingTab = app.tabBars.buttons[\"Local Testing\"]          @discardableResult     func goToUIElements() -&gt; Self {         uiElementsTab.tap()         return self     }          @discardableResult     func goToWebView() -&gt; Self {         webViewTab.tap()         return self     }          @discardableResult     func goToLocalTesting() -&gt; Self {         localTestingTab.tap()         return self     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>Verifications<\/strong> \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b \u043a\u043b\u0430\u0441\u0441 XCUIElement (\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432 UI-\u0442\u0435\u0441\u0442\u0430\u0445), \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u043c \u043f\u043e\u0441\u043b\u0435 \u043d\u0430\u0436\u0430\u0442\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0442.\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>Verifications.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  extension XCUIElement {     @discardableResult     func verifyExistence(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c\" : message         XCTAssertTrue(             self.waitForExistence(timeout: timeout),             errorMessage         )         return self     }          @discardableResult     func verifyHittable(message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\" : message         XCTAssertTrue(             self.isHittable,             errorMessage         )         return self     }          @discardableResult     func verifyDisappear(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ? \"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 '\\(self)' \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c\" : message         XCTAssertFalse(             self.waitForExistence(timeout: timeout),             errorMessage         )         return self     }          @discardableResult     func verifyAndTap(timeout: TimeInterval = 3, message: String = \"\") -&gt; Self {         self.verifyExistence(timeout: timeout, message: message)             .verifyHittable(message: message)             .tap()         return self     }          @discardableResult     func verifyLabel(expected: String, message: String = \"\") -&gt; Self {         let errorMessage = message.isEmpty ?         \"\u0422\u0435\u043a\u0441\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 '\\(self)' \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442. \u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439: '\\(self.label)', \u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439: '\\(expected)'\" :         message         XCTAssertEqual(self.label, expected, errorMessage)         return self     }               @discardableResult     func typeTextSafely(_ text: String, message: String = \"\") -&gt; Self {         self.verifyExistence(message: message)             .verifyHittable(message: message)             .tap()         self.typeText(text)         XCUIApplication().keyboards.buttons[\"Return\"].tap()         return self     }          @discardableResult     func scrollToView(maxAttempts: Int = 10) -&gt; Self {         for _ in 1...maxAttempts {             if self.isHittable {                 return self             }             sleep(2)             XCUIApplication().webViews.firstMatch.swipeUp()         }         XCTFail(\"\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \\(self) \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435\")         return self     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>HomeScreen<\/strong> &#8212; \u043a\u043b\u0430\u0441\u0441 \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 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>\u041d\u0438\u0436\u043d\u0435\u0435 \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043e\u043a\u043e\u043b\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <em>(_ inputMessage: String)<\/em> \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u043a\u043e\u043b\u043e \u0438\u043c\u0435\u043d\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0432\u043d\u0435\u0448\u043d\u0435\u0435 \u0438\u043c\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>HomeScreen.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import XCTest  final class HomeScreen: BaseScreen {     private lazy var titleLabel = app.navigationBars.staticTexts[\"UI Elements\"]     private lazy var buttonText = app.buttons[\"Text\"]     private lazy var alertButton = app.buttons[\"Alert\"]     private lazy var alertText = app.alerts.element.staticTexts[\"\u0414\u0443\u0440\u043e\u0432 \u0432\u0435\u0440\u043d\u0438 \u0441\u0442\u0435\u043d\u0443\"]     private lazy var alertOKButton = app.alerts.element.buttons[\"\ud83d\ude14\"]     private lazy var buttonBack = app.navigationBars.buttons[\"UI Elements\"]     private lazy var textField = app.textFields[\"Enter a text\"]     private lazy var resultLabel = app.staticTexts[HomeScreenValue.textFieldInput]          lazy var baseElement = titleLabel<\/code><\/pre>\n<\/div>\n<\/details>\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-459746","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/459746","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=459746"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/459746\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=459746"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=459746"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=459746"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}