Саша Априамашвили

Саша Априамашвили

Неделя
May 10, 2021 → May 16, 2021
Темы

Архив недели @AlexApriamashv1

Понедельник


Всем привет! Меня зовут Саша, я занимаюсь развитием единой мобильной платформы и сервисов для разработчиков в компании Grab. Grab – это экосистема, в которой жители Юго-Восточной Азии заказывают такси, еду, оплачивают покупки и т.д. На этой неделе говорим об iOS и инфраструктуре.

Что будет происходить на этой неделе. Ниже (в цепочке) примерный план на эту неделю. Отзывы и предложения по темам приветствуются!

Мотивация и смена обстановки. Поговорим о факторах, которые побуждают нас на изменения, будь то новая прическа (не про меня), новое место работы или переезд в другую страну

Ускоряем запуск iOS приложения. Какие факторы влияют на скорость запуска мобильного приложения, как уменьшить время запуска и какие преимущества это дает над вашими конкурентами.

Мобильный разработчик навсегда? В продолжении темы про мотивацию, какие чувства у вас вызывает "неизведанное", будь то новая задача, фреймворк, технология, отрасль? Поговорим про то, как перестать бояться выйти из зоны комфорта.

Запускаем UI тесты на iOS Создаем автоматизированную систему выполнения UI тестов для iOS, при помощи отвертки, молотка и плоскогубцев.

Если нет разницы, зачем тестировать дольше? Продолжаем тему тестов и говорим как можно сократить количество выполняемых тестов, а вместе с этим и время выполнения проверок на CI, посредством анализа влияния изменений на кодовую базу или Test Impact Analysis

🔥Тред #1

Вторник


Спасибо за ваш фидбек по расписанию на неделю! Я вижу, что темы «Мотивация» и «Выход из зоны комфорта», не пользуется большой популярностью. Давайте их поменяем! Надеюсь сегодня вам будет интересно почитать о моем опыте переезда и жизни в Юго-Восточной Азии.

Сегодня расскажу про переезд, жизнь и работу в Юго-Восточной Азии. Для простоты навигации, разделю это все на секции и буду выкладывать как цепочки сообщений: 🛫 Переезд из России 🍜 Жизнь и работа в Бангкоке 🇸🇬 Сингапур 👨‍💻 Работа над огромной экосистемой в Grab

Постараюсь создавать опросы между секциями!

Я помню тот самый момент, когда я подумал: «Хватит!».

В Апреле 2017 года ранним утром на балконе московской девятиэтажки, в квартире, которую мы с женой снимали на тот момент, я курил и наблюдал за тем, как из свинцово-серого неба во внутренний двор медленно опускается снег.

Наблюдая, как двор снова постепенно менял цвет с грязно-зеленого на грязно-белый, на то как вокруг своих автомобилей матерясь суетились мужички, поменявшие резину на прошлой неделе, я находил умиротворение в мысли о том, что через пару дней мы полетим в теплый и солнечный Таиланд

В этот момент, у меня не было ни офера от компании, ни малейшего представления о том, что такое Таиланд, кроме красивых картинок тропических островов.

При этом, не было ни капли сомнения в том, что это будет моей следующей остановкой.

Я говорю это не из-за того, что был невероятно уверен в своих способностях пройти оставшиеся этапы собеседований и получить офер. Тут чувства были прямо-противоположные, я ужасно волновался своему первому онсайт интервью на английском языке.

Все началось с сообщения рекрутера в LinkedIn, в котором он описывал компанию Agoda, нанимающую мобильных разработчиков в их офис в Бангкоке. Ничего об этой компании я до этого не слышал.

По началу, к собеседованиям, и уж тем более к возможности переезда в Таиланд, я относился с юмором. По двум причинам:

Во-первых, я никогда не рассматривал Азию. Как и многие, на тот момент я мечтал переехать в США или Европу.

Во-вторых, Таиланд звучал для меня как место в которое люди едут отдыхать, но уж никак не зарабатывать деньги и получать ценный опыт. Да и Тайского языка я не знаю, как выжить в стране без знания языка?

О том насколько сильно я заблуждался в своих мыслях, я узнал уже на онсайте.

Бангкок впечатлил меня своими высоченными небоскребами, нависающими и давящими со всех сторон. Незабываемым контрастом между роскошью и запредельной нищетой, запахами уличной еды и шумом проносящихся мимо тук-туков.

Это было далеко не то, куда я хотел бы переехать, но возможность исследовать этот мир не давала мне покоя.

Последним гвоздем в гроб моих сомнений была встреча с командой в Агоде и, в частности, с теми кто проводил собеседования. Никогда раньше я не чувствовал такого сильного рвения работать в компании, как в тот момент.

Меня воодушевила возможность работать, общаться и учиться у этих людей. Каждый из них казался сверх-разумом, работающим над супер-важным проектом. И я хотел быть частью этого.

В тот момент, когда я получил офер, я не думал о том, принимать его или нет. Единственное о чем я переживал это: «как сказать родителям о том, что мы переезжаем в другую страну?»

Вернувшись в Москву, мы с женой потратили примерно 1 день на то чтобы взвесить все «за» и «против», рассказать обо всем родителям и начать паковать чемоданы.

Я помню тот самый момент, когда я подумал: «Хватит!».
Ветка про переезд из России: twitter.com/mobileunderhoo…

Что бы вас мотивировало собрать чемоданы и уехать работать и жить в другую страну?
🤔 19.3% Зарплата (Total Comp)
🤔 36.4% Страна (назначения)
🤔 26.6% Страна (отправления)
🤔 17.7% Компания (проекты, люди)

🔥Тред #2
Бангкок – от очарования до разочарования

В Июле 2017, мы с женой попрощались с родителями, выкурили по последней сигарете и пошли на посадку первого в нашей жизни рейса в один конец.

По прилету в Бангкок, нас встретила знойная жара и дикая влажность. Почему-то обратил на это внимание только в этот раз. Отчетливо помню, как при выходе из самолета меня обдало стеной жаркого влажного воздуха, такого который бывает на курортах в знойный летний день.

Мы быстро прошли пограничный контроль, забрали два чемодана со всеми пожитками и, через мгновение, уже стояли в пробке по дороге в отель.

Хочу сказать, что процесс переезда был на высшем уровне. Компания оплатила билеты на самолет мне и моей жене, трансфер до отеля и сам отель на первые 30 дней. Расходы на визу и прочие документы были также покрыты Агодой. При желании, даже имелась опция заказать морской контейнер.

Сказать, что мои первые впечатления о компании и от всего, что происходило вокруг были положительными – ничего не сказать. Я был на седьмом небе от счастья!

До Агоды у меня не было опыта прохождения онбординга в компании. Максимум, что было на предыдущих местах работы, так это тот момент, когда тебя проводят по опен спейсу, представляют людям, имена которых ты точно не запомнишь с первого раза и указывают на твое рабочее место.

Бывало так, что это место вовсе и не твое.

Онбординг в компаниях – это давольно интересная часть погружения в рабочий процесс. Для начала, тебя одаривают мерчем с логотипами компании, будь то блокноты, ручки, стикеры, футболки, худи и тд. Выдают бейдж, ноутбук и прочие необходимые для работы вещи.

Затем, тебя в игровой форме знакомят с правилами и ценностями компании. В случае с Агодой, мы даже проходили психологические тесты, во все той же игровой форме.

Эти тесты, в теории определяют на сколько хорошо ты вольешься в ту или иную команду, но по факту, это формальность, которая ни на что не влияет.

После онбординга, тебя знакомят с командой и вы отправляетесь на обед, где твои новые коллеги пытаются понять кто ты и зачем пожаловал. Остаток дня проводится за чтением документации и обучении процессам сформированными в компании.

В Агоде я впервые познакомился с правильным применением фреймворка Scrum, такими понятиями как CI/CD, A/B тесты, и многое, чего я не встречал до этого на своих предыдущих местах работы, но всегда хотел попробовать.

Каждый день я узнавал что-то новое, учился и помогал другим людям узнать то, что уже знаю я. Одни словом, опыт работы в этой компании был незабываем.

Помимо технических знаний, я постоянно совершенствовал Английский. В тех командах, которых мне посчастливилось работать, всегда были либо носители языка, либо люди прожившие в США, Британии достаточно долгую часть своей жизни.

Я помню насколько сложно мне было по-началу что-то говорить на митингах. Я постоянно забывал слова, стеснялся своего произношения, боялся что скажу неправильно или что меня не поймут. Все эти страхи ушли давольно скоро.

К концу первого месяца, мы уже переехали в нашу новую квартиру, из которой я мог пешком ходить в офис.

Было ощущение того, что жизнь удалась!

Аренда квартиры в Бангкоке это давольно интересное мероприятие. На тот момент, не было проблем найти хороший вариант, с бассейном, сауной и консьержем в самом центре города.

По меркам местных жителей, все эти квартиры стоили бешеных денег. Помните я говорил о контрасте роскоши и запредельной нищеты которая бросилась в глаза при первом посещении?

Примерная стоимость квартиры в центре города, в пешей доступности от больших торговых центров и офиса была порядка 20-25к бат. Что в пересчете на рубли составляло около 40-50к. ($550-650) в месяц.

Для примера, местные жители, если и снимали квартиры, то делали это много дальше от центра, а соответственно и дешевле. Такая квартира стоила бы порядка 6-8к бат, или 12-16к рублей ($150-250). Конечно, ни о каких бассейнах и прочем не идет и речи.

Первые несколько месяцев в Бангкоке пролетели незаметно. Я продолжал наслаждаться работой в Агоде, мы путешествовали по стране, ездили на выходные на острова, ходили на массаж и, в целом, жизнь казалось раем!

Для меня, этот рай начал рушиться примерно после 6 месяцев.

Таиланд – это сказано красивая и удивительная страна! К моему сожалению, я жил в Бангкоке.

Всякие мелочи: барная улица с караоке под окном, толпы медленно-идущих тайцев беспросветно уткнувшихся в телефоны по дороге в офис и обратно, расизм, духота, запах нечистот, грязь, крысы и огромные тараканы шныряющие по улицам города, начали постепенно действовать на нервы.

Я, по прежнему, наслаждался работой в Агоде, от этого было сложнее сделать какой-то обдуманный шаг вперед, на поиски нового места.

Еще 6 месяцев спустя, я уже проходил собеседования в 3 компании разных точках мира, одной из этих компаний был Grab.

🔥Тред #3
Таиланд – это сказано красивая и удивительная страна! К моему сожалению, я жил в Бангкоке.
Продолжение: twitter.com/mobileunderhoo…

🔥Тред #4
Бангкок – от очарования до разочарования

В выборе между прекрасной работой в ужасном месте и менее воодушевляющим (по отзывам) месте работы в новой стране, каков был бы ваш выбор?
🤔 25.6% Выбираю работу
🤔 74.4% Вперед к приключениям!

Среда


Ну куда ты уезжаешь? Сингапур – это тот же Бангкок!

Это пример того, что я слышал от своих коллег, когда рассказал о решении двигаться дальше. Именно эту фразу мы с женой еще много раз со смехом вспоминали находясь в Сингапуре. Но давайте по порядку.

После прохождения собеседований в Grab, у меня были смешанные чувства по поводу ухода из Агоды. С одной стороны, мне безумно нравилось работать в компании, с другой – я не видел больших преимуществ для себя, в плане роста.

В определенный момент, я осознал, что немного устал от работы над кодом мобильного приложения. Мне захотелось изведать непонятный мне, на тот момент, мир CI/CD инфраструктуры.

С изучением всего этого в Агоде была небольшая загвоздка, вся инфраструктура уже была выполнена на давольно высоком уровне и требовала небольших доработок. Учиться мне было практически не на чем.

С другой стороны, Grab. На тот момент, компания очень бурно развивала свой бизнес, наращивала отдел разработки и, не имела практически никакой инфраструктуры для мобильных приложений.

Хоть я и изначально пошел на позицию iOS инженера, я знал, что рано или поздно, я смогу добраться до их пайплайнов.

Но давайте вернемся к переезду в Сингапур, а о Grab поговорим чуть позже.

Через 2,5 часа, после вылета из Бангкока, мы приземлились в аэропорту Changi, в Сингапуре.

Сингапур – это крохотное, но гордое государство расположившееся на небольшом архипелаге к югу от Малайзии.

За все время жизни в Бангкоке, мы так и не побывали здесь как туристы. Потому, нам пришлось исследовать страну уже по факту переезда.

По дороге из аэропорта, я судорожно пытался рассмотреть город в темноте. Все пейзажи, которые мне удавалось разглядеть напоминали мне что-то родное, и до боли знакомое.

«Это же Москва!» – подумал я. Горящие огни окон многоэтажек обрамленных толстым слоем кирпича и бетона мелькающие за окном такси, очень напоминали спальные районы Москвы.

Все ассоциации с Москвой растаяли на следующее утро, как только мы проснулись и увидели где оказались.

Яркие лучи солнца сочились через решетчатую затворку балкона, где-то внизу слышались радостные воскликни детей и всплески воды в бассейне. Небо, ярко-синее, без единого облачка. Ветер слегка покачивал листья пальмы, растущей под окном. Мы дома!

Первым культурным шоком, который случился у нас после Бангкока был переход через дорогу, а точнее то, что водители останавливались перед переходами и пропускали пешеходов.

Переход через дорогу в Бангкоке, всегда был лотереей. Никогда не знаешь, заметит тебя водитель или нет. Загорается зеленый сигнал светофора, ты поднимаешь руки, а там уже как получится: либо это поможет водителю тебя заметить, либо парамедику снять с тебя футболку.

Первые пару недель в Сингапуре, мы активно искали жилье. Немного удручал тот факт, что аренда квартиры стоит в разы дороже, чем в Бангкоке.

Стоит заметить, что зарплата в Сингапуре, так же, в разы больше, чем в Бангкоке, а налоги – меньше.

В целом, стоимость аренды квартиры, напрямую зависит от района, типа здания и инфраструктуры.

В Сингапуре есть минимум 3 вида жилья, которое можно арендовать на длительный срок: 🏢 Социальное жилье (HDB) 🏬 Кондоминиум 🏡 Частный дом

Социальное жилье, или HDB, получившее свое название благодаря организации занимающейся его развитием (Housing and Development Board) – это микрорайоны, в которых, в основном, живут местные жители.

HDB – это, микро города, со всей присущей инфраструктурой: магазинами, детскими садами, школами, развлекательными центрами и тд. Именно проплывающие мимо HDB, напомнили мне спальные районы Москвы, по прилету.

Стоимость аренды квартиры в HDB, в среднем, SG$500-2000 (30к-110к руб / $350-1500) в месяц. За эти деньги, вы получите просторную однокомнатную квартиру с быстрым доступом к магазинчикам, фудкорту, школе, паркам и прочим прелестям цивилизации.

Второй вид жилья – кондоминиум. Это самый распространенный вид жилья среди экспатриантов. Кондо в Сингапуре очень напоминают кондо в Бангкоке. Красивые ухоженные здания со всеми удобствами вроде бассейнов, барбекю павильонов, теннисных кортов, саун, джакузи, охраны.

Квартиры с окнами в пол и шикарным видом на зеленые площадки и парки города. Кафе, магазины и парки в пешей доступности от дома и прочие прелести жизни обойдутся вам в SG$2000-4000 (110к-220к руб / $1500-3000) в месяц за однокомнатную квартиру.

Про третий вид жилья я знаю немного. Всерьез никогда не рассматривал вариант аренды дома. Как понятно из размеров страны, земля здесь давольно дорогая, соответственно и цены на частные дома с крохотной лужайкой перед домом могут взлететь до небес.

В среднем, цена за аренду частного дома здесь будет начинаться от SG$7000 (400к руб / $5300).

Разработчик или SWE, здесь может позволить себе аренду средней квартиры в кондоминиуме, при этом, у него получится еще путешествовать и немного откладывать на черный день.

Жизнь в Сингапуре более чем конформная, большой выбор продуктов питания, различений и отличное позиционирование для путешествий по Азии и Океании.

С приходом вируса и ужесточением мер по перемещению, последний пункт уже не имеет такого значения, но я все еще надеюсь на светлое будущее!

Если подвести итог, у меня не подниматься рука сравнивать Сингапур и Бангкок. Сингапур ушел на много лет вперед, здесь чувствуется влияние колониального стиля Британии. Люди говорят на безупречном английском. Умная архитектура города, и размещение зданий.

Множество возможностей роста и развития. Огромное число крупных компаний, в том числе и все представители FAANG.

Это только мое мнение, но Сингапур – лучший город в Юго-Восточной Азии!

🔥Тред #5
Первые пару недель в Сингапуре, мы активно искали жилье. Немного удручал тот факт, что аренда квартиры стоит в разы дороже, чем в Бангкоке.
продолжение, про аренду жилья в Сингапуре: twitter.com/mobileunderhoo…

🔥Тред #6
Ну куда ты уезжаешь? Сингапур – это тот же Бангкок!

🔥Тред #7

Пятница


Переезд из квартиры в квартиру не менее утомителен, чем переезд в другую страну. Благо, все закончилось, я снова с вами!

Вижу, что тема Азии вас немного утомила, потому, напишу что-то более-менее техническое. Сегодня говорим об ускорении времени запуска приложения и о типах связки зависимостей.

Большие компании всегда найдут показатели, которые можно улучшить и заработать больше денег. Многие такие улучшения происходят в пользовательском опыте, например, мобильного приложения.

Пользовательский опыт это очень обширная тема, можно говорить о создании потрясающих анимаций; уменьшении количества нажатий на кнопку, для достижения цели; покраске, этих самых, кнопок и еще много о чем.

Есть один аспект пользовательского опыта, от предвкушения работы над которым у разработчиков загораются глаза, и руки сами тянутся к клавиатуре.

Этот аспект – скорость. А точнее, оптимизация выполнения программы. Тут можно говорить о чем угодно, от уменьшения количества циклов в отдельном куске кода, до ускорения выполнения отдельных операций.

«А есть ли во всем этом какой-то реальный профит для компании, кроме радости разработчиков интересной задаче?», – спросите вы. Давайте разбираться.

Представьте, что вы работаете в молодой компании, у которой дела идут в гору. Вы решаете расширяться, нанимать больше сотрудников, добавлять функциональности вашему продукту.

Со временем, если вы не подготовились к этому заранее, а скорее всего так и есть, вы сталкиваетесь с двумя проблемами.

С каждым днем, ваш перерыв на кофе с пончиком занимает все больше времени, но когда вы возвращаетесь на рабочее место, сборка проекта еще не завершена.

Ваши пользователи начинают жаловаться на количество времени, которое они проводят на сплеш-скрине, с каждым днем, жалобы все серьезнее и серьезнее.

Как вы поняли, сегодня мы говорим о второй проблеме – скорость запуска iOS приложения.

Существует огромное количество причин, почему приложение начинает зависать на старте. Это может быть связано с выполнением запросов на сервер, инициализацией тяжелых компонент, чтением из базы и тд.

В большинстве случаев, разработчики вашей молодой компании, побороли все очевидные причины зависания приложения, потому, вам придется смотреть в чем еще может быть проблема.

Начните с анализа количества зависимостей вашего проекта. В наше время так просто добавить какую-нибудь стороннюю библиотеку, их сотни тысяч и они делают все что вам может потребоваться.

Помимо сторонних зависимостей, вы могли уже пытаться справиться с первой проблемой, укоротив время инкрементальной сборки разбитием вашего кода на модули.

Оба типа зависимостей, что внешние, что внутренние, должны каким-то образом быть представлены в финальном бандле приложения, установленном на устройстве пользователя.

Существует 2 основных типа указания таких зависимостей, а точнее, 2 типа связки зависимостей с кодом вашего приложения: статическая и динамическая.

Динамическая связка используется по-умолчанию, в большинстве случаев. Именно динамически-связанный фреймворк производит ваш Xcode, при попытке создания таргета Framework для проекта.

Зависимости, связанные динамически, дают на выходе отдельно-стоящие MACH-O файлы, которые затем копируются в бандл вашего приложения в директорию “Frameworks”.

Эти фреймворки находятся вашим приложением через решение рантайм пути поиска или @rpath. Преимуществом динамической связки является возможность переиспользования зависимостей между исполняемыми файлами.

За поиск и связку таких зависимостей отвечает специальная утилита dylib. В момент старта вашего приложения, dylib начинает поиск и загрузку ваших динамических зависимостей в память.

В случае, если не удалось найти зависимость, dylib даст об этом знать прекратив выполнение вашего приложения при старте.

Со статической связкой все происходит немного иначе. Статические библиотеки не копируются рядом с исполняемым файлом приложения. Вместо этого, символы ваших статических зависимостей сливаются в одно целое со своим спутником, то есть с исполняемым файлом приложения.

В отличии от динамической, статическая связка не дожидается рантайма и происходит в момент сборки проекта, таким образом, у вас не будет неприятного сюрприза в виде завершения работы при старте, из-за недостающей зависимости.

Такой неполноценный проект просто не соберется, а соответственно и не попадет к пользователю. Такую гарантию качества вам предоставит утилита Ld, отвечающая за линовку символов.

Теперь, поскольку мы немного разобрались в разнице между типами связываний, давайте подумаем почему наше приложение может тормозить при старте и на что фактически уходит это время. Для того чтобы это понять, нам необходимо разобраться в том, как работает динамическое связывание.

Когда пользователь нажимает на иконку приложения на устройстве, система заменяет текущий процессией только что созданным и передает ему управление.

Ваше приложение загружается в память устройства, где-то на этом этапе производится ASLR и система подгружает утилиту dylib, которая начинает загружать библиотеки в память.

Алгоритм загрузки зависимостей давольно простой - это обычный DFS. Загрузка библиотеки в память происходит после того, как загружены все прямые и транзитивные зависимости этой библиотеки.

Как только все библиотеки загружены, управление передается приложению, через вызов функции main и ваш AppDelegate получает вызов соответствующего метода.

Так на что же тратится время? В основном, весь процесс замедляется за счет безопастности. Помимо применения ASLR, дополнительная безопасность вашего приложения и всех его компонент осуществляется при помощи сверки подписи.

dylib не может загружать в память какие угодно библиотеки, для каждой загружаемой зависимости, необходимо сверить подпись и подтвердить, что она была выпущена либо разработчиком приложения, либо Apple.

Как раз эта проверка и съедает львиную часть драгоценного времени при запуске вашего проекта.

Вы можете пересмотреть необходимость использования динамической связки. В большинстве случаев, ваши зависимости будут необходимы только в основном исполняемом файле.

Для смены типа связывания ваших внутренних тагретов,смените тип связки на MACH_O_TYPE = staticlib, в настройках проекта.

Будьте внимательны при работе с ресурсами. Так как статический фреймворк не копируется в бандл приложения, ресурсы содержащиеся в этом фреймворке туда тоже не попадут.

Создайте отдельный таргет в вашем проекте с MACH_O_TYPE = mh_bundle и поместите туда все свои картинки, xib файлы и прочие ресурсы. Затем укажите его в фазе Copy Bundle Resources вашего приложения. Теперь этот бандл будет лежать рядом с исполняемым файлом вашего проекта.

Осталось задать новый путь к ресурсам, при помощи указания пути относительно основного бандла

let resourcePath = Bundle.main.path(forResource: "MyBundle", ofType: "bundle")

Теперь вы можете использовать ресурсы вместе со статическими библиотеками!

Из опыта работы в такой молодой и успешной компании, трюк с изменением типа связки помог увеличить количество клиентов приложения на 30%

Теперь, поскольку мы немного разобрались в разнице между типами связываний, давайте подумаем почему наше приложение может тормозить при старте и на что фактически уходит это время. Для того чтобы это понять, нам необходимо разобраться в том, как работает динамическое связывание.
Продолжение: twitter.com/mobileunderhoo…

🔥Тред #8
Как оказалось, время запуска приложения играет огромную роль в при вызове такси, заказе еды или оплате услуг. У кого приложение быстрее, того и любят больше

🔥Тред #9

Суббота


Сегодня поговорим про настройку инфраструктуры UI тестов в iOS. Но это случится чуть позже. А сейчас, проведем небольшой опрос по вчерашней теме!

Какой тип связки зависимостей используется у вас в проекте?
🤔 34.0% Динамическая
🤔 33.3% Статическая
🤔 32.7% Затрудняюсь ответить

Какие способы ускорения времени сборки используете вы?
🤔 48.2% Разбиваю на модули
🤔 9.6% Альт. билд системы (кеш)
🤔 42.1% Нет проблем со сборкой

Сколько времени ваше приложение тратит на холодный запуск?
🤔 44.4% < 3 секунд
🤔 25.8% 3-5 секунд
🤔 7.1% 5-10 секунд
🤔 22.7% > 10 секунд

Холодный запуск приложения – это время запуска без кеша. Его можно померить перегрузив устройство. Актуально для обеих платформ.

Воскресенье


Кажется, я немного перестарался с тредом про инфраструктуру для UI тестов в iOS 😅 Выложу в нескольких цепочках и добавлю ссылки в этот тред, для удобства навигации.

Наконец, пришло время поговорить о тестах и инфраструктуре.

Поборов проблемы со временем старта, вы продолжаете работать над приложением, добавлять больше функциональности в проект, обновлять окаменелые куски кода и тд.

Со временем, вы замечаете, что последние переработки функциональности, как и некоторые добавленные фичи, возвращаются назад с ручной регрессии или выливаются в виде очередного инцидента в Crashlytics.

Тут нет ничего удивительного, ваша кодовая база становится все больше и запутанней с каждым днем. Что же делать? Как избавиться от косых взглядов QA и красных глаз менеджера, у которого стоит KPI на стабильность?

Ответов на эти вопросы может быть несколько, но сегодня мы обсудим автоматизацию тестирования. В частности, тестирования связки компонент при помощи UI тестов.

В наши дни существует несколько способов проводить такое тестирование. Многие слышали о стандартном XCTest, с возможностью записи действий в симуляторе, KIF, EarlGrey и прочих подобных фреймворках.

Сегодня мы рассмотрим автоматизацию тестирования на примере стандартных UI тестов в XCTest. По двум причинам:

Во-первых, это классических способ тестирования, рекомендованный Apple. Для того чтобы начать его использовать, не нужно устанавливать и подключать дополнительные зависимости в проект.

Во-вторых, это blackbox тестирование, что подразумевает отсутствие доступа к кодовой базе проекта. Это создает условия, максимально приближенные к реальному взаимодействию пользователя с вашим приложением.

Мы не будем вдаваться в реализацию самих UI тестов, скажу лишь то, что для адекватной работы с тестами, я бы рекомендовал написание своего собственного фреймворка, на основе паттерна PageObject, который бы описывал интерфейсы ваших экранов и отдельных компонент.

Паттерн PageObject зародился в вебе, вот здесь можно посмотреть что это такое: webdriver.io/docs/pageobjec…

И так, представим, что все согласны с тем, что существует проблема проверки качества проекта, менеджмент видит необходимость написания UI тестов для проверки интеграции и совместимости компонент в проекте. Вам даже выделили проект и дали финансирование на создание инфраструктуры.

Так давайте разберемся что из себя эта инфраструктура может представлять. Рассмотрим следующие аспекты такой системы: 🖥 Железо ⚙️ Выполнение 🏋️‍♂️ Масштабирование 📊 Аналитика

Одним из первых вопросов на которые нужно будет ответить – это где выполнять тестовые сценарии. Конечно, вы можете согласиться на том, что каждый разработчик будет запускать тесты на своей локальной машине, перед тем как создать запрос на слияние с основной веткой.

Такая система будет работать на доверии, а это значит, что вероятность ситуации, когда разработчик "забудет" прогнать тесты перед созданием запроса будет возрастать с каждым новым тестом. Да и как уследить за тем, прогнаны ди все тесты, был ли результат выполнения положительным?

Отсюда, мы приходим к мысли, что такие проверки должны выполняться централизовано и для всех запросов на слияние с основной веткой. Таким образом, мы сможем точно понять был ли вариант выполнения успешным и были ли выполнены все необходимые тестовые сценарии.

Таким централизованным местом выполнения могут стать, опять же, локальные машины разработчиков. При наличии некоторого координатора, вы сможете подключить все ваши машины в единую сеть агентов, которые будут выполнять задачи пришедшие от координатора.

Примером такого координатора может служить GitLab Runner (docs.gitlab.com/runner/install/), в случае использования GitLab. Для GitHub вы можете использовать Jenkins или TeamСity, которые предоставят вам возможность регистрации раннеров jetbrains.com/help/teamcity/…

Кстати, вы можете настроить GitLab пайплайны и использовать их в GitHub 🤯 docs.gitlab.com/ee/ci/ci_cd_fo…

Проблем с решением использовать локальные машины давольно много.

Во-первых, к вам на машине может пожаловать запрос на прогон тестов от координатора, что съест давольно большое количество ресурсов и, скорее всего, отправит вас на перерыв со все тем же кофе и пончиком.

Во-вторых, количество активных машин в пулле будет меняться. Разработчики будут включать/выключать машины, а особо пронырливые – вовсе отменять регистрацию своей машины в пулле.

Похоже, вашей компании придется потратить еще какое-то количество денег на покупку новых машин. Но вопрос в том, как потратить эти деньги с умом?

Тут есть, как минимум, 2 варианта: купить физические машины, арендовать машины в облаке.

Покупка физических машин позволит иметь прямой доступ к этим самым машинам, диагностировать возможные проблемы и устранять неполадки, проводить эксперименты и иметь возможно делать выводы по этим экспериментам давольно быстро.

Однако, с покупкой физических машин есть ряд сложностей. Во-первых, их нужно где-то хранить, администрировать, проводить ремонт, замену и докупку машин при увеличении флота. Всем этим нужно кому-то заниматься, а это дополнительные расходы на людей.

Аренда машин в облаке затруднит работу с ними напрямую, так как доступ будет осуществляться через компанию арендодателя, при этом, у вас пропадет ряд вопросов и забот, в том числе с хранением и поддержкой этих самых машин.

Предположим, вы не хотите иметь дело с закупкой и содержанием собственной собственного флота и предпочитаете арендовать уже готовое решение. У вас будет несколько вариантов таких компаний.

При выборе арендодателя, нужно помнить, что Apple разрешает осуществлять сборку, запуск тестов и аналитику под iOS, только на официальном “яблочном” железе.

Такое требование заметно сужает выбор, но варианты все еще остаются. Самыми популярными провайдерами будут MacStadium и AWS.

MacStadium позволит вам запустить hypervisor c несколькими виртуальными машинами на хосте типа MacPro или Mac Mini, это увеличит фактическое количество доступных агентов для запуска тестов и сборки проекта.

Amazon, не так давно, анонсировал запуск macOS образов в своем сервисе AWS. aws.amazon.com/about-aws/what… Такое решение позволит создавать герметичное окружение для ваших сборок и тестов, что откроет возможность осуществлять кеширование операций и ускорении времени сборки и теста.

Представим, что вы выбрали один из облачных провайдеров. Давайте перейдем к логике прогона тестовых сценариев на новых машинах.

Глобально, у вас есть 2 этапа: сборка для запуска UI тестов и сам прогон тестовых сценариев. Давайте по порядку.

В момент сборки проекта для запуска тестов, происходит сборка 2 основных компонент: Приложение Бандлы тестов

Ваше приложение состоит из основного исполняемого файла и всех его зависимостей связанных статически или динамически (тема прошлого поста).

Тестовый раннер принимает на вход тестовые банлды, собранные из таргетов, указанных в схеме сборки. В прогоне тестовых сценариев использованы только те тесты, которые попадут в раннер. Задание этих тестов происходит в схеме (.xcscheme), для которой выполняется команда xcodebuild.

Рекомендуется разделять схемы запуска Unit и UI тестов, так как для разного типа тестов могут потребоваться разные настройки и переменные окружения. В целом, логика запуска этих двух типов прогона может различаться.

Чтобы совершить сборку проекта и раннера без перехода к выполнению тестов, необходимо использовать опцию build-without-testing при вызове xcodebuild. Результатом выполнения этой команды, будет файл .xctestrun, в котором хранятся указания к выполнению тестовых сценариев.

Подробнее, про содержание файла можно почитать тут: manpagez.com/man/5/xcodebui…

Как только у вас есть все артефакты сборки, вы можете перейти к прогону своих тестовых сценариев.

Само разделение этого процесса на этапы обусловлено тем, что выполнение тестов может прерваться по какой либо причине, при этом, проще повторить только операцию прогона сценариев переиспользовав артефакты сборки из прошлого этапа.

Тут можно пойти еще дальше и попробовать перезапустить только те тесты, с которыми были проблемы при первом прогоне. xcodebuild позволяет задавать список тестов для запуска.

Найти “упавшие” тесты, вы можете с помощью тестового лога, который ведет сам xcodebuild. При прогоне нескольких тестов в параллель, тест-логи будут находиться внутри .xcresult файла.

Поменяв форматирование имен тестов, вы можете передать их в xcodebuild test-without-building, через параметр ‘-only-testing:’, для повторного выполнения. Введение таких ретраев, позволит увеличить стабильность ваших тестовых прогонов и сэкономить пару нервных клеток разработчикам

Представим, что вы выбрали один из облачных провайдеров. Давайте перейдем к логике прогона тестовых сценариев на новых машинах.
Продолжение: twitter.com/mobileunderhoo…

🔥Тред #10
Запускать тесты оказалось не таким уж и хитрым делом. Но как мы можем подготовиться к росту их количества?

Существует 2 типа масштабирования: вертикальное и горизонтальное. Вертикальное масштабирование подразумевает увеличение количества ресурсов на машине, горизонтальное, увеличение количества машин с сохранением текущего ресурса, либо его уменьшением.

В случае, если мы решим использовать самый мощный мак про на сегодняшний день, с 28 CPU, у нас будет возможность эффективного запуска порядка 14-18 симуляторов одновременно, в расчёте 1-2 ядер на симулятор.

В теории, такая доработка позволит заметно ускорить выполнение тестовых сценариев. На практике, при задании параллельного выполнения, встроенный координатор стандартного раннера распределяет тесты по их количеству, что создает дисбаланс во времени выполнения между симуляторами.

Второй минус такого подхода заключается в том, что предел масштабирования достигается давольно быстро, и этот предел – жесткий.

Горизонтальное масштабирование имеет более мягкий предел – бюджет вашей компании, потому, такой способ больше подходит при стремительном росте количества тестов. Минус горизонтального масштабирования заключается в том, что он требует гораздо больше трудозатрат.

Представим, что нашей целью является равномерное распределение тестовых сценариев на N машин с мощностью в 2 CPU каждая. При этом, N может быть от 1, до бесконечно большого числа машин в вашем флоте.

Разберемся с требованием равномерного распределения. Равномерное распределение тестовых сценариев – это такое распределение сценариев между машинами, при котором время старта и завершения выполнения всех операций будет равным, в пределах погрешности.

Другими словами, мы хотим, чтобы при параллельном выполнении тестов на разных машинах, время завершения для всех машин было примерно одинаковым.

Реализовать такое распределение не представляет сложности. Вся информация, которую нам необходимо знать, это идентификатор тестового сценария и среднее время его выполнения.

Имея эти 2 параметра для каждого теста, мы можем написать алгоритм балансировки нагрузки при помощи “кучи” (Heap). В реализации этого алгоритма, мы будем складывать наши тесты в очереди (Queue), находящиеся внутри MinHeap. Количество очередей в куче будет равно нашему N.

Таким образом, мы добьемся примерно-равного распределения тестов в очередях по суммарному времени выполнения. Каждая очередь будет отправлена на соответствующую машину для выполнения. В результате, время выполнения всех тестов среди всех машин должно быть примерно-одинаковым.

“Откуда мы узнаем время выполнения тестов”, – думаете вы? Для этого, мы будем собирать аналитику по каждому выполненному тесту и отправлять ее в базу данных.

Для этих целей, нам подойдет TimeSeries база данных (например InfluxDB), из которой мы сможем запрашивать среднее время выполнения тестов за определенный период времени. Допустим, за вчера.

При таком подходе, вы сможете значительно уменьшит время выполнения ваших UI тестов и быть готовыми к их последующему росту. Все что нужно будет сделать – изменить значение нашего N.

Запускать тесты оказалось не таким уж и хитрым делом. Но как мы можем подготовиться к росту их количества?
Продолжение: twitter.com/mobileunderhoo…

🔥Тред #11
Последним, но не по значению аспектом вашей инфраструктуры, является аналитика. Как понять что с выполнением тестов нет проблем? Как узнать время выполнения каждого теста? И на многие подобные вопросы, вам поможет ответить аналитика вашей системы.

Перечислю основные показатели, которые важно отслеживать для того, чтобы понимать что ваша инфракрасно все еще жива. Вы можете добавить свои :)

Время выполнения теста. Помимо того, что эта метрика помогает в балансировке очередей тестов, она же выдает аномалии их поведения. Время выполнения теста резко изменилось – самое время проверить что в кодовой базе.

Стабильность теста. Эта метрика поможет показать общую картину здоровья ваших тестов, выделить команды, которые нуждаются в помощи в написании тестов и помог принять решение о том игнорировать результат падения теста или нет.

Общее время выполнения. Вы потратили огромное количество времени и сил на создание само-масштабируемой системы выполнения тестов.

Покажите всем сколько времени вы сэкономили, сравнивая самое долгое время распределенного выполнения тестов с суммой времени выполнения каждого индивидуально теста, чтобы показать время без параллелизма.

🔥Тред #12
Последним, но не по значению аспектом вашей инфраструктуры, является аналитика. Как понять что с выполнением тестов нет проблем? Как узнать время выполнения каждого теста? И на многие подобные вопросы, вам поможет ответить аналитика вашей системы.
Продолжение: twitter.com/mobileunderhoo…

🔥Тред #13
Наконец, пришло время поговорить о тестах и инфраструктуре.

Одним из первых вопросов на которые нужно будет ответить – это где выполнять тестовые сценарии. Конечно, вы можете согласиться на том, что каждый разработчик будет запускать тесты на своей локальной машине, перед тем как создать запрос на слияние с основной веткой.
🖥️ Железо: twitter.com/mobileunderhoo…

Представим, что вы выбрали один из облачных провайдеров. Давайте перейдем к логике прогона тестовых сценариев на новых машинах.
⚙️ Выполнение тестов: twitter.com/mobileunderhoo…

Запускать тесты оказалось не таким уж и хитрым делом. Но как мы можем подготовиться к росту их количества?
🏋️‍♂️ Масштабирование: twitter.com/mobileunderhoo…

Последним, но не по значению аспектом вашей инфраструктуры, является аналитика. Как понять что с выполнением тестов нет проблем? Как узнать время выполнения каждого теста? И на многие подобные вопросы, вам поможет ответить аналитика вашей системы.
📊 Аналитика: twitter.com/mobileunderhoo…

🔥Тред #14
Последним, но не по значению аспектом вашей инфраструктуры, является аналитика. Как понять что с выполнением тестов нет проблем? Как узнать время выполнения каждого теста? И на многие подобные вопросы, вам поможет ответить аналитика вашей системы.
Машины twitter.com/mobileunderhoo… Выполнение twitter.com/mobileunderhoo… Масштабирование: twitter.com/mobileunderhoo… Аналитика: twitter.com/mobileunderhoo…

🔥Тред #15
Неделя подошла к концу, скоро с вами будет новый автор. Надеюсь вам было интересно, мне так точно 😄 Спасибо всем! В цепочке ниже ссылка на темы этой недели. - @AlexApriamashv1

Сегодня расскажу про переезд, жизнь и работу в Юго-Восточной Азии. Для простоты навигации, разделю это все на секции и буду выкладывать как цепочки сообщений: 🛫 Переезд из России 🍜 Жизнь и работа в Бангкоке 🇸🇬 Сингапур 👨‍💻 Работа над огромной экосистемой в Grab
🌏 Переезд в Юго Восточную Азию twitter.com/mobileunderhoo…

Большие компании всегда найдут показатели, которые можно улучшить и заработать больше денег. Многие такие улучшения происходят в пользовательском опыте, например, мобильного приложения.
🏎 Ускорение запуска приложения и типы связки зависимостей в iOS twitter.com/mobileunderhoo…

Кажется, я немного перестарался с тредом про инфраструктуру для UI тестов в iOS 😅 Выложу в нескольких цепочках и добавлю ссылки в этот тред, для удобства навигации.
🏋️ Инфраструктура для UI тестов под iOS twitter.com/mobileunderhoo…

🔥Тред #16

Ссылки