02/09/2022

Мобильная автоматизация

Мобильная автоматизация

Сложности мобильной автоматизации

Основные сложности при автоматизации тестирования мобильных приложений:

  1. существует несколько платформ: Android, iOs;
  2. у Android есть разные лаунчеры, обертки, которые также хотелось бы покрыть;
  3. сложный деплой, сложнее чем на вебе, тк прежде чем запустить тесты нужно собрать билды (их нужно где то собирать и как то передавать в тесты). Также сложные хот фиксы, их не так просто сделать как в вебе, например, нужно проходить процесс ревью перед заливом в маркет;
  4. сложность в масштабировании (параллелизации и многопоточном запуске), т. к. используется много ресурсов для запуска мобильных тестов( и для эмуляторов, и для реальных устройств) запустить всё во много потоков не так просто и дорого;
  5. дорогостоящая инфраструктура - есть простой вариант, использование cloud ферм для запуска тестов, но цена у них очень высокая. А для запуска на реальном железе - для iOs нужны Mac устройства, с хорошими ресурсами и это тоже дорого.
  6. нестабильные тесты - т.к. в моб приложении ограниченная зона видимости, мы видим только те элементы, которые отображаются на экране. Могут быть разнообразные popup, push сообщения, нотификации, которые перекрывают элементы.

Однако, в автоматизации моб приложений мы используем тот же паттерн Page Objects, Selenium под капотом и тот же подход к написанию тестов (Arrange(подготавливаем данные) - Act(выполняем действие) - Assert(проверяем)).

Инструменты для мобильной автоматизации

AppiumEspressoXCUITestDetoxSelendroid
iOS+-+++
Android++-++
TypeBalck boxWhite boxBlack boxGrey boxBlack box
Programming LangAlmost anyKotlinSwiftJavaScriptJava
CostFreeFreeFreeFreeFree
CommunityVery activeGoogleAppleWixAverage
SpeedSlowFastFastFastSlow
Web, native, hybrid+Hybrid and nativeOnly nativeOnly+

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

Detox - подходит только для приложений на react native, нативные моб приложения им не получится автоматизировать.

Espresso, XCUITest - нативные инструменты, заточные под свою платформу.

Преимущества Appium

  1. Возможность писать кросс платформенные тесты. Написав один раз тест под одну платформу, нужно минимальное количество действий чтобы адаптировать его под другую (добавить соответсвующие локаторы и обработать индивидуальные особенности платформы);
  2. Позволяет писать тесты на практически любом языке программирования;
  3. Нет необходимости модифицировать код приложения. Appium - полный Black box и нам ненужно модифицировать код самого приложения;
  4. Работает на основе Selenium JSON wire protocol;
  5. Open source фреймворк с активным комьюнити. Спонсируется souce lab которая также предоставляет cloud решения;
  6. Поддержка параллельного запуска используя Selenium Grid;

Архитектура Appium

Appium - это http сервер.

У нас есть тестовый скрипт, мы передаем его в Appium и Appium транслирует его на мобильные устройства, с помощью json wire protocol.

Appium - это обертка над теми же нативными инструментами(XCUITest и UIAutomator, Expresso), т.к. он все свои команды дальше ретранслирует в команды понятные нативным инструментам.

Для iOS используется XCUITest, для Android можно выбрать между UIAutomator и Expresso.

Для Expresso добавили поддержку примерно в 2020 г, он на 20% быстрее, чем UIAutomator. Плюс Expresso делает Appium немного Grey box'ом, потому что есть возможность сделать backdoor к приложению и в целом делает немного более открытым код приложения.

JSONWP(JSON wire protocol) - механизм, созданный командой разработчиков WebDriver. Этот протокол представляет собой набор четко определенных стандартизированных endpoints, открытых через RESTfull API.

AppiumDriver.getPageSource(); - этот метод вызовет HTTP-запрос, и получит ответ от API. Назад вернется page source в формате строки.

/session/:sessionId/source - эндпоинт, который обрабатывает метод getPageSource.

Appium + Android

Appium работает с Android через Espresso и UIAutomator. Поддерживается Google. Espresso быстрее чем UIAutomator.

Appium + iOS

Несколько лет назад под капотом использовался не XCUITests, а другой фреймворк. Но Apple решила прекратить его поддержку и выпустила XCUITests. А XCUITests на тот момент противоречил философии Appium, в том что нам не нужно модифицировать код, т.к. XCUITests нужно было собирать вместе с приложением.

И некоторое время, Appium нельзя было использовать для iOS приложений. На помощь пришел Facebook и сделал WebDriverAgent Server. При запуске тестов на Appium'e на моб устройство также ставится WebDriverAgent и он транслирует команды от Appium к XCUITests.

Способы запуска

  • на реальных устройствах;

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

  • на симуляторах/эмуляторах;

Оптимальный вариант. Не так много кейсов, которые репродьюсятся только на реальных устройствах. Они есть но их не много.

для iOS - используются симуляторы, на Android поднимаются эмуляторы.

Используются стандартные эмуляторы, которые предоставляет Android Studio и симуляторы от XCode для iOS.

  • на cloud фермах
    • Browser Stack (2 параллельных запуска ~ 400вмесяц,5параллельныхзапусков 1000в месяц, 5 параллельных запусков ~ 1000 в месяц)
    • Sauce Labs
    • AWS Device Farm

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

Запуск тестов

  • для iOS

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

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

  • для Android

Собираем apk через Gradle и Android Studio на эмулятор и на реальное устройство и можно работать.

Что нужно чтобы начать?

Android

  • JDK (Java Development Kit)
  • Android SDK
  • Appium

iOS

  • Mac OS
  • XCode
  • JDK (Java Development Kit)
  • Homebrew
  • Node and npm

https://qa-automation.git-doc.evo.dev/mobile/ubuntu.html

Стек инструментов

  • Appium
  • Java/Kotlin
  • TestNg
  • Maven
  • Allure REport
  • AssertJ
  • Log4J

Инструменты чтобы находить локаторы

Android

  • UIAutomatorViewer (Android)
  • Appium Inspector - делает скриншот текущего экрана и показывает состояние выбранного элемента.

Можно искать элементы по id и по xPath:

  • Id

resource-id = id

@AndroidFindBy(id = "tvProSalePay")
  • xPath
@AndroidFindBy(xpath = "//android.widget.TextView[@text = 'XL']")

iOS

Можно использовать только Appium Inspector, так как нет других инструментов для этой цели.

Можно искать по id, iOSClassChain, iOS predicate string (в порядке снижения скорости).

По xPath тоже можно но крайне не рекомендуется так как это происходит очень медленно из за того что в iOS приложениях нет xml дерева и appium его вычисляет самостоятельно а на это тратится время.

  • Id
@iOSXCUITFindBy(id="client name")
  • iOSClassChain Аналог xPath.
@iOSXCUITFindBy(iOSClassChain="**/XCUIElementTypeButton[`name == 'icRatingStar'`]")
  • iOS predicate string

Свой тип локаторов.

String selector = "type == 'XCUIElementTypeButton' AND value BEGINSWITH[c] 'bla' AND visible == 1"

Боли Appium

Недоступные элементы

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

Решение:

  1. Можно использовать библиотеку tesseract - для распознавания текста на изображении.
  2. Клики по координатам.
    Если нужно кликнуть на элемент, которого нет в дом дереве.
    В этом случае лучше брать не координаты этого элемента, а стараться брать соотношение по экрану (находить центр и т.д.), потому что если мы поменяем устройство, на котором будем прогонять и там расширение экрана другое, то мы столкнемся с трудностями.

Ограниченная зона видимости

Когда мы делаем скриншот в Appium, мы видим дерево только тех элементов, которые есть сейчас на экране, то что вне мы не видим.

Решение:

Дойти до элементов вне зоны видимости мы можем только проскролив.

  • iOS
HashMap<String, String> scrollObject = new HashMap<>();
scrollObject.put("element", element.getId());
scrollObject.put("toVisible", "true");

driver.executeScript("mobile:scroll", scrollObject);
  • Android
protected void scrollToElementAndroid(String scrollableListId, String selectionText){
    ((AndroidDriver) driver).findElementByAndroidUIAutomator("new UiScrollable(new UiSelector().scrollable(true)"
    + ".resourceId(\"" + scrollableListId + "\"))"
    + ".setAsHorizontalList().scrollIntoView(new UiSelector().text(\"" + selectionText + "\"))").click();
}

Универсальный скролл

public void swipeUpToFindElement(By by, int maxSwipes){
    int alreadySwiped = 0;
    while(driver.findElements(by).size() == 0){
        if (alreadySwiped > maxSwipes){
            waitForElementToBePresent(by, "Невозможно найти элемент по свайпу", Constants.SMALL_TIMEOUT);
            return;
        }
        swipeUpQuick();
        Log.info("Выполнен свайп");
        ++alreadySwiped;
    }
}

Платформозависимость

У Android и iOS есть свои особенности.

  • Разные атрибуты у элементов iOS - value, android - text iOs - visible, android - displayed iOS - enabled, android - checked, checkable, enabled

  • Различия в основных флоу приложения на Android и на iOS

  • Часто при работе с веб вью на разных версиях Android у элементов разный xPath

@AndroidFindAll(

)

watch?v=zp0qC6JT0rE