{"id":478119,"date":"2026-04-30T13:00:09","date_gmt":"2026-04-30T13:00:09","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=478119"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=478119","title":{"rendered":"Xcode Simulator \u2014 \u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0433\u043e\u043d \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 CI + Fastlane"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0420\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u043f\u0440\u043e \u043d\u0430\u0448 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 <code>fastlane<\/code>, \u0435\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u043c \u043f\u043e <a href=\"https:\/\/github.com\/MarathonLabs\/marathon\" rel=\"noopener noreferrer nofollow\">Maraphon<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/github.com\/avito-tech\/Emcee\" rel=\"noopener noreferrer nofollow\">Emcee<\/a>, \u0442\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043c\u043e\u0438 \u0441\u043e\u0432\u0435\u0442\u044b \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u0434\u043d\u044b\u043c\u0438 \/ \u043d\u0435\u043b\u0435\u043f\u044b\u043c\u0438 \/ \u0438 \u043f\u043e\u0440\u043e\u0439 \u0434\u0430\u0436\u0435 \u0437\u0430\u0431\u044b\u0432\u043d\u044b\u043c\u0438 &#8212; \u043d\u0435 \u043e\u0431\u0435\u0441\u0441\u0443\u0434\u044c\u0442\u0435.<\/p>\n<p>\u041d\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0445\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0434\u0432\u0435 \u043e\u0442\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441\u0445\u043e\u0436\u0438\u0435 \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u043e\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u0430\u0432\u0442\u043e\u0440\u0430, \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441 \u043d\u0438\u043c\u0438 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/vivid_money\/articles\/649901\/\" rel=\"noopener noreferrer nofollow\">\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 iOS UI-\u0442\u0435\u0441\u0442\u043e\u0432. \u0427\u0430\u0441\u0442\u044c 1. \u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/vivid_money\/articles\/652397\/\" rel=\"noopener noreferrer nofollow\">\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 iOS UI-\u0442\u0435\u0441\u0442\u043e\u0432. \u0427\u0430\u0441\u0442\u044c 2. \u0420\u0430\u0441\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432<\/a><\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<p>\u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u044f \u0443\u0432\u0438\u0434\u0435\u043b \u0432 <code>Fastfile<\/code><\/p>\n<p>\u0412 <code>Fastfile<\/code> \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/docs.fastlane.tools\/actions\/run_tests\/#run_tests\" rel=\"noopener noreferrer nofollow\">scan<\/a>. \u041d\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0443 \u0438\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043f\u0438\u0441\u043a\u0430:<\/p>\n<ol>\n<li>\n<p>iOS \u043f\u0440\u043e\u0435\u043a\u0442 (Swift + SwiftUI + UIKit + SwiftPM)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u041e\u0421 (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e iOS 26.4.1)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f iOS 18.6 (UI \u0434\u043b\u044f iOS 26 \u0438 18 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0435 \u0432\u0435\u0440\u0441\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u0438 \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0445 \u043e\u0441\u044f\u0445)<\/p>\n<\/li>\n<li>\n<p>\u0414\u0436\u043e\u0431\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438\u0434\u0443\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u0434\u043b\u044f GitLab <code>concurrent = 1<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e \u043d\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043c\u0435\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u043e\u0433\u0434\u0430 \u0431\u044b \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u0448\u043b\u043e \u0431\u044b \u0432 \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043d\u043e \u0438\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0431\u043e\u0435\u0432\u043e\u0439 \u043f\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u043f\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 CI<\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0434\u0436\u043e\u0431\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u043d\u0430 CI, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0440\u0435\u0445 \u0432\u0438\u0434\u043e\u0432 \u0442\u0435\u0441\u0442\u043e\u0432:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/1d\/67\/4c\/1d674ca81a5a0099ce9b955514786b9c.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/1d\/67\/4c\/1d674ca81a5a0099ce9b955514786b9c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/1d\/67\/4c\/1d674ca81a5a0099ce9b955514786b9c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410 <code>fastlane<\/code> \u0441\u043b\u0443\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"ruby\"> private_lane :run_testing do |options|    scan(        project: project,        scheme: options[:scheme],        testplan: options[:testplan],        destination: \"platform=iOS Simulator,id=#{options[:uuid]}\",        skip_detect_devices: true,        code_coverage: false,        derived_data_path: derived_data_path,        disable_concurrent_testing: true    )end  lane :run_unit_tests do    run_testing(scheme: \"AppTests\", testplan: \"UnitTests\", uuid: \"123..\")  end  lane :run_ui_tests_26_4 do    run_testing(scheme: \"AppUITests\", testplan: \"UITests\", uuid: \"123..\")  end  lane :run_ui_tests_18_6 do    run_testing(scheme: \"AppUITests\", testplan: \"UITests\", uuid: \"456..\")  end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0443\u0441\u043a\u0430\u0442\u0435\u043b\u044c \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u0438\u0437\u043b\u0438\u0448\u0435\u0441\u0442\u0432 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u0442\u043e\u0440\u043e\u043c \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0435 \u043f\u0440\u043e <code>fastlane<\/code>, \u0433\u0434\u0435 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f <code>xcodebuild<\/code> \u043a\u043e\u043c\u0430\u043d\u0434\u0430:<\/p>\n<pre><code class=\"bash\">xcodebuild \\    -scheme AppTests \\    -project App.xcodeproj \\    -derivedDataPath DerivedData\/App-biooakmzntobceawoboqmizvekct \\    -destination 'platform=iOS Simulator,id=5F53A860-544D-4A6F-9F1A-C414CC89DDA5' \\    -disable-concurrent-testing \\    -enableCodeCoverage NO \\    -testPlan 'AppTests' \\    build test<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/23\/26\/d5\/2326d568ecaa52b0069fdab1a5a87bef.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/23\/26\/d5\/2326d568ecaa52b0069fdab1a5a87bef.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/23\/26\/d5\/2326d568ecaa52b0069fdab1a5a87bef.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0448\u043b\u043e 11 \u043c\u0438\u043d\u0443\u0442 \u0438 4 \u0441\u0435\u043a\u0443\u043d\u0434\u044b (\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0438 \u0432\u0437\u044f\u043b \u0441\u0440\u0435\u0434\u043d\u0435\u0435), \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0441\u0447\u0435\u0442\u0430 \u0434\u043e \u043d\u0430\u0448\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c, \u0432\u0441\u0435 \u0442\u0440\u0438 \u0434\u0436\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438\u043d\u043e\u0433\u0434\u0430 \u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043a\u0435\u0448 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f, \u0438\u043d\u043e\u0433\u0434\u0430 \u043d\u0430 \u0440\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 SwiftPM \u0433\u043b\u044e\u0447\u0438\u0442 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0434\u0436\u043e\u0431\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043f\u043e\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0430\u0441\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0434\u0436\u043e\u0431\u0430\u043c. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0431\u0443\u0434\u0435\u0442 \u043b\u0438 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u043b\u043a.<\/p>\n<hr\/>\n<h2>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u0440\u0430\u0437\u0434\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u043c<\/h2>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0444\u043b\u0430\u0433 <code>-testProductsPath<\/code> \u0438\u0437 <a href=\"https:\/\/developer.apple.com\/documentation\/xcode-release-notes\/xcode-13_3-release-notes\" rel=\"noopener noreferrer nofollow\">Xcode 13.3<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u0430\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>xcodebuild now supports an .xctestproducts bundle format for the build-for-testing and test-without-building actions. Using a bundle makes it easier to run tests, particularly when transporting tests between systems. Use the new -testProductsPath argument to set the path to the bundle.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u043b\u0430\u0433 <code>build-for-testing<\/code> \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c <code>DerivedData<\/code>, <code>xcodebuild<\/code> \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e <code>.xctestproducts<\/code> \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u043e\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 <code>-testProductsPath<\/code> + <code>test-without-building<\/code> \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432.<\/p>\n<p><code>Lane<\/code> \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"ruby\">  private_lane :build_for_testing do |options|    # \u0441\u043e\u0437\u0434\u0430\u0435\u043c `.xctestproducts` \u043f\u0440\u044f\u043c \u0432 DerivedData \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438    product_path = \"#{File.join(derived_data_path, \"#{options[:scheme]}\")}.xctestproducts\"    scan(      project: project,      scheme: options[:scheme],      sdk: \"iphonesimulator\",      destination: \"generic\/platform=iOS Simulator\",      # \u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c `true`      build_for_testing: true,      code_coverage: false,      derived_data_path: derived_data_path,      # \u0422\u0430\u043a \u043a\u0430\u043a fastlane \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 `-testProductsPath` \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 `xcargs`      xcargs: \"-testProductsPath #{product_path}\"    )    # \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 `.xctestproducts` \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438,    # \u0442\u043e \u043c\u044b \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043b\u0438\u0448\u043d\u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u0443\u0441\u043a\u0430\u0442\u0435\u043b\u044c UI \u0442\u0435\u0441\u0442\u043e\u0432    tests_files = [      \"App.app\",      \"AppUITests-Runner.app\"    ]    derived_data = File.join(product_path, \"Binaries\/0\/Debug-iphonesimulator\")    Dir.children(derived_data).each do |name|      if tests_files.any?(name)        next      else        path = \"#{derived_data}\/#{name}\"        if File.directory?(path)          FileUtils.rm_rf(path)        else          File.delete(path)        end      end    end    # \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u044d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441\u0431\u043e\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c    # \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0434\u0436\u043e\u0431\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 `-testProductsPath` \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432    artifacts_path = File.join(ENV[\"HOME\"], \"builds\/artifacts\/#{options[:uname]}\")    if !File.exist?(artifacts_path)      Dir.mkdir(artifacts_path)    end    # \u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c `.xctestproducts` \u0438\u0437 Xcode DerivedData \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b    FileUtils.mv(product_path, artifacts_path)    # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e `.xctestproducts` \u0438\u0437 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432    File.join(artifacts_path, File.basename(product_path))  end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 <code>lane<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 <code>${SCHEME}.xctestproducts<\/code> \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u0435\u0441\u0442\u0438\u0442 <code>${SCHEME}.xctestproducts<\/code> \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b (\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u043d\u0430 CI)<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u043d\u0435\u0442 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0443\u0442\u044c \u0434\u043e <code>${SCHEME}.xctestproducts<\/code> \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043c\u043e\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u044d\u0442\u043e\u0442 <code>lane<\/code> \u0432\u0435\u0440\u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430 \u043f\u0443\u0442\u044c <code>$HOME\/builds\/artifacts\/2026.04.28_01-44-11-883074-+0700\/${SCHEME}.xctestproducts<\/code>. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c <code>xcodebuild<\/code> \u043a\u043e\u043c\u043d\u0430\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 (<code>.xctestproducts<\/code>) \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"bash\">xcodebuild \\    -scheme AppTests \\    -project App.xcodeproj \\    -derivedDataPath DerivedData\/App-biooakmzntobceawoboqmizvekct \\    -sdk 'iphonesimulator' \\    -destination 'generic\/platform=iOS Simulator' \\    -enableCodeCoverage NO \\    -testProductsPath DerivedData\/App-biooakmzntobceawoboqmizvekct\/AppTests.xctestproducts \\    build-for-testing<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c <code>lane<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u0434\u043b\u044f \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 UI \u0442\u0435\u0441\u0442\u043e\u0432:<\/p>\n<pre><code class=\"ruby\">lane :build_tests_products do    # \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0438\u043c\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u044d\u0442\u043e\u0439 \u0434\u0436\u043e\u0431\u044b \u043b\u0435\u0436\u0430\u043b\u0438 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438    uname = \"#{Time.now.strftime(\"%Y.%m.%d_%H-%M-%S-%6N-%z\")}\"    build_for_testing(        scheme: \"AppTests\",        uname: uname    )    products = build_for_testing(        scheme: \"AppUITests\",        uname: uname    )    File.write(File.join(project_dir, \"products.txt\"), File.dirname(products))end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<pre><code class=\"ruby\">File.write(File.join(project_dir, \"products.txt\"), File.dirname(products))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u043d\u0430\u043c \u0437\u0430\u0442\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c. \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u044d\u0442\u043e \u0432\u0441\u0451 \u0434\u0435\u043b\u0430\u0442\u044c \u201c\u043f\u043e-\u0432\u0437\u0440\u043e\u0441\u043b\u043e\u043c\u0443\u201d, \u0437\u0430\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 <code>artifactory<\/code> \u043d\u0430 <code>aws<\/code> \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u043a\u0443\u0434\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0434\u0436\u043e\u0431\u044b \u0441\u0435\u0431\u0435 \u0441\u043a\u0430\u0447\u0430\u044e\u0442, \u0447\u0442\u043e \u0438\u043c \u043d\u0443\u0436\u043d\u043e. \u041d\u043e \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u043b\u0438 \u043a\u043e\u0433\u0434\u0430 \u0443 \u0432\u0430\u0441 CI \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0434\u043d\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430, \u0442\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0443\u0442 \u0436\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e \u043d\u0438\u0445 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 \u0442\u043e\u0442 \u0436\u0435 <code>artifactory<\/code>, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0430\u0439\u043b, \u0430 \u043d\u0435 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0430\u0440\u0445\u0438\u0432, \u0438 \u043f\u043e\u0442\u043e\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u0434\u043e\u043b\u0433\u043e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0444\u0430\u0439\u043b\u044b \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0443\u0436\u0435 \u043b\u0435\u0436\u0430\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u043f\u0438\u0448\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e <code>.xctestproducts<\/code> \u0432 \u0444\u0430\u0439\u043b <code>products.txt<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0430\u0447\u0435\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u0434\u0436\u043e\u0431\u043e\u0439 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432 \u0434\u0436\u043e\u0431\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 <code>.gitlab-ci.yml<\/code> \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code>iOS Build Tests Products:  extends: .testing_template  script:    - bundle exec fastlane ios build_tests_products  artifacts:    when: on_success    paths:      - products.txt    expire_in: 1 dayiOS 26.4.1 iPhone | UI Tests:  extends: .testing_template  needs: [ \"iOS Build Tests Products\" ]  script:    - bundle exec fastlane ios run_ui_tests_26_4<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 CI \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0445\u043e\u0436\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/c8\/c3\/56\/c8c356c1415e37f70c933d0d4e795204.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/c8\/c3\/56\/c8c356c1415e37f70c933d0d4e795204.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/c8\/c3\/56\/c8c356c1415e37f70c933d0d4e795204.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410 \u0444\u0430\u0439\u043b <code>products.txt<\/code> \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">cat products.txt \/Users\/user\/builds\/artifacts\/2026.04.28_13-54-47-168741-+0700<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u044d\u0442\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043d\u0430\u0448 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0441\u0442\u0430\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ea\/90\/5f\/ea905fb3a2708afcb9c136f4d2558776.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/ea\/90\/5f\/ea905fb3a2708afcb9c136f4d2558776.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/ea\/90\/5f\/ea905fb3a2708afcb9c136f4d2558776.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 <code>lane<\/code> \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>run_testing<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b, \u0440\u0430\u043d\u044c\u0448\u0435 \u043e\u043d \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043d\u0430 \u043d\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u0442\u0435\u0441\u0442\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u0443 \u043d\u0430\u0441 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 <code>lane<\/code> \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>build_tests_products<\/code> , \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c <code>lane<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 <code>-testProductPath<\/code>.<\/p>\n<pre><code class=\"ruby\">private_lane :run_testing do |options|    products_path = File.read(File.join(project_dir, \"products.txt\"))    product_path = \"#{products_path}\/#{options[:scheme]}.xctestproducts\"    scan(        testplan: options[:testplan],        # \u0412\u0430\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437-\u0437\u0430 \u0431\u0430\u0433\u0430 https:\/\/github.com\/fastlane\/fastlane\/issues\/20540        package_path: \"\",        # \u0412\u0430\u0436\u043d\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c `build` \u0444\u0430\u0437\u0443. \u041f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0444\u043b\u0430\u0433\u0430:        # - \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 skip, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f 'build test'        # - \u043a\u043e\u0433\u0434\u0430 skip, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f 'test'        skip_build: true,        # \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 `true`, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c 'test' \u0444\u043b\u0430\u0433 (\u0441\u043c\u043e\u0442\u0440\u0438 \u0432\u044b\u0448\u0435)        test_without_building: true,        destination: \"platform=iOS Simulator,id=#{options[:destination]}\",        skip_detect_devices: true,        disable_concurrent_testing: true,        derived_data_path: product_path,        xcargs: \"-testProductsPath #{product_path}\"    )end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432<\/p>\n<pre><code class=\"bash\">xcodebuild \\    -destination 'platform=iOS Simulator,id=4E015A22-1A11-4C64-8A4C-46D2285B0262' \\    -derivedDataPath \/Users\/user\/builds\/artifacts\/2026.04.28_22-34-01-946967-+0700\/AppTests.xctestproducts \\    -disable-concurrent-testing \\    -enableCodeCoverage NO \\    -testPlan 'AppTests' \\    -testProductsPath \/Users\/user\/builds\/artifacts\/2026.04.28_22-34-01-946967-+0700\/AppTests.xctestproducts \\    test-without-building<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u043d\u043e\u0432\u0430 \u0432\u0435\u0441\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0441\u0442\u043e\u0438\u043b\u043e \u043b\u0438 \u044d\u0442\u043e \u0432\u0441\u0435\u0445 \u043d\u0430\u0448\u0438\u0445 \u0443\u0441\u0438\u043b\u0438\u0439:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/4e\/7b\/0e\/4e7b0ec889570977785e631209f9ec42.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/4e\/7b\/0e\/4e7b0ec889570977785e631209f9ec42.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/4e\/7b\/0e\/4e7b0ec889570977785e631209f9ec42.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u0432 21.7% (8 \u043c\u0438\u043d\u0443\u0442 \u0438 40 \u0441\u0435\u043a\u0443\u043d\u0434 \u0432\u043c\u0435\u0441\u0442\u043e 11 \u043c\u0438\u043d\u0443\u0442, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0438 \u0432\u0437\u044f\u043b \u0441\u0440\u0435\u0434\u043d\u0435\u0435), \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430 1\/5 \u0441\u0442\u0430\u043b\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0430 \u044d\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0434\u0432\u0435 \u0441 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u043e\u0439 \u043c\u0438\u043d\u0443\u0442\u044b. \u0412 \u0434\u0435\u043d\u044c \u044d\u0442\u043e\u0442 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 MR\/PR, \u043d\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 push \u0432 \u0432\u0435\u0442\u043a\u0443. \u0418\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<hr\/>\n<h2>\u041f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432<\/h2>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430. \u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430 \u0438\u0437 <code>Fastlane<\/code>, \u0447\u0442\u043e \u043c\u0435\u043d\u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b:<\/p>\n<pre><code class=\"ruby\">private_lane :run_testing do |options|    uuid = (sh \"xcrun simctl create #{options[:SimName]} #{options[:SimDeviceType]} #{options[:SimRuntime]}\").chop    sh \"xcrun simctl boot #{uuid}\"    sh \"xcrun simctl bootstatus #{uuid}\"    begin        scan(            destination: \"platform=iOS Simulator,id=#{uuid}\",            ...        )    ensure        sh \"xcrun simctl shutdown #{uuid}\"        sh \"xcrun simctl delete #{uuid}\"    endend<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 <code>run_testing<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442 \u044d\u0442\u043e\u0442 <code>lane<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0435\u0433\u043e. \u041d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043d\u0430\u043c\u0435\u043a\u0430 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432. \u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0431\u044a\u044f\u0441\u043d\u044e, \u0432 \u0447\u0435\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430. \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u044f\u0441\u043d\u0438\u043c \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0438\u0437 \u043a\u043e\u0434\u0430 \u0432\u044b\u0448\u0435 \u0434\u043b\u044f <code>simctl<\/code>. \u041a\u0430\u043a \u0432\u044b \u0437\u043d\u0430\u0435\u0442\u0435 <code>simctl<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u043c\u0438. \u0412\u044b\u0448\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u0435\u043b\u0430\u044e\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435.<\/p>\n<ol>\n<li>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>create<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl create ${SimName} ${SimDeviceType} ${SimRuntime}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>boot<\/code> \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl boot 4E015A22-1A11-4C64-8A4C-46D2285B0262<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 <code>bootstatus<\/code> \u043b\u043e\u0447\u0438\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl bootstatus 4E015A22-1A11-4C64-8A4C-46D2285B0262<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443\u0441\u0442\u0440\u043e\u0438\u043c \u0437\u0430\u043c\u0435\u0440\u044b \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e. \u041a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u043d\u0438\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 <code>time<\/code> \u0437\u0430\u043c\u0435\u0440\u044f\u0435\u043c \u043e\u0431\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0442\u0440\u0435\u0445 <code>simctl<\/code> \u043a\u043e\u043c\u0430\u043d\u0434 <code>create<\/code> + <code>boot<\/code> + <code>bootstatus<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0436\u0434\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e:<\/p>\n<pre><code class=\"bash\">time (SIM_ID=$(xcrun simctl create \"iPhone-17-Pro-Max-Unit-Tests\" \"com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro-Max\" \"com.apple.CoreSimulator.SimRuntime.iOS-26-4\") \\    &amp;&amp; xcrun simctl boot ${SIM_ID} \\    &amp;&amp; xcrun simctl bootstatus ${SIM_ID})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<pre><code class=\"bash\">[2026-04-28 17:43:24 +0000] Status=4, isTerminal=NO, Elapsed=00:29.Waiting on System App[2026-04-28 17:43:25 +0000] Status=4, isTerminal=NO, Elapsed=00:30.Waiting on System App[2026-04-28 17:43:26 +0000] Status=4294967295, isTerminal=YES, Elapsed=00:31.Finished0.08s user 0.09s system 0% cpu 32.036 total<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u043a \u0442\u0435\u0441\u0442\u0430\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 32 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0448\u0430\u0433 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430:<\/p>\n<pre><code class=\"bash\">time (xcrun simctl boot ${SIM_ID} &amp;&amp; xcrun simctl bootstatus ${SIM_ID})<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 3 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435:<\/p>\n<pre><code class=\"bash\">Monitoring boot status for iPhone-17-Pro-Max-Unit-Tests (BC8ABA4E-2FCD-4D79-AEE3-5F9B728496B4).[2026-04-28 17:48:44 +0000] Status=1, isTerminal=NO, Elapsed=00:01.Waiting on BackBoard[2026-04-28 17:48:50 +0000] Status=4, isTerminal=NO, Elapsed=00:07.Waiting on System App[2026-04-28 17:48:52 +0000] Status=4294967295, isTerminal=YES, Elapsed=00:09.Finished( xcrun simctl boot ${SIM_ID} &amp;&amp; xcrun simctl bootstatus ${SIM_ID}; )  0.07s user 0.08s system 1% cpu 9.855 total<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0423 \u043d\u0430\u0441 \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438\u0434\u0435\u0442 3 \u0442\u0435\u0441\u0442\u0430 \u0438 3 \u0440\u0430\u0437\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440. \u0415\u0441\u043b\u0438 \u043e\u0442\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u044b\u0448\u0435, \u0442\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0434\u0430\u0435\u0442 \u043d\u0430\u043c +20 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0430 \u0434\u043b\u044f \u0442\u0440\u0435\u0445 \u0446\u0435\u043b\u0430\u044f \u043c\u0438\u043d\u0443\u0442\u0430. \u041f\u043e\u043a\u0430 \u044d\u0442\u043e \u0442\u0435\u043e\u0440\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 <code>lane<\/code> \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u043c ID \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432:<\/p>\n<pre><code class=\"bash\">lane :run_unit_tests do    run_testing(        scheme: \"AppTests\",        testplan: \"AppTests\",        destination: \"8A23906D-84CA-42FA-9703-1CA8986B11D9\"    )endlane :run_ui_tests do    run_testing(        scheme: \"AppUITests\",        testplan: \"AppUITests\",        destination: \"8A23906D-84CA-42FA-9703-1CA8986B11D9\"    )end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410 \u0438\u0437 <code>lane<\/code> \u043f\u0443\u0441\u043a\u0430\u0442\u0435\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430<\/p>\n<pre><code class=\"ruby\">private_lane :run_testing do |options|    uuid = options[:destination]    sh \"xcrun simctl boot #{uuid}\"    sh \"xcrun simctl bootstatus #{uuid}\"    begin        scan(            destination: \"platform=iOS Simulator,id=#{uuid}\",            ...        )    ensure        sh \"xcrun simctl shutdown #{uuid}\"    endend<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0443\u0448\u0438\u043c \u0432 \u0440\u0435\u043f\u043e \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043c \u0432\u0435\u0441\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0438 \u0441\u0440\u0435\u0434\u043d\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f 7 \u043c\u0438\u043d\u0443\u0442 \u0438 10 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e \u043d\u0430 1 \u043c\u0438\u043d\u0443\u0442\u0443 \u0438 30 \u0441\u0435\u043a\u0443\u043d\u0434 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 (\u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u044b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u044d\u0442\u0443 \u0446\u0438\u0444\u0440\u0443 \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b\u0438).<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/1b\/94\/3e\/1b943ee435f7105974db4a7c72478cd7.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/1b\/94\/3e\/1b943ee435f7105974db4a7c72478cd7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/1b\/94\/3e\/1b943ee435f7105974db4a7c72478cd7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0443\u0441\u043a\u043e\u0440\u0438\u043b\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0430 35.24%. \u0418\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<hr\/>\n<h2>\u0412\u044b\u0436\u0438\u043c\u0430\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432<\/h2>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433\u043e\u043c \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u043d\u043e\u0432\u0430 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u043c\u0438. \u041d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c (shutdown) \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u044b \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0445\u0438\u043d\u0442, \u043f\u043e <code>cron<\/code> \u0443 \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0436\u0434\u043e\u0435 \u0443\u0442\u0440\u043e \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u0434\u043d\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f:<\/p>\n<ol>\n<li>\n<p>\u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl shutdown all<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u0427\u0438\u0441\u0442\u0438\u0442 \u0432\u0441\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl erase all<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b \u0435\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b, \u0447\u0442\u043e\u0431\u044b, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438\u0441\u044c \u0442\u0435\u0441\u0442\u044b, \u043e\u043d\u0438 \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u201c\u043f\u0440\u043e\u0433\u0440\u0435\u0442\u044b\u201d<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0430\u0432\u0438\u043c \u043d\u0430\u0448 <code>run_testing<\/code> \u0447\u0442\u043e\u0431\u044b \u043e\u043d:<\/p>\n<ol>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d, \u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u0441\u0442\u043e\u043c<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u043b \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u043f\u043e\u0441\u043b\u0435 \u0442\u0435\u0441\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"ruby\">private_lane :run_testing do |options|    uuid = options[:destination]    is_booted = (sh \"xcrun simctl list devices booted\").include?(uuid)    unless is_booted        sh \"xcrun simctl boot #{uuid}\"        sh \"xcrun simctl bootstatus #{uuid}\"    end    scan(        destination: \"platform=iOS Simulator,id=#{uuid}\",        ...    )end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0443\u0448\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0440\u0430\u0437. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u0430\u0440\u0442\u0438\u043d\u0443:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/fe\/d8\/83\/fed883bd575a29250f73ae026d456df1.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/fe\/d8\/83\/fed883bd575a29250f73ae026d456df1.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/fe\/d8\/83\/fed883bd575a29250f73ae026d456df1.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0413\u0434\u0435 \u0441\u0440\u0435\u0434\u043d\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 6 \u043c\u0438\u043d\u0443\u0442 \u0438 8 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e \u043d\u0430 1 \u043c\u0438\u043d\u0443\u0442\u0443 \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u044b \u0443\u0441\u043a\u043e\u0440\u0438\u043b\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0430 44.58%. \u0418\u0434\u0435\u043c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<hr\/>\n<h2>\u0420\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u0434\u0436\u043e\u0431\u044b \u043f\u043e \u0440\u0430\u043d\u043d\u0435\u0440\u0430\u043c<\/h2>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0430\u043d\u0430\u043b\u0438\u0437 \u0434\u0436\u043e\u0431 \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435.<\/p>\n<ol>\n<li>\n<p>\u0421\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0434\u043e\u043b\u0433\u0430\u044f \u0438 \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0440\u0430\u0431\u043e\u0442\u0430)<\/p>\n<\/li>\n<li>\n<p>\u042e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b (\u043b\u0435\u0433\u043a\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430, \u0441\u043b\u0430\u0431\u043e \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440)<\/p>\n<\/li>\n<li>\n<p>UI \u0442\u0435\u0441\u0442\u044b (\u0442\u044f\u0436\u0435\u043b\u044b\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b)<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0437 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0438 \u0435\u0441\u043b\u0438 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441 \u0442\u044f\u0436\u0435\u043b\u043e\u0439 \u0434\u0436\u043e\u0431\u043e\u0439, \u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u043d\u0430 \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u0415\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u044f\u0436\u0435\u043b\u044b\u0435 \u0434\u0436\u043e\u0431\u044b, \u0442\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u0448\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0443, \u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u0447\u0442\u0438 \u0442\u043e\u0447\u043d\u043e UI \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u0447\u043d\u0443\u0442 \u0444\u043b\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0449\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e.<\/p>\n<p>\u041d\u0430\u0448\u0430 \u0446\u0435\u043b\u044c, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 UI \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u043d\u043d\u0435\u0440 \u043d\u0430 CI. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0440\u0430\u043d\u043d\u0435\u0440 <code>ios<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0435\u043f\u0435\u0440\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0442\u044f\u0436\u0435\u043b\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u0418 \u043d\u043e\u0432\u044b\u0439 \u0440\u0430\u043d\u043d\u0435\u0440, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u0433\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438. \u0420\u0430\u0437\u0440\u0435\u0448\u0438\u043c \u043d\u043e\u0432\u043e\u043c\u0443 \u0440\u0430\u043d\u043d\u0435\u0440\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u043e 2 \u043b\u0435\u0433\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e, \u0430 \u0441\u0442\u0430\u0440\u043e\u043c\u0443 \u0440\u0430\u043d\u043d\u0435\u0440\u0443 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u043c \u0442\u043e\u043b\u044c\u043a\u043e 1 \u0442\u044f\u0436\u0435\u043b\u0443\u044e \u0434\u0436\u043e\u0431\u0443, \u0430 \u0441\u0430\u043c\u043e\u043c\u0443 CI \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 2 \u0434\u0436\u043e\u0431\u044b \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438. \u0422\u043e \u0435\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0433\u0443\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u0431\u0438\u043d\u0430\u0446\u0438\u0438:<\/p>\n<ol>\n<li>\n<p>1 \u043b\u0435\u0433\u043a\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 + 1 \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430<\/p>\n<\/li>\n<li>\n<p>2 \u043b\u0435\u0433\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447\u0438<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u043b\u0435\u0433\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447, \u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0430 \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u043d\u043d\u0435\u0440 \u0441 \u0442\u0435\u0433\u043e\u043c <code>ios_low_load<\/code> \u0438 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 ~\/.gitlab-runner\/config.toml (\u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 GitLab):<\/p>\n<pre><code>concurrent = 2[[runners]]  name = \"ios\"  limit = 1  [[runners]]  name = \"ios_low_load\"  limit = 2<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0440\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u0442\u0438 \u0442\u0435\u0433\u0438 \u0432 <code>.gitlab-ci.yml<\/code>, \u0442\u0443\u0442 \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e, \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0440\u0430\u043d\u043d\u0435\u0440 <code>ios_low_load<\/code>, \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0440\u044b\u0439.<\/p>\n<pre><code>iOS iPhone | Unit Tests:  tags:    - ios_low_load<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0443\u0448\u0438\u043c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c. \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u044e\u0442 \u043f\u043e\u0447\u0442\u0438 30-40 \u0441\u0435\u043a\u0443\u043d\u0434, \u0432 \u0442\u0435\u043e\u0440\u0438\u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u0436\u0435.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ec\/99\/96\/ec9996b0b7538d91e4c137b719e524b9.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/ec\/99\/96\/ec9996b0b7538d91e4c137b719e524b9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/ec\/99\/96\/ec9996b0b7538d91e4c137b719e524b9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u0441\u0435\u0445 \u0437\u0430\u0434\u0430\u0447, \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c 5 \u043c\u0438\u043d\u0443\u0442 49 \u0441\u0435\u043a\u0443\u043d\u0434. \u041d\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 5 \u043c\u0438\u043d\u0443\u0442 \u0438 23 \u0441\u0435\u043a\u0443\u043d\u0434\u044b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u0447 \u0441\u0442\u0430\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e. \u0427\u0442\u043e \u0434\u0430\u043b\u043e \u043d\u0430\u043c \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u0432 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0447\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u0431\u044b \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b\u0438 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b, \u0442\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0431\u044b \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043c\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u043b\u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u043d\u0430 51.36%, \u0442\u043e \u0435\u0441\u0442\u044c \u0432 2 \u0440\u0430\u0437\u0430, \u043a\u0430\u043a \u0432\u044b \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0431\u0435\u0437 \u0432\u0441\u0435\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432\u044b\u0448\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u0431\u044b\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435 11 \u043c\u0438\u043d\u0443\u0442. \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043d\u0430 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u0442\u0430\u043f.<\/p>\n<hr\/>\n<h2>\u0420\u0430\u0441\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0432\u0430\u0435\u043c UI \u0442\u0435\u0441\u0442\u044b<\/h2>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0441\u0430\u043c\u0430\u044f \u0445\u043e\u043b\u0438\u0432\u0430\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0435 UI \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. Xcode (<code>xcodebuild<\/code> \u0435\u0441\u043b\u0438 \u0442\u043e\u0447\u043d\u0435\u0435) \u0438\u043c\u0435\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430. \u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440, \u043a\u043e\u0433\u0434\u0430 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/29\/28\/52\/292852b52e30b6ed839aab442f7c94d7.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/29\/28\/52\/292852b52e30b6ed839aab442f7c94d7.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/29\/28\/52\/292852b52e30b6ed839aab442f7c94d7.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410 \u0432\u044b\u0432\u043e\u0434 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"bash\">xcrun simctl list devices booted== Devices ==-- iOS 26.4 --    iPhone-17-Pro-Max-Unit-Tests (8A23906D-84CA-42FA-9703-1CA8986B11D9) (Booted) <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b \u043f\u0440\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/7c\/3e\/0f\/7c3e0fcc30761eecb19712ed59925e39.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/7c\/3e\/0f\/7c3e0fcc30761eecb19712ed59925e39.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/7c\/3e\/0f\/7c3e0fcc30761eecb19712ed59925e39.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430 \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432:<\/p>\n<pre><code class=\"bash\">xcrun simctl list devices booted== Devices ==-- iOS 26.4 --<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a. \u0418\u0437 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0430 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b, \u0430 \u043a\u043b\u043e\u043d\u044b \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0447\u0435\u0440\u0435\u0437 <code>-destination<\/code>. \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u0438 \u0441\u0438\u043c\u0443\u044f\u043b\u0442\u043e\u0440\u044b \u043d\u0435 \u0442\u0440\u0435\u043a\u0430\u044e\u0442\u0441\u044f <code>simctl<\/code>, \u0442\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u043c\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0435\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 <code>simctl<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u044d\u043a\u0440\u0430\u043d\u0430, \u043c\u044b \u044d\u0442\u043e\u0433\u043e \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d UDID \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430.<\/p>\n<p>\u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u044c, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0430\u043c\u0435\u0442\u0438\u043b, \u0447\u0442\u043e \u0432 <code>fastlane<\/code> \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445 \u0432\u044b\u0448\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <code>disable_concurrent_testing: true<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043b\u044f <code>xcodebuild<\/code> \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 <code>-disable-concurrent-testing<\/code> \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u044b \u0447\u0435\u0440\u0435\u0437 <code>testPlan<\/code>, \u0430 <code>testPlan<\/code> \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043e\u043d\u0430 \u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430\u0434 <code>-disable-concurrent-testing<\/code>. \u041c\u044b \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433 \u0432 <code>fastlane<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044c, \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u0441\u0442 \u043d\u0435 \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c, \u0445\u043e\u0442\u044f \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 <code>testPlan<\/code> \u0432\u043e\u0442 \u0442\u0443\u0442:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ba\/4b\/88\/ba4b88447c71739d1817b795c8c3b1dc.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/ba\/4b\/88\/ba4b88447c71739d1817b795c8c3b1dc.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/ba\/4b\/88\/ba4b88447c71739d1817b795c8c3b1dc.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0438\u0448\u0435\u043c \u043a\u0430\u043a Xcode \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 (\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0432 <code>testPlan<\/code>). \u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code class=\"bash\">xcodebuild \\-destination 'platform=iOS Simulator,id=8A23906D-84CA-42FA-9703-1CA8986B11D9' \\-testPlan 'UITests-iPhone' \\-testProductsPath AppUITests.xctestproducts \\test-without-building<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol>\n<li>\n<p><code>xcodebuild<\/code> \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 (8A23906D-84CA-42FA-9703-1CA8986B11D9) \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u043f\u0443\u0449\u0435\u043d<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u043a\u043b\u043e\u043d\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u043c \u0435\u0441\u043b\u0438 \u044f\u0432\u043d\u043e \u043d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 (<code>-parallel-testing-worker-count N<\/code>) (\u0433\u0434\u0435 N &#8212; \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043b\u043e\u043d\u043e\u0432):<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"bash\">xcrun simctl clone 8A23906D-84CA-42FA-9703-1CA8986B11D9 \"Clone ${N} ${DEVICE_NAME}\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u043a\u043b\u043e\u043d\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043b\u043e\u043d\u044b \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0430\u044e\u0442\u0441\u044f (\u0438\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443 \u043d\u0438\u0445 \u043d\u0435\u0442 UDID)<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430 \u0431\u0430\u0437\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0432\u044b\u0432\u043e\u0434\u044b, \u0433\u0434\u0435 \u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u043e\u043d\u044b \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 UDID \u0438 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0438\u043c\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u043e\u043d\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f, \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c pool \u043a\u043b\u043e\u043d\u043e\u0432 \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u044d\u0442\u043e \u0442\u044f\u0436\u0435\u043b\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f CPU (\u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 <code>htop<\/code> \u0438 \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 <code>boot<\/code> \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0443). \u0412\u043e\u0442 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0441 \u043c\u043e\u0449\u043d\u043e\u0439 <code>M<\/code> \u043c\u0430\u0448\u0438\u043d\u044b, \u0442\u0443\u0442 <code>xcodebuild<\/code> \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043b\u043e\u043d\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432:<\/p>\n<\/li>\n<\/ol>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/fc\/cd\/79\/fccd7985f78e1c564c804b12f17773c9.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/fc\/cd\/79\/fccd7985f78e1c564c804b12f17773c9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/fc\/cd\/79\/fccd7985f78e1c564c804b12f17773c9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0410 \u0432\u0435\u0434\u044c \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c 4-5-6 \u043a\u043b\u043e\u043d\u043e\u0432 (\u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0443\u0441\u0442\u043e\u044f\u0432\u0448\u0435\u0435\u0441\u044f \u043a\u043e\u043b-\u0432\u043e \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0444\u043b\u0430\u043a\u0443\u044e\u0442), \u0438 \u0437\u0430\u043f\u0443\u0441\u043a \u044d\u0442\u0438\u0445 4-6 \u043a\u043b\u043e\u043d\u043e\u0432 \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0441\u044a\u0435\u0434\u0430\u044e\u0442 \u043e\u0442 3 \u0434\u043e 5 \u043c\u0438\u043d\u0443\u0442 \u043f\u0440\u0435\u0436\u0434\u0435, \u0447\u0435\u043c \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u044b \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432, \u0442\u043e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0431\u044b\u0432\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439, \u0447\u0442\u043e \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u043a\u043b\u043e\u043d\u0435 \u0442\u0435\u0441\u0442\u044b \u0443\u0436\u0435 \u043f\u0440\u043e\u0448\u043b\u0438, \u0430 \u0447\u0435\u0442\u0432\u0435\u0440\u0442\u044b\u0439 \u0438\u043b\u0438 \u043f\u044f\u0442\u044b\u0439 \u0435\u0449\u0435 \u0434\u0430\u0436\u0435 \u043d\u0435 \u043f\u0440\u043e\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c.<\/p>\n<p>\u041d\u043e \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u044d\u0442\u043e \u0432\u0441\u0451 \u0442\u0435\u043e\u0440\u0438\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043c\u0435\u0440\u044b.<\/p>\n<ol>\n<li>\n<p>\u0422\u0435\u0441\u0442\u044b \u0431\u0435\u0437 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d\u0430 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0437\u044f\u0442\u044c \u0438\u0437 \u0434\u0436\u043e\u0431, \u0447\u0442\u043e \u043c\u044b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043b\u0438 \u0432\u044b\u0448\u0435, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u044b\u043b 2 \u043c\u0438\u043d\u0443\u0442\u044b \u0438 10 \u0441\u0435\u043a\u0443\u043d\u0434<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u044b \u0441 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0436\u0438\u043c\u043e\u043c. \u041d\u0430\u0448 \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0435\u0433\u043e 2 \u0442\u0435\u0441\u0442\u0430 (2 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 XCTest \u043a\u043b\u0430\u0441\u0441\u0430), \u043d\u043e \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c. \u0412 <code>fastlane<\/code> \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c <code>concurrent_workers: 2<\/code> \u0447\u0442\u043e\u0431\u044b \u0442\u043e\u0447\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u043e\u0441\u044c \u043d\u0443\u0436\u043d\u043e\u0435 \u043d\u0430\u043c \u043a\u043e\u043b-\u0432\u043e \u043a\u043b\u043e\u043d\u043e\u0432-\u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432. \u0414\u0432\u0430 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u0432\u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"ruby\">private_lane :run_testing do |options|  scan(    concurrent_workers: 2,    ...  )end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<pre><code class=\"bash\">xcodebuild \\    -destination 'platform=iOS Simulator,id=8A23906D-84CA-42FA-9703-1CA8986B11D9' \\    -derivedDataPath AppUITests.xctestproducts \\    -parallel-testing-worker-count 2 \\    -testPlan 'AppUITests' \\    -testProductsPath AppUITests.xctestproducts \\    test-without-building <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/a1\/73\/bf\/a173bf843f697693da0377b997ef7083.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/a1\/73\/bf\/a173bf843f697693da0377b997ef7083.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/a1\/73\/bf\/a173bf843f697693da0377b997ef7083.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>2 \u043c\u0438\u043d\u0443\u0442\u044b \u0438 30 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0435. \u042d\u0442\u043e\u043c\u0443 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 &#8212; \u0432\u0440\u0435\u043c\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043b\u043e\u043d\u043e\u0432 \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u043e\u0435, \u0447\u0442\u043e \u043d\u0438\u0432\u0435\u043b\u0438\u0440\u0443\u0435\u0442 \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0444\u0438\u0442 \u043e\u0442 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 (\u043d\u043e \u0442\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043c\u0430\u043b\u043e\u0433\u043e \u043a\u043e\u043b-\u0432\u0430 \u0442\u0435\u0441\u0442\u043e\u0432, \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430\u0445 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0433\u0440\u0435\u0448\u043d\u043e\u0441\u0442\u044c \u0438 \u0442\u0430\u043c \u0443\u0436\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438)<\/p>\n<ol start=\"3\">\n<li>\n<p>\u0414\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043c\u0435\u0440 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043d\u043e \u0440\u0443\u0447\u043d\u043e\u0433\u043e:<\/p>\n<\/li>\n<\/ol>\n<ul>\n<li>\n<p>\u0412\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0432 \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0441\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u043c \u0443\u0436\u0435 \u043f\u0440\u043e\u0433\u0440\u0435\u0442\u044b\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0430\u043c\u0438\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0441\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b \u043f\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u043c. \u0412 \u0442\u0435\u043e\u0440\u0438\u0438 \u0440\u0430\u0441\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043f\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u043c \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u0445\u043e\u0434\u0443 \u0443 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"ruby\">lane :run_ui_tests do |options|    thread1 = Thread.new do        scan(            destination: \"platform=iOS Simulator,id=#{SIMULATOR_1}\",            only_testing: [                \"UITest-1\",                \"UITest-2\",            ]        )    end    thread2 = Thread.new do        scan(            destination: \"platform=iOS Simulator,id=#{SIMULATOR_2}\",            only_testing: [                \"UITest-3\",                \"UITest-4\",            ]        )    end    thread1.join    thread2.joinend<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, <code>fastlane<\/code> \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0437 <code>fastlane<\/code> \u043d\u0430 <code>bash<\/code>:<\/p>\n<pre><code class=\"ruby\">lane :run_ui_tests do |options|    scan(        destination: \"platform=iOS Simulator,id=#{options[:destination]}\",        only_testing: options[:only_testing].split(\",\"),        disable_concurrent_testing: true    )end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<pre><code class=\"bash\">fastlane ios run_ui_tests destination:${SIM_1} only_testing:'UITest-1,UITest-2' &amp; \\    fastlane ios run_ui_tests destination:${SIM_2} only_testing:'UITest-3,UITest-4' &amp; \\    wait<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u043e\u0433\u0440\u0435\u0442\u044b\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b, \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0435 \u0432\u0440\u0435\u043c\u044f 1 \u043c\u0438\u043d\u0443\u0442\u0430 \u0438 38 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e \u043d\u0430 24.62% \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043d\u0435\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430 \u0438 \u043d\u0430 34.66% \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430 \u0441 \u0445\u043e\u043b\u043e\u0434\u043d\u044b\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u043c \u043a\u043b\u043e\u043d\u043e\u0432.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/c7\/59\/fc\/c759fcdccda485f4f9b9717829d836fd.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/c7\/59\/fc\/c759fcdccda485f4f9b9717829d836fd.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/c7\/59\/fc\/c759fcdccda485f4f9b9717829d836fd.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0418\u0437 \u0447\u0435\u0433\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0432\u044b\u0432\u043e\u0434, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0432\u044b\u0436\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432, \u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u0440\u0443\u0447\u043d\u043e\u043c\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u0443\u0436\u0435 \u043f\u0440\u043e\u0433\u0440\u0435\u0442\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445. \u0423\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u0435 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430 \u043d\u0430 3-5 \u043c\u0438\u043d\u0443\u0442 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c, \u043d\u043e, \u0435\u0441\u043b\u0438 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0440\u0430\u0437 \u0437\u0430 \u0434\u0435\u043d\u044c, \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0443\u0436\u0435 \u0438\u0434\u0435\u0442 \u043d\u0430 \u0447\u0430\u0441\u044b.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 CI, \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 <a href=\"https:\/\/github.com\/MarathonLabs\/marathon\" rel=\"noopener noreferrer nofollow\">Maraphon<\/a>. \u041f\u043e \u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043e\u043d\u0438 \u043a\u0430\u043a \u0440\u0430\u0437 \u0440\u0435\u0448\u0430\u044e\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 \u0445\u043e\u043b\u043e\u0434\u043d\u044b\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u043c \u043a\u043b\u043e\u043d\u043e\u0432, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043b\u043e\u043d\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0438 \u043a\u0435\u0448\u0438\u0440\u0443\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u044b.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435:<\/p>\n<p>\u0411\u044b\u043b\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u0430\u043a\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430 UI \u0442\u0435\u0441\u0442\u044b. \u0412\u0440\u0435\u043c\u044f \u0435\u0435 \u043f\u0440\u043e\u0433\u043e\u043d\u0430 \u0431\u044b\u043b\u043e \u043e\u043a\u043e\u043b\u043e 30 \u043c\u0438\u043d\u0443\u0442 (4 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430 \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u043e\u043d\u044b, \u0431\u043e\u043b\u044c\u0448\u0435 CI \u043d\u0435 \u0442\u044f\u043d\u0443\u043b). \u0422\u0435\u0441\u0442\u043e\u0432 \u0431\u044b\u043b\u043e \u0438 \u043f\u0440\u0430\u0432\u0434\u0430 \u043c\u043d\u043e\u0433\u043e &#8212; \u0441\u043e\u0442\u043d\u044f-\u0434\u0432\u0435. \u0414\u0436\u043e\u0431\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430\u0441\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e (\u0434\u043e 10 \u0440\u0430\u0437 \u0432 \u0434\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e, \u0430 \u0435\u0441\u043b\u0438 \u0440\u0435\u043b\u0438\u0437 \u0438 \u0442\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435). \u041f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0432 \u0447\u0430\u0442\u0435 \u0431\u044b\u043b\u043e, \u0447\u0442\u043e QA \u0436\u0434\u0451\u0442, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0431\u0440\u0430\u0442\u044c \u0431\u0438\u043b\u0434 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443, \u0434\u0430 \u0438 \u0441\u0430\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0436\u0434\u0430\u043b\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e UI \u0442\u0435\u0441\u0442\u044b \u0433\u0440\u0443\u0437\u0438\u043b\u0438 \u0441\u0438\u043b\u044c\u043d\u043e CI, \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0448\u044c.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0443\u043d\u043a\u0442\u043e\u0432, \u0447\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u044b\u0448\u0435 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435, \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043d\u0438\u0437\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u0441 30 \u043c\u0438\u043d\u0443\u0442 \u0434\u043e 12-15 \u043c\u0438\u043d\u0443\u0442 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043c\u043d\u044e. \u041f\u043e\u0441\u043b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044b\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0438 \u0432 \u0434\u0440\u0443\u0433\u0438\u0435 UI \u0442\u0435\u0441\u0442\u044b, \u0438 \u0434\u0430\u0436\u0435 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u044b \u043d\u0430\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437, \u043f\u043e\u0442\u043e\u043c \u0447\u0442\u043e \u043c\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0442\u0443\u043b\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430 \u043b\u0435\u0442\u0443 \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u043b\u0430 \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d\u043e\u0432 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430 \u0438\u0445 \u043d\u0430 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0445 \u043f\u0440\u043e\u0433\u0440\u0435\u0442\u044b\u0445 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445. \u042f \u043f\u043e\u0442\u043e\u043c \u0434\u0435\u043b\u0430\u043b \u0440\u0430\u0441\u0447\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0438 \u0438\u0445 \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 CI. \u0418 \u0443 \u043c\u0435\u043d\u044f \u0432\u044b\u0445\u043e\u0434\u0438\u043b\u043e, \u0447\u0442\u043e \u0442\u0435\u0441\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0438\u0441\u044c \u0437\u0430 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043d\u0435 \u0431\u044b\u043b\u043e \u043f\u043e\u0442\u0435\u0440\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430 \u0447\u0442\u043e-\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0435 \u043a\u0440\u043e\u043c\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 (\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0438 \u043f\u0440\u043e\u0447\u0435\u0435). \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0448\u043b\u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043a \u0442\u0430\u043a\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e, \u0447\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0436\u0435 \u043d\u0435\u0447\u0435\u0433\u043e \u0431\u044b\u043b\u043e \u0443\u043b\u0443\u0447\u0448\u0430\u0442\u044c. \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0435\u0434\u0435\u043b \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043b\u0435\u0433\u043a\u043e \u044d\u0442\u043e \u0441\u0443\u043c\u043c\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430, \u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 \u043a\u043e\u043b-\u0432\u043e \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u043e\u0432, \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c \u0438\u0437 <code>.xcresult<\/code>. \u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u0436\u043e\u0431\u044b\/\u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0430, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0443\u0431\u0440\u0430\u0442\u044c \u044d\u0442\u043e\u0442 bottle neck.<\/p>\n<hr\/>\n<h2>\u0411\u043e\u043d\u0443\u0441, \u043a\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b \u0434\u043e \u043a\u043e\u043d\u0446\u0430, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 .xctestproducts<\/h2>\n<p>\u042d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u043e\u0447\u0435\u043d\u044c \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 DerivedData \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0430\u0447\u0435. \u0414\u0438\u0440\u0435\u043a\u0442\u0440\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u0438, \u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0435 \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d\u044b, \u0447\u0442\u043e \u0435\u0441\u0442\u044c <code>${TESTPLAN_NAME}.xctestrun<\/code>, \u0447\u0442\u043e \u0438\u0437 \u0441\u0435\u0431\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 <code>plist<\/code> \u0444\u0430\u0439\u043b. \u041f\u0440\u0438\u0447\u0435\u043c \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u0430, \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u043d\u043e\u0432\u0430 \u043f\u0435\u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>testplan<\/code>, \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0439 <code>.xctestrun<\/code>. \u041f\u043e\u043a\u0430\u0436\u0443 \u043f\u0430\u0440\u0443 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0441\u0430\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b:<\/p>\n<p>\u0412 <code>.xctestrun<\/code> \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;key&gt;CommandLineArguments&lt;\/key&gt;&lt;array&gt;    &lt;string&gt;-AppleLanguages&lt;\/string&gt;    &lt;string&gt;(en)&lt;\/string&gt;    &lt;string&gt;-AppleTextDirection&lt;\/string&gt;    &lt;string&gt;NO&lt;\/string&gt;    &lt;string&gt;-AppleLocale&lt;\/string&gt;    &lt;string&gt;en_US&lt;\/string&gt;&lt;\/array&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u0442\u0435\u0441\u0442\u044b) \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438 \u043c\u0435\u043d\u044f\u044f <code>.xctestrun<\/code> \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0442\u044c \u0442\u0435\u0441\u0442\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0444\u0440\u0430\u043d\u0446\u0443\u0437\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c:<\/p>\n<pre><code class=\"xml\">&lt;key&gt;CommandLineArguments&lt;\/key&gt;&lt;array&gt;    &lt;string&gt;-AppleLanguages&lt;\/string&gt;    &lt;string&gt;(fr)&lt;\/string&gt;    &lt;string&gt;-AppleTextDirection&lt;\/string&gt;    &lt;string&gt;NO&lt;\/string&gt;    &lt;string&gt;-AppleLocale&lt;\/string&gt;    &lt;string&gt;fr_FR&lt;\/string&gt;&lt;\/array&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;key&gt;OnlyTestIdentifiers&lt;\/key&gt;&lt;array&gt;    &lt;string&gt;UITest1\/test()&lt;\/string&gt;    &lt;string&gt;UITest2\/test()&lt;\/string&gt;&lt;\/array&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b. \u041c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u043f\u0438\u0441\u0430\u043b\u0438 \u043c\u0438\u043d\u0438 \u0442\u0443\u043b\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0435\u0440\u0435\u0442 \u043e\u0442\u0441\u044e\u0434\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0435\u0441\u0442\u043e\u0432, \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u0442 \u0438\u0445 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f (\u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u0437\u0430 \u043e\u0434\u043d\u043e \u0432\u0440\u0435\u043c\u044f), \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 \u043f\u043b\u0430\u043d \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435.<\/p>\n<p>\u0418 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f:<\/p>\n<pre><code class=\"xml\">&lt;key&gt;EnvironmentVariables&lt;\/key&gt;&lt;dict&gt;    &lt;key&gt;LOCAL_PORT&lt;\/key&gt;    &lt;string&gt;8000&lt;\/string&gt;&lt;\/dict&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0435\u0440\u0435\u0437 <code>EnvironmentVariables<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c <code>port<\/code> \u0434\u043b\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043a\u0430\u043a \u0447\u0435\u0440\u0435\u0437 <code>testplan<\/code>, \u0442\u0430\u043a \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0447\u0435\u0440\u0435\u0437 <code>.xctestrun<\/code>. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e CI \u0438 \u0432\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 CI <code>.xctestproducts<\/code>, \u0442\u043e \u0441\u0431\u043e\u0440\u0449\u0438\u043a, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u043d\u0438\u0439, \u043a\u0430\u043a\u043e\u0439 <code>port<\/code> \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u043c <code>testplan<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0436\u0435 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0443\u0442.<\/p>\n<hr\/>\n<p>\u0426\u0435\u043b\u044c \u0441\u0442\u0430\u0442\u044c\u0438:<\/p>\n<ol>\n<li>\n<p>\u041d\u0435 \u0440\u0430\u0441\u0442\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0421\u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u043d\u0438\u044f \u0432 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u0432\u0438\u0434 (\u0434\u043e \u044d\u0442\u043e\u0433\u043e \u044d\u0442\u043e \u043b\u0435\u0436\u0430\u043b\u043e \u043a\u0443\u0441\u043a\u0430\u043c\u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c<\/p>\n<\/li>\n<li>\n<p>\u0421\u0435\u0431\u0435 \u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0430 \u0434\u043b\u044f \u0431\u0443\u0434\u0443\u0449\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0432\u0441\u0435\u043c, \u043a\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b. \u041d\u0430\u0434\u0435\u044e\u0441\u044c \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0418\u0418 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f, \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043f\u0435\u043b\u0447\u0435\u043a\u043a\u0435\u0440 \u0434\u043b\u044f \u0440\u0443\u0441\u0441\u043a\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 IntelliJ Idea.<\/p>\n<\/div>\n<p>\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\/1030150\/\">https:\/\/habr.com\/ru\/articles\/1030150\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0420\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u043f\u0440\u043e \u043d\u0430\u0448 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 fastlane, \u0435\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u043e\u043c \u043f\u043e Maraphon \u0438\u043b\u0438 Emcee, \u0442\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043c\u043e\u0438 \u0441\u043e\u0432\u0435\u0442\u044b \u0434\u043b\u044f \u0432\u0430\u0441 \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u0434\u043d\u044b\u043c\u0438 \/ \u043d\u0435\u043b\u0435\u043f\u044b\u043c\u0438 \/ \u0438 \u043f\u043e\u0440\u043e\u0439 \u0434\u0430\u0436\u0435 \u0437\u0430\u0431\u044b\u0432\u043d\u044b\u043c\u0438 &#8212; \u043d\u0435 \u043e\u0431\u0435\u0441\u0441\u0443\u0434\u044c\u0442\u0435.\u041d\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0445\u043e\u0447\u0443 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0434\u0432\u0435 \u043e\u0442\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0441\u0445\u043e\u0436\u0438\u0435 \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u043e\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0433\u043e \u0436\u0435 \u0430\u0432\u0442\u043e\u0440\u0430, \u043e\u0447\u0435\u043d\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0441 \u043d\u0438\u043c\u0438 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f:\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 iOS UI-\u0442\u0435\u0441\u0442\u043e\u0432. \u0427\u0430\u0441\u0442\u044c 1. \u0417\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 iOS UI-\u0442\u0435\u0441\u0442\u043e\u0432. \u0427\u0430\u0441\u0442\u044c 2. \u0420\u0430\u0441\u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u0418 \u0432\u043e\u0442 \u0447\u0442\u043e \u044f \u0443\u0432\u0438\u0434\u0435\u043b \u0432 Fastfile\u0412 Fastfile \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e, \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0435\u0441\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 scan. \u041d\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u043f\u0438\u0448\u0443 \u0438\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043f\u0438\u0441\u043a\u0430:iOS \u043f\u0440\u043e\u0435\u043a\u0442 (Swift + SwiftUI + UIKit + SwiftPM)\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u041e\u0421 (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e iOS 26.4.1)\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f UI \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u043b\u044f iOS 18.6 (UI \u0434\u043b\u044f iOS 26 \u0438 18 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0435 \u0432\u0435\u0440\u0441\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0440\u0435\u0441\u0441\u0438\u0438 \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0445 \u043e\u0441\u044f\u0445)\u0414\u0436\u043e\u0431\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0438\u0434\u0443\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e (\u0434\u043b\u044f GitLab concurrent = 1)\u0418\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e \u043d\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043c\u0435\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u043e\u0433\u0434\u0430 \u0431\u044b \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u044b\u0448\u043b\u043e \u0431\u044b \u0432 \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u043b\u0433\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043d\u043e \u0438\u0441\u043f\u044b\u0442\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u0431\u043e\u0435\u0432\u043e\u0439 \u043f\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0430\u0436\u043d\u043e\u0435 \u043f\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 CI\u0412\u043e\u0442 \u0442\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0434\u0436\u043e\u0431\u044b \u0432 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u043d\u0430 CI, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u0440\u0435\u0445 \u0432\u0438\u0434\u043e\u0432 \u0442\u0435\u0441\u0442\u043e\u0432:\u0410 fastlane \u0441\u043b\u0443\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: private_lane :run_testing do |options|    scan(        project: project,        scheme: options[:scheme],        testplan: options[:testplan],        destination: &#171;platform=iOS Simulator,id=#{options[:uuid]}&#187;,        skip_detect_devices: true,        code_coverage: false,        derived_data_path: derived_data_path,        disable_concurrent_testing: true    )end  lane :run_unit_tests do    run_testing(scheme: &#171;AppTests&#187;, testplan: &#171;UnitTests&#187;, uuid: &#171;123..&#187;)  end  lane :run_ui_tests_26_4 do    run_testing(scheme: &#171;AppUITests&#187;, testplan: &#171;UITests&#187;, uuid: &#171;123..&#187;)  end  lane :run_ui_tests_18_6 do    run_testing(scheme: &#171;AppUITests&#187;, testplan: &#171;UITests&#187;, uuid: &#171;456..&#187;)  end\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0443\u0441\u043a\u0430\u0442\u0435\u043b\u044c \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0435\u0437 \u0438\u0437\u043b\u0438\u0448\u0435\u0441\u0442\u0432 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u0442\u043e\u0440\u043e\u043c \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0435 \u043f\u0440\u043e fastlane, \u0433\u0434\u0435 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f xcodebuild \u043a\u043e\u043c\u0430\u043d\u0434\u0430:xcodebuild \\    -scheme AppTests \\    -project App.xcodeproj \\    -derivedDataPath DerivedData\/App-biooakmzntobceawoboqmizvekct \\    -destination &#8216;platform=iOS Simulator,id=5F53A860-544D-4A6F-9F1A-C414CC89DDA5&#8217; \\    -disable-concurrent-testing \\    -enableCodeCoverage NO \\    -testPlan &#8216;AppTests&#8217; \\    build test\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0442\u0435\u0441\u0442\u044b \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:\u0421\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u0448\u043b\u043e 11 \u043c\u0438\u043d\u0443\u0442 \u0438 4 \u0441\u0435\u043a\u0443\u043d\u0434\u044b (\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0438 \u0432\u0437\u044f\u043b \u0441\u0440\u0435\u0434\u043d\u0435\u0435), \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0441\u0447\u0435\u0442\u0430 \u0434\u043e \u043d\u0430\u0448\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c, \u0432\u0441\u0435 \u0442\u0440\u0438 \u0434\u0436\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438\u043d\u043e\u0433\u0434\u0430 \u0441\u0431\u043e\u0440\u043a\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043a\u0435\u0448 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f, \u0438\u043d\u043e\u0433\u0434\u0430 \u043d\u0430 \u0440\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435 SwiftPM \u0433\u043b\u044e\u0447\u0438\u0442 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0434\u0436\u043e\u0431\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043f\u043e\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0430\u0441\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0434\u0436\u043e\u0431\u0430\u043c. \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0431\u0443\u0434\u0435\u0442 \u043b\u0438 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0442\u043e\u043b\u043a.\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u0438 \u0440\u0430\u0437\u0434\u0430\u0435\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0444\u043b\u0430\u0433 -testProductsPath \u0438\u0437 Xcode 13.3, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u0430\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:xcodebuild now supports an .xctestproducts bundle format for the build-for-testing and test-without-building actions. Using a bundle makes it easier to run tests, particularly when transporting tests between systems. Use the new -testProductsPath argument to set the path to the bundle.\u041f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u043a\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u043b\u0430\u0433 build-for-testing \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c DerivedData, xcodebuild \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e .xctestproducts \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u043e\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 -testProductsPath + test-without-building \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432.Lane \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  private_lane :build_for_testing do |options|    # \u0441\u043e\u0437\u0434\u0430\u0435\u043c `.xctestproducts` \u043f\u0440\u044f\u043c \u0432 DerivedData \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438    product_path = &#171;#{File.join(derived_data_path, &#171;#{options[:scheme]}&#187;)}.xctestproducts&#187;    scan(      project: project,      scheme: options[:scheme],      sdk: &#171;iphonesimulator&#187;,      destination: &#171;generic\/platform=iOS Simulator&#187;,      # \u0422\u0443\u0442 \u0432\u0430\u0436\u043d\u043e \u044d\u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c `true`      build_for_testing: true,      code_coverage: false,      derived_data_path: derived_data_path,      # \u0422\u0430\u043a \u043a\u0430\u043a fastlane \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 `-testProductsPath` \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0447\u0435\u0440\u0435\u0437 `xcargs`      xcargs: &#171;-testProductsPath #{product_path}&#187;    )    # \u0422\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 `.xctestproducts` \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438,    # \u0442\u043e \u043c\u044b \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043b\u0438\u0448\u043d\u0435\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u0443\u0441\u043a\u0430\u0442\u0435\u043b\u044c UI \u0442\u0435\u0441\u0442\u043e\u0432    tests_files = [      &#171;App.app&#187;,      &#171;AppUITests-Runner.app&#187;    ]    derived_data = File.join(product_path, &#171;Binaries\/0\/Debug-iphonesimulator&#187;)    Dir.children(derived_data).each do |name|      if tests_files.any?(name)        next      else        path = &#171;#{derived_data}\/#{name}&#187;        if File.directory?(path)          FileUtils.rm_rf(path)        else          File.delete(path)        end      end    end    # \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432, \u044d\u0442\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441\u0431\u043e\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c    # \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u0434\u0436\u043e\u0431\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 `-testProductsPath` \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0442\u0435\u0441\u0442\u043e\u0432    artifacts_path = File.join(ENV[&#171;HOME&#187;], &#171;builds\/artifacts\/#{options[:uname]}&#187;)    if !File.exist?(artifacts_path)      Dir.mkdir(artifacts_path)    end    # \u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c `.xctestproducts` \u0438\u0437 Xcode DerivedData \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b    FileUtils.mv(product_path, artifacts_path)    # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e `.xctestproducts` \u0438\u0437 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432    File.join(artifacts_path, File.basename(product_path))  end\u041c\u044b \u043e\u043f\u0438\u0441\u0430\u043b\u0438 lane \u043a\u043e\u0442\u043e\u0440\u044b\u0439:\u0421\u043e\u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 ${SCHEME}.xctestproducts \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u041f\u043e\u043c\u0435\u0441\u0442\u0438\u0442 ${SCHEME}.xctestproducts \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b (\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 \u043d\u0430 CI)\u0412\u0435\u0440\u043d\u0435\u0442 \u0438\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0443\u0442\u044c \u0434\u043e ${SCHEME}.xctestproducts \u0432 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u0445\u0412 \u043c\u043e\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u044d\u0442\u043e\u0442 lane \u0432\u0435\u0440\u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430 \u043f\u0443\u0442\u044c $HOME\/builds\/artifacts\/2026.04.28_01-44-11-883074-+0700\/${SCHEME}.xctestproducts. \u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c xcodebuild \u043a\u043e\u043c\u043d\u0430\u0434\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 (.xctestproducts) \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:xcodebuild \\    -scheme AppTests \\    -project App.xcodeproj \\    -derivedDataPath DerivedData\/App-biooakmzntobceawoboqmizvekct \\    -sdk &#8216;iphonesimulator&#8217; \\    -destination &#8216;generic\/platform=iOS Simulator&#8217; \\    -enableCodeCoverage NO \\    -testProductsPath DerivedData\/App-biooakmzntobceawoboqmizvekct\/AppTests.xctestproducts \\    build-for-testing\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c lane, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u0434\u043b\u044f \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 UI \u0442\u0435\u0441\u0442\u043e\u0432:lane :build_tests_products do    # \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0438\u043c\u044f, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u044d\u0442\u043e\u0439 \u0434\u0436\u043e\u0431\u044b \u043b\u0435\u0436\u0430\u043b\u0438 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438    uname = &#171;#{Time.now.strftime(&#171;%Y.%m.%d_%H-%M-%S-%6N-%z&#187;)}&#187;    build_for_testing(        scheme: &#171;AppTests&#187;,        uname: uname    )    products = build_for_testing(        scheme: &#171;AppUITests&#187;,        uname: uname    )    File.write(File.join(project_dir, &#171;products.txt&#187;), File.dirname(products))end\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u0442\u0440\u043e\u043a\u0443:File.write(File.join(project_dir, &#171;products.txt&#187;), File.dirname(products))\u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0434\u0436\u043e\u0431\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u043d\u0430\u043c \u0437\u0430\u0442\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u043c. \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u044d\u0442\u043e \u0432\u0441\u0451 \u0434\u0435\u043b\u0430\u0442\u044c \u201c\u043f\u043e-\u0432\u0437\u0440\u043e\u0441\u043b\u043e\u043c\u0443\u201d, \u0437\u0430\u0430\u0440\u0445\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 artifactory \u043d\u0430 aws \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u043a\u0443\u0434\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u0434\u0436\u043e\u0431\u044b \u0441\u0435\u0431\u0435 \u0441\u043a\u0430\u0447\u0430\u044e\u0442, \u0447\u0442\u043e \u0438\u043c \u043d\u0443\u0436\u043d\u043e. \u041d\u043e \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0438\u043b\u0438 \u043a\u043e\u0433\u0434\u0430 \u0443 \u0432\u0430\u0441 CI \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0434\u043d\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430, \u0442\u043e \u043f\u0440\u043e\u0449\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0443\u0442 \u0436\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e \u043d\u0438\u0445 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432 \u0442\u043e\u0442 \u0436\u0435 artifactory, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0444\u0430\u0439\u043b, \u0430 \u043d\u0435 \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0430\u0440\u0445\u0438\u0432, \u0438 \u043f\u043e\u0442\u043e\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u0434\u043e\u043b\u0433\u043e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u0444\u0430\u0439\u043b\u044b \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u0443\u0436\u0435 \u043b\u0435\u0436\u0430\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0435.\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u043f\u0438\u0448\u0435\u043c \u043f\u0443\u0442\u044c \u0434\u043e .xctestproducts \u0432 \u0444\u0430\u0439\u043b products.txt, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 \u043a\u043e\u0440\u0435\u043d\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043a\u0430\u0447\u0435\u043d\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0439 \u0434\u0436\u043e\u0431\u043e\u0439 \u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0432 \u0434\u0436\u043e\u0431\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 .gitlab-ci.yml \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:iOS Build Tests Products:  extends: .testing_template  script:    &#8212; bundle exec fastlane ios build_tests_products  artifacts:    when: on_success    paths:      &#8212; products.txt    expire_in: 1 dayiOS 26.4.1 iPhone | UI Tests:  extends: .testing_template  needs: [ &#171;iOS Build Tests Products&#187; ]  script:    &#8212; bundle exec fastlane ios run_ui_tests_26_4\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044f \u0441\u043e \u0441\u0431\u043e\u0440\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 CI \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0445\u043e\u0436\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440:\u0410 \u0444\u0430\u0439\u043b products.txt \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435:cat products.txt \/Users\/user\/builds\/artifacts\/2026.04.28_13-54-47-168741-+0700\u041f\u043e\u0441\u043b\u0435 \u043a\u043e\u043c\u043c\u0438\u0442\u0430 \u044d\u0442\u0438\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u043d\u0430\u0448 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d \u0441\u0442\u0430\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 lane \u0441 \u0438\u043c\u0435\u043d\u0435\u043c run_testing \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0435\u0441\u0442\u044b, \u0440\u0430\u043d\u044c\u0448\u0435 \u043e\u043d \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u043d\u0430 \u043d\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b \u0442\u0435\u0441\u0442\u044b. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u0442\u0435\u0441\u0442\u043e\u0432 \u0443 \u043d\u0430\u0441 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 lane \u0441 \u0438\u043c\u0435\u043d\u0435\u043c build_tests_products , \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u043c lane \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u043e\u0432 \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u043b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0431\u043e\u0440\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 -testProductPath.private_lane :run_testing do |options|    products_path = File.read(File.join(project_dir, &#171;products.txt&#187;))    product_path = &#171;#{products_path}\/#{options[:scheme]}.xctestproducts&#187;    scan(        testplan: options[:testplan],        # \u0412\u0430\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437-\u0437\u0430 \u0431\u0430\u0433\u0430 https:\/\/github.com\/fastlane\/fastlane\/issues\/20540        package_path: &#171;&#187;,        # \u0412\u0430\u0436\u043d\u043e \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c `build` \u0444\u0430\u0437\u0443. \u041f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0444\u043b\u0430\u0433\u0430:        # &#8212; \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 skip, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f &#8216;build test&#8217;        # &#8212; \u043a\u043e\u0433\u0434\u0430 skip, \u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f &#8216;test&#8217;        skip_build: true,        # \u0412\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 `true`, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0438\u0442\u044c &#8216;test&#8217; \u0444\u043b\u0430\u0433 (\u0441\u043c\u043e\u0442\u0440\u0438 \u0432\u044b\u0448\u0435)        test_without_building: true,        destination: &#171;platform=iOS Simulator,id=#{options[:destination]}&#187;,        skip_detect_devices: true,        disable_concurrent_testing: true,        derived_data_path: product_path,        xcargs: &#171;-testProductsPath #{product_path}&#187;&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-478119","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478119","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=478119"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478119\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=478119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=478119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=478119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}