Connect with us

Автоматическое тестирование приложений

Как 40 строк кода ускорили End to End тесты на iOS более чем на 50%

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

Опубликовано

/

     
     

В Wealthfront (компания финансовых услуг, базирующаяся в Пало-Альто) тестирование является одним из основных инженерных принципов — в виде модульного и сквозного (end-to-end) тестирования на всех платформах. В частности, команда iOS управляет собственной CI-инфраструктурой для запуска тестов на интеграционном сервере, зеркально отражающем производственную среду. С учетом того, что у нас в iOS около 30 тысяч юнит-тестов и почти 1 тысяча сквозных тестов (и это число растет), ускорение нашего E2E-пакета стало первоочередной задачей, поскольку на его выполнение уходит значительное количество времени. В этом посте мы расскажем о том, как мы ускорили наши тесты на 50% с помощью небольшого, целенаправленного изменения.

Проблема: медленные и нестабильные UI тесты

iOS E2E тесты уже давно являются головной болью. XCUITest и xcodebuild печально известны своими сбоями и зависаниями, и когда тесты не имеют защиты от этих проблем, скорость и надежность значительно страдают. Несмотря на такие оптимизации, как отключение анимации, включение параллельного тестирования и распределение тестов по нескольким Mac Mini, наш набор E2E-тестов занимал значительное количество времени — даже при одновременном выполнении на трех машинах.

Мы пришли к выводу, что есть две основные стратегии, когда речь идет о iOS E2E-тестах и XCUITest, но мы всегда отдаем предпочтение надежности:

  1. Приоритет скорости над надежностью: выполняя немедленные утверждения, например XCTAssertTrue(self.testApp.textFields[“email”].exists), мы значительно увеличиваем скорость, но это не очень хорошо масштабируется в распараллеленной среде, особенно на старых машинах.
  2. Приоритет надежности над скоростью: ожидание истинности утверждений, например self.testApp.textFields[“email”].waitForExistence(), существенно снижает скорость, но лучше масштабируется в распараллеленных средах.

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

Вот сниппет одного из наших повторяющихся тестов потока вывода:

Заметили ли вы узкие места?

Кое-что, что привлекло наше внимание, — это 1 секунда между каждым запросом. После некоторого расследования мы обнаружили, что механизм опроса XCTWaiter (который является неизменяемым и неконфигурируемым) ждет 1 секунду между проверками, блокируя цикл выполнения процесса раннера тестирования, пока не будет выполнено условие или не будет достигнут тайм-аут. Этот дизайн явно устарел, он появился в эпоху до появления компьютеров mac серии M.

Быстрое фикс: ускоренный опрос с помощью кастомной замены XCTWaiter

Поскольку Apple закрыла доступ к своей реализации, мы решили воссоздать и улучшить этот механизм с нуля. Наша первая итерация включала опрос каждые 0.1 секунды вместо 1 секунды. Мы также добавили предварительную проверку, чтобы обойти полинг, если условие уже было истинным с самого начала. Вот наша первоначальная реализация:

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

Хотя локальное увеличение скорости на 80% было многообещающим, эти улучшения не нашли отражения в нашем CI. Мы столкнулись с рядом проблем при работе в распараллеленной среде, вероятно, из-за дополнительной нагрузки на процессор, которую вносил новый механизм опроса. Опрос в 10 раз чаще в четырех параллельных процессах перегружал наши Mac Mini M1, что приводило к периодическим сбоям тестового процесса и сводило на нет большинство, если не все улучшения в скорости.

Оптимизация для параллельных сред с экспоненциальным откатом

Чтобы решить эту проблему, мы усовершенствовали нашу реализацию с помощью экспоненциального отката. Благодаря этой настройке наш механизм опроса адаптируется как к отзывчивости условий, так и к загрузке процессора на наших узлах CI. Окончательная реализация выглядела следующим образом:

Благодаря этим изменениям наши конвейеры CI значительно сократили время выполнения, оставаясь при этом стабильными:

Как 40 строк кода ускорили End to End тесты на iOS более чем на 50%

Заключительные мысли

Уделив время наблюдению и исследованию узких мест в нашем тестовом E2E наборе, мы добились следующих результатов:

  • Более быстрое время выполнения: до 80% прироста скорости локально и 50% на наших CI-конвейерах
  • Перспективность: теперь наши тесты будут автоматически использовать преимущества аппаратных улучшений, не требуя изменений в коде

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

Приложение: интеграция в ваш тестовый iOS пакет E2E

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

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: