Хабр, привет!

Меня зовут Борис. Я Mobile AQA lead в Vivid Money.

Это вторая статья в цикле статей по iOS-автоматизации, в которых я расскажу о том, как ускорить прохождение UI-тестов.

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

В рамках этой статьи мы разберем такие этапы:

  • зачем распараллеливать тесты?

  • распараллеливаем тесты, используя Xcode;

  • распараллеливаем тесты, используя Fastlane.

Зачем распараллеливать тесты?

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

Представим ситуацию: у вас есть 500 ui-тестов, которые прогоняются за 4 часа. Четыре часа на прогон - это очень много, но если поделить эти 500 тестов на 8 симуляторов, прогон займет 30 минут!

Распараллеливаем тесты, используя Xcode

Вам понадобится:

  • Xcode версии ≥ 11.7;

  • Тест-план, содержащий ≥ 2 классов с тестами.

В тест плане нужно выбрать “Execute in parallel”

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

  • Первый содержит - 3;

  • Второй содержит - 2;

  • Третий содержит - 10.

В таком случае xcode создаст три симулятора и запустит на каждом классе с тестами. Xcode не станет вам делить их поровну для каждого симулятора.

Распараллеливаем тесты, используя Fastlane

В качестве примера рассмотрим реализацию на multi_scan - это плагин для fastlane.

Представим ситуацию, что у нас 40 тестов, и мы хотим их прогнать на 4 симуляторах.

multi_scan(
  project: 'yourProjectPath',
  scheme: 'SwiftRadioUITests',
  fail_build: false,
  device: 'iPhone 8',
  batch_count: 4,
  parallel_testrun_count: 4
)

Нас интересуют параметры:

  • batch_count - на сколько частей стоит поделить общее количество тестов для запуска на симуляторе. Например, у вас 40 тестов, и мы указываем значение 4, тогда на каждом симуляторе запустится по 10 тестов.

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

Указывайте одинаковые цифры в этих двух параметрах.

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

multi_scan(
  workspace: 'yourProjectPath',
  scheme: 'SwiftRadioUITests',
  fail_build: false,
  destination: 'platform=iOS Simulator,name=iPhone 8,OS=13.1',
  parallel_testrun_count: 2,
  batches: [
    [
      'SwiftRadioUITests/RegressionTests/testExample1',
      'SwiftRadioUITests/RegressionTests/testExample2',
      'SwiftRadioUITests/RegressionTests/testExample3'
    ],
    [
      'SwiftRadioUITests/RegressionTests/testExample4',
      'SwiftRadioUITests/RegressionTests/testExample5',
      'SwiftRadioUITests/RegressionTests/testExampl'
    ]
  ]
)

Обратим внимание на параметры:

  • batches - это массив с вашими тестами. Его следует использовать, если вы хотите явно указать какие тесты должны прогонять на каждом симуляторе. В массиве вы должны указать путь к вашему тесту по след схеме: Имя тестового таргета/ Имя класса с тестами/ Имя теста.

  • destination - это аргумент, в котором вы можете указать определенный: симулятор, физический девайс, mac.

Разберем более подробно destination:

Ключ

Описание

Пример значения

platform

Поддерживаемая платформа

iOS Simulator, tvOS Simulator, watchOS Simulator

name

Полное имя симулятора, которое можно найти в “Devices and Simulators”

iPhone 8, Apple TV, Apple Watch SE - 40mm

id

UDID вашего устройства. UDID можно достать используя утилиту simctl

6DC4A7BA-EA7F-40D6-A327-A0A9DF82F7F6

OS

Версия iOS, tvOS, watchOS. Указываем версию, которую поддерживает Xcode

OS=13.1

Немного примеров для понимания destination:

  1. Указываем симулятор iPhone X на версии ОС 13.1.

    -destination 'platform=iOS Simulator,name=iPhone X,OS=13.1'
    
  2. Указываем симулятор используя UDID симулятора.

    -destination 'platform=iOS Simulator,id=6DC4A7BA-EA7F-40D6-A327-A0A9DF82F7F6'
    

Самое важное

  • Распараллеливание тестов позволяет вам ускорить прохождение ваших тестов в несколько раз!

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

  • Для распараллеливании тестов на ci воспользуйтесь плагином multi_scan для fastlane. Реализация очень простая, а профита много.

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

Полезные статьи на эту тему:

Навигация по статьям:


Интересуешься автоматизацией на iOS? Подписывайся на мой телеграмм-канал, в котором я публикую материалы, которые будут полезны как начинающим, так и опытным iOS-автоматизаторам.

Комментарии (5)


  1. stopper79
    25.02.2022 17:07

    Я, конечно только недавно, закончил курсы "Тестировщиков", но, почему не docker? Для CI/CD Вы используете плагин? Почему не Jenkins, GitLab, etc?


    1. Boris_Lys Автор
      25.02.2022 17:13

      CI может быть любой: Jenkins, Gitlab и.т.д. В разделе "Распараллеливаем тесты на CI", я показываю скрипт для запуска тестов на fastlane(раннер). И этот скрипт можно добавить в job любого удобного для вас CI. Возможно мне стоит изменить названия заголовков, чтобы не вводить в заблуждения ????


    1. Boris_Lys Автор
      25.02.2022 17:21

      Поправил заголовки. Спасибо за комментарий


  1. Gernok
    25.02.2022 17:09

    На xcode 13.2 сейчас на этом плагине постоянно происходят падения на объединении репортов, когда количество симуляторов больше 1. Разработчик фиксить не планирует. Как решали эту проблему?


    1. Boris_Lys Автор
      25.02.2022 17:26

      Пока что никак, во время написания статьи использовал xcode 13.1. Спасибо за комментарий! Будем думать, что с этой проблемой делать