Тестирование Flutter-приложений c помощью Appium |
16.10.2023 12:08 |
Автор: Дмитрий Тумашев Flutter - это открытый и бесплатный фреймворк для разработки мобильных приложений от Google, который предлагает набор функций для создания кросс-платформенных приложений. Однако, как и любой другой инструмент, он требует эффективного использования практик тестирования для гарантии его качества. С помощью стандартной библиотеки Flutter, разработчики могут создавать различные типы тестов: unit-тесты, widget-тесты и интеграционные тесты. Каждый из этих типов тестов имеет свое специфическое применение и важность. Рассмотрим интеграционные тесты. Они проверяют, как взаимодействуют несколько частей приложения вместе, или даже весь стек приложения в целом. Так как фреймворк уже содержит в себе инструменты для написания таких тестов, Flutter-разработчики могут писать тесты, не используя дополнительных внешних инструментов. Если же тесты пишет отдельная QA-команда, это может стать проблемой, так как Dart - далеко не самый популярный язык. К счастью, есть инструменты, которые позволяют тестировать Flutter-приложения не используя Dart. Appium - это открытый инструмент автоматизации тестирования, который позволяет вам тестировать все типы приложений: нативные, гибридные, а также мобильные веб-приложения, в том числе и Flutter, используя популярные языки программирования. Appium состоит из трех основных компонентов или модулей:
Для Flutter добавляется третий элемент - библиотека Appium-Flutter-Driver, которая позволяет тестовым сценариям взаимодействовать с Flutter-приложением. В этом гайде описывается, как настроить окружение для тестирования с помощью Appium и создать тесты для Flutter-приложения используя Python. Начало работыПредположим, что у нас уже есть какое-то приложение для тестирование. В этом гайде я буду использовать маленькое тестовое приложение, которое может следующее:
Такой набор функциональности позволит показать написание тестов не только для самого Flutter, но и для нативных и WebView-компонентов, т.к. они часто присутствуют во Flutter-приложениях. Весь путь этого гайда можно повторить самому - весь код хранится в репозитории appium_flutter_demo, ветка - Для начала нам понадобится установленные Node и Python3, а также XCode и Android Studio. Если ваша платформа не MacOS, можете просто пропускать все части, связанные с iOS и Маком. Тестирование под Android остается идентичным. Подготовим инструменты, которые будут выполнять тестирование приложения, а именно сам Appium и Flutter Appium Driver. Установка AppiumМожно установить последнюю версию (
Устанавливаем Appium Flutter Driver.
Настройка Flutter-проектаДля того, чтобы Flutter-приложением можно было управлять с помощью Flutter Appium Driver, добавим в проект пакет flutter_driver.
Необходимо включить расширение flutter_driver при запуске приложения. Включение расширения влияет на поведение приложения, так, например, хардверная клавиатура не будет работать, потому что её заменяет виртуальная клавиатура flutter_driver. Чтобы избежать нежелательного поведения при обычной работе с приложением в debug/profile режиме, добавим отдельную точку входа в программу. Создадим файл
Соберем тестовые билды. flutter_driver может работать только если приложение собрано в debug или profile режиме. Тесты у меня будут прогоняться на симуляторе iOS и эмуляторе Android. Если сборка под Android не отличается между эмулятором и реальным устройством, то у iOS всё иначе. Profile-режим недоступен для симулятора, также нужно указывать, что сборка выполняется именно под симулятор.
Записываем пути к созданным файлам, они еще понадобятся. Настройка проекта с тестамиТеперь можно заняться созданием проекта с тестами. Я буду использовать Python, но Appium имеет поддержку и других ЯП. API пакетов для разных языков отличается, поэтому при необходимости писать тесты, например, на Java или JS, сверяйтесь с документацией. Для работы с проектом установим Poetry. Вы можете использовать любой другой инструмент для управления зависимостями или вообще устанавливать пакеты через
Создаём проект
Добавляем в проект зависимости для работы с Appium и Flutter Driver. Кроме того, добавим пакет dotenv, чтобы далее можно было удобно указывать конфигурацию для тестов на конкретной машине.
Создадим файл .env в корне проекта и добавляем в него следующие значения:
Так как приложение работает и на iOS, и на Android, сделаем тесты кроссплатформенными. Платформу выполнения тестов определит переменная окружения “PLATFORM”. Создадим в проекте enum текущей платформы:
Теперь можно настроить работу Appium. Для конфигурации подключения и поведения Appium использует такое понятие, как capabilities. По своей сути это JSON, который передается серверу Appium при создании сессии. Подробнее можно почитать в официальной документации. Нас же интересуют конкретные параметры, которые нужны для корректной работы наших тестов.
Создадим файл
Теперь создадим наш собственный класс для тест-кейсов, который будет наследовать питоновский
В В Контексты приложенияОдин из основных концептов в Appium - контексты. Нативная часть, Flutter, встроенные WebView - Appium использует разную логику и инструменты для работы с каждой из этих частей приложения. Именно эти части и называются контекстами. Если мы рассматриваем Flutter-приложения, контекстов будет три:
Для переключения между контекстами используется метод Для удобства работы с контекстами добавим соответствующие методы в наш класс:
WebView на Android имеет идентификатор - Отметим, что Теперь поговорим о поиске элементов и взаимодействии с ними. Работа с элементамиВ зависимости от контекста используются два разных способа поиска элементов. FlutterПри работе во Flutter-контексте используются методы самого Flutter Driver. Поиск элементов выполняется с помощью метода класса
Все доступные файндеры и команды можно посмотреть в репозитории appium-flutter-driver. Можно написать свои, что еще предстоит сделать дальше. Сам файндер определяет только условия поиска. Для самого выполнения поиска элемента в приложении и взаимодействии с ним используется конструктор класса
Элемент можно получить с помощью конструктора класса Натив и WebViewЕсли при работе с контекстом Flutter нужно отдельно создавать условие для файндера, а потом использовать конструктор Enum Стандартные команды для элементовВне зависимости от того, работаем мы с Flutter, нативом или вебом, основные команды для элемента у нас одинаковые, т.к.
Ожидание появления элементовНе все элементы на экране появляются мгновенно. Элементы могут отображаться после загрузки данных из сети или из хранилища, диалоги и переходы между экранами происходят с анимациями, приложение может подтормаживать и так далее. Если мы будем искать элементы без ожидания, то тесты могут проваливаться, поэтому часто нам нужно ждать появления элемента. Самый банальный вариант - жесткое ожидание с помощью Для Flutter есть команда Эту функциональность можно использовать для того, чтобы проверять, есть ли элемент на экране. Напишем два метода, использующих эту функциональность. Они будут возвращать
Теперь можно написать методы получения элементов:
Благодаря этим методам в тестах мы сможем писать короткий и понятный код. Написание тестовСоздание первого теста для FlutterСпустя пару часов приготовлений мы наконец-то можем написать наш первый тест-кейс :) Создадим файл с тестами В него добавим класс Запускаем приложение командой
В открывшемся окне браузера включаем “Select Widget Mode” и нажимаем в симуляторе на нужный нам виджет или ищем его вручную в дереве виджетов. Так, нажав на кнопку “Добавить”, искомый виджет фокусируется в дереве, и мы можем просмотреть всю необходимую информацию о нем, например, тип виджета -
Находим кнопку “Добавить” по её типу, нажимаем на неё, а затем проверяем успешное открытие диалога создания новой записи. Благодаря тому, что ожидается появление элемента на экране в течение 5 секунд, тест проходит успешно. Без этого ожидания проверка выполнялась бы мгновенно, и диалог не успевал бы появиться на экране. Запустим Appium и тесты. Проследим, что наш единственный тест выполняется успешно.
Взаимодействие с нативными элементамиТеперь напишем тест на выбор изображения из галереи. Здесь будем взаимодействовать с нативными компонентами самой ОС, и напишем сценарии для прогона и на iOS, и на Android. Для того, чтобы определить возможные условия поиска нативных элементов, отлично подходит Appium Inspector - еще один клиент для Appium, который позволяет в удобном UI взаимодействовать с тестируемым приложением. Загружаем приложение с GitHub и запускаем. Перед нами откроется окно, где можно задать параметры соединения и необходимые capabilities. Указываем такие же параметры, как и в нашем проекте. Нажимаем “Start session”. После этого на симуляторе должно запуститься приложение, а в окне Инспектора отобразится активная сессия. Слева теперь видим окно с приложением, в котором на данный момент будет бесконечная загрузка. Appium Inspector не поддерживает контекст Flutter, в котором запускается наше приложение, и считает, что приложение работает в нативном контексте. Сверху переключаем контекст на “Hybrid”, и обратно на “Native”, после чего приложение должно успешно отобразиться в окне. Открываем диалог добавления записи, нажимаем кнопку “Выбрать файл”. Обновляем данные в инспекторе и выбираем желамое изображение. В первом разделе получим возможные варианты для поиска элемента. С Андроидом все работает аналогично. Меняем capabilities в конфигурации, запускаем приложение на эмуляторе и открываем пикер файлов. Видим доступные варианты поиска элементов. Переходим к написанию теста. Создаём новый тест и, на основе текущей платформы, используем разные условия поиска. Не забываем переключиться между контекстами.
Теперь можем запустить тесты на обеих платформах и проверить, они корректно выполняют все действия.
Отметим, что здесь жестко указано, какой файл нужно выбирать в пикере. Если этот конкретный файл будет отсутствовать на устройстве, тест упадет. Вместо точных данных о элементе, можно использовать XPath или iOS Class Chain, которые позволяют, например, выбирать элемент по его порядку в списке. Ввод текстаПишем тест на ввод названия записи. Здесь всё просто. Открываем диалог, вводим текст в поле, проверяем наличие текста.
Создание собственного файндераВозьмем пример с добавленной записью. Кнопка удаления записи представлена в виде одинокой иконки. Найти эту кнопку можно через файндер Поиск иконок реализуем по их значению - строкам вида Создаём файл
Добавляем файл
Указываем это расширение в методе
Теперь можно пересобрать приложение и использовать новый файндер в наших тестах, например, в тесте на удаление записи.
Взаимодействие с WebViewНапишем тест поведения кнопки “Найти в Wikipedia” у добавленной записи. После нажатия на нее должен открываться поиск Википедии, в который уже предустановлено название записи. В Appium Inspector есть возможность работать с WebView, но она достаточно ограничена. Даже сам Инспектор предупредит об этом следующим сообщением: Следуем совету в сообщении и переходим на нужную страницу в Chrome вручную и открываем DevTools. Далее выбираем, по какому критерию будем искать элемент. Если ID элемента статичный, то XPath - самый простой вариант. В текущем примере используем именно его. Далее нам нужно проверить значение, установленное в строке поиска, поэтому скопируем XPath для нее - Пишем тест:
Заметим, что этот тест корректно выполняется на iOS, но на Android - падает. Это происходит из-за того, что для управления WebView используется отдельное приложение Chromedriver, которое необходимо добавить в наш проект. Для этого нужно запустить Appium Server c параметрами, позволяющими автоматическую загрузку Chromedriver.
В capabilities для Android нужно указать путь к Chromedriver, куда он будет скачиваться и откуда будет использоваться. Я добавил этот путь в .env, чтобы можно было легко его менять на разных ПК.
Теперь можно снова запустить тесты и удостовериться, что наш новый тест для WebView корректно выполняется. На этом написание тест-кейсов можно считать законченным. ЗаключениеМы рассмотрели, как использовать Appium для автоматического тестирования приложений на Flutter. Описанные тест-кейсы покрывают основные сценарии взаимодействия с приложением, как с Flutter-частью, так и в гибридном режиме вместе с нативом. Надеюсь, гайд послужит хорошей отправной точкой для работы с Appium в вашем проекте. Если у вас остались вопросы или есть дополнения - приглашаю в комментарии. Полный код проекта можно посмотреть в репозитории. Удачного тестирования! |