Всем привет! Меня зовут Стас, и я Senior QA в компании inDrive, наставник на курсе «Инженер по тестированию плюс» в Яндекс Практикуме. Ещё веду телеграм-канал «Тестировщики нужны».
Многие начинающие автоматизаторы задаются вопросом: «Как же написать свой первый автотест на мобильное приложение?». В данной статье я и хотел бы ответить на этот вопрос. На самом деле, материалов на эту тему написано большое количество. Подробно рассказывается применение паттерна PageObject в написании тестов и многое другое. Но наша с вами задача — написать наш первый простенький тест на экран авторизации на языке Java. Давайте решим эту задачу вместе!
Введение в тестирование мобильных приложений
На текущий момент при тестировании практически любого мобильного приложения вы столкнётесь с двумя операционными системами: iOS и Android. В данной статье мы будем работать с Android-приложением.
Для выбора правильного подхода к тестированию мобильного приложения необходимо определиться с его видом. На текущий момент имеется три вида приложений:
нативные приложения — такие приложения, которые устанавливаются на смартфон и работают непосредственно на смартфоне. Нативные приложения не предполагают работу и взаимодействие с браузером и интернетом;
веб-приложения — такие приложения адаптированы под десктопную и мобильную версию;
гибридные приложения — нативные приложения, внутри которых встроена возможность открывать веб-страницы.
Определившись с видом и типом мобильного приложения, можно смело переходить к разработке тестов. Обычно тестами называют последовательность шагов, выполнение которых приводит продукт в требуемое состояние. Во время тестирования исполняется весь набор заготовленных заранее тестов.
![](https://habrastorage.org/getpro/habr/upload_files/4eb/a9f/ca7/4eba9fca73dd15f7d6b7829320239171.png)
Существует два, скажем, вида тестирования — ручное и автоматизированное. В ручном тестировании тесты, разумеется, исполняет тестировщик, обычно такая позиция называется Manual QA. И тестировщик является связующим звеном между тестами и приложением. Выглядит это примерно следующим образом.
![](https://habrastorage.org/getpro/habr/upload_files/a9e/e3f/755/a9ee3f755aee5eba359e06a8e388c95c.png)
Сказать, что тестировщик напрямую работает с приложением, не совсем верно. Во время исполнения тестов он нажимает на кнопки, что-то вводит в поля, иными словами, работает с интерфейсом приложения. Также тестировщик работает и с API сервиса, и с сетевым интерфейсом, CLI, GUI и т. д. Если API используются клиентами-программами для взаимодействия с сервером, то GUI используется человеком.
![](https://habrastorage.org/getpro/habr/upload_files/c9f/cf7/822/c9fcf7822666a680a6f92adc5fd3234d.png)
Ручное тестирование — это, конечно, хорошо, но давайте посмотрим на вариант замены ручного труда на автоматизированный. Вместо тестировщика с приложением будут взаимодействовать программные клиенты. Но кто же будет запускать тесты, спросите вы? Верно! За запуск тестов будет отвечать фреймворк тестирования. Он запускает тесты, показывает результаты прогонов, хранит историю запусков и многое другое.
Для работы с GUI интерфейса необходимы специальные адаптеры, их ещё называют драйверами (да, да, многие вспомнят, чтобы звук на компьютере воспроизводился, а, например, видеокарта передавала изображение, необходимо было устанавливать драйверы). Например, в нашем тесте имеется шаг с тапом на кнопку Поиск. Драйвер получает команду, что ему нужно тапнуть на кнопку Поиск, а затем эту команду передаёт нужному интерфейсу в нашем приложении. В результате нажимается кнопка Поиск, тест успешно пройден. Если же кнопки нет либо по какой-то причине она не нажимается, то будет ошибка, тест падает.
![](https://habrastorage.org/getpro/habr/upload_files/0f7/53c/90f/0f753c90f2fafe08bd1e926254c7e107.png)
Часто функциональности драйвера может не хватать для решения каких-либо нестандартных задач, не хватает должного уровня логирования. И для решения таких проблем используются различные обёртки. Например, Kakao или Kaspresso. Эти обёртки могут сильно различаться в зависимости от решаемых задач. Некоторые из них — просто синтаксический сахар (это синтаксические возможности, применение которых не влияет на поведение программы, но делает использование языка более удобным для человека), другие же — довольно толстая прослойка, выполняющая много сложной работы.
![](https://habrastorage.org/getpro/habr/upload_files/6da/0cc/327/6da0cc327d61d07b38e6429b169fe430.png)
Установка инструментов
Выбор языка
Существуют различные языки, которые можно использовать для автоматизации тестирования, например: Java, Python, Kotlin, Swift, JavaScript и многие другие. Всё зависит от вас и от того, какие цели вы преследуете. Мы будем использовать в нашем примере язык Java. Для этого необходимо его скачать и установить с официального сайта.
Android Studio
Android-приложение можно запустить как на физическом устройстве, так и на эмуляторе. Чаще всего запускают автотесты на эмуляторах. Для этого необходимо скачать и установить Android Studio с официального сайта.
Appium
Следующий наш инструмент — Appium (инструмент с открытым исходным кодом, который помогает автоматизировать приложения как для Android, так и для iOS). Есть две возможности запуска Appium: UI или консольная. Для установки и запуска консольной версии нам дополнительно понадобится NodeJs. А UI-версию можно скачать с официального сайта, и она сразу будет готова к работе.
Appium Inspector
Для поиска локаторов (локатор — это путь к элементу в интерфейсе, с помощью которого автоматизированный тест (автотест) сможет его найти) нам понадобится инспектор графического интерфейса.
Appium Inspector — это просто клиент Appium с пользовательским интерфейсом, где отображается экран тестируемого приложения и где мы можем посмотреть пути к элементам.
IntelliJ IDEA
Разрабатывать мы будем в IntelliJ IDEA, которая также доступна для скачивания с официального сайта, где я предлагаю выбрать Community Edition версию.
Приложение
Мы с вами будем разрабатывать тесты на приложение, которое вы сможете скачать себе и самостоятельно собрать в Android Studio. Оно доступно по ссылке. Или же можно скачать apk.
Настройка и установка эмулятора Android Studio
Вопрос выбора операционной системы для автоматизации Android не сильно критичен. У вас может стоять как ОС Windows, Linux, так и MacOS.
Для старта нам будет нужен Android SDK и установленная Android Studio. Нам необходимо будет создать эмулятор. Не будем в статье останавливаться на этом, так как гайд по настройке эмулятора хорошо расписан в официальной документации.
Настройка Appium
После того как мы настроили Android Studio, давайте мы с вами настроим Appium. Откроем установленный ранее Appium UI. Нам необходимо в поле Host указать адрес 0.0.0.0, а в Port: 4723.
![](https://habrastorage.org/getpro/habr/upload_files/e4e/a34/7ef/e4ea347ef2b2b72545d6674b98bbaa29.png)
Затем перейдём в Edit Configurations и укажем пути ANDROID_HOME и JAVA_HOME, как показано на скриншоте ниже, и нажмём Save and Restart:
![](https://habrastorage.org/getpro/habr/upload_files/876/8cc/462/8768cc462a3cfb523c527ffa62c3b125.png)
Обратите внимание, что ваши пути могут отличаться от представленных на скриншоте, как минимум, разными пользователями.
Затем перейдём в Appium во вкладку Advanced и проверим, что ваши настройки в полях Server Address, Server Port такие же, как и на скриншоте ниже:
![](https://habrastorage.org/getpro/habr/upload_files/255/600/610/255600610bf6b3deac095cd8465bb9b4.png)
После настройки всех необходимых полей нажмём кнопку Start Server и убедимся, что Appium Server запущен:
![](https://habrastorage.org/getpro/habr/upload_files/0c9/e7d/2a7/0c9e7d2a7da3eab776d7b21a7f0bb6ed.png)
На данный момент нам с ним делать ничего не нужно, оставим запущенный Appium Server.
Настройка Appium Inspector и поиск локаторов
Для того чтобы наши тесты понимали, с какими элементами интерфейса мы будем взаимодействовать, нам необходимо узнать, как к этим элементам можно обращаться. Для этого запустим Appium Inspector и укажем Remote Host: 0.0.0.0, а также Remote Path /wd/hub, как показано ниже на скриншоте:
![](https://habrastorage.org/getpro/habr/upload_files/de9/038/ca5/de9038ca5fdbb892845a38f843f38465.png)
Теперь перейдём к Capability. Capability — это набор параметров и значений, используемых для запуска сеанса Appium. Информация в наборе используется для описания того, какие «возможности» вам требуются во время запуска эмулятора. Например, определённую мобильную операционную систему или определённую версию устройства. Capability представлены в виде пар ключ-значение, причём значения могут быть любого допустимого типа JSON.
{
"appium:platformName": "Android",
"appium:deviceName": "autoschool10",
"appium:app": "/Users/s.yakovlev/Desktop/login.apk"
}
В переменной appium:platformName
у нас указана платформа Android, в переменной appium:deviceName мы указываем имя нашего созданного Android эмулятора, у нас он называется "autoschool10", а также путь, до .apk.
![](https://habrastorage.org/getpro/habr/upload_files/f58/a21/6f5/f58a216f5ab383b2a4150c01c3b5c23e.png)
Сохраним указанные capability и назовём этот пресет как loginAndroidApp, на самом деле название не играет никакой роли, оно должно быть понятным вам самим.
![](https://habrastorage.org/getpro/habr/upload_files/72f/a5e/ffd/72fa5effdde5994b98c9ac1ffdc70ade.png)
Сохранённые capability доступны во вкладке Saved Capability:
![](https://habrastorage.org/getpro/habr/upload_files/1bf/0c6/758/1bf0c67589821cb0d28d297f94aeea33.png)
Теперь нам осталось открыть Android Studio и запустить созданный ранее эмулятор и в Appium Inspector нажать Start Session.
![](https://habrastorage.org/getpro/habr/upload_files/844/f45/7dd/844f457dd5482717edfd8ead2f209dc0.png)
У нас запускается Appium Inspector, где в левой части отображается снимок экрана, а справа дерево элементов.
![](https://habrastorage.org/getpro/habr/upload_files/d28/13b/1e6/d2813b1e642a50ce8590ab911bab152c.png)
Мы напишем три теста:
первый будет проверять, что отображается название Login в таббаре,
второй тест проверит позитивный сценарий авторизации,
а третий тест проверит негативный сценарий авторизации.
Для этого нам понадобятся пути к данным элементам. Начнём с таббара. Кликнем на название Login — и мы увидим, что справа отобразятся свойства данного элемента:
![](https://habrastorage.org/getpro/habr/upload_files/adc/33f/cab/adc33fcabbbd0b6059bc8ab38056ce9d.png)
Выпишем id этого элемента, он нам понадобится несколько позже: com.example.login:id/toolbar
То же самое проделаем с полями Email и Password. Для Email id будет com.example.login:id/username
и com.example.login:id/password
соответственно для поля с паролем.
![](https://habrastorage.org/getpro/habr/upload_files/1c3/818/453/1c381845364c06095666eaa52d424678.png)
![](https://habrastorage.org/getpro/habr/upload_files/e27/826/170/e27826170e375ebc01edd8ddd9e01f79.png)
Также узнаем id для кнопки SIGN IN OR REGISTER:
![](https://habrastorage.org/getpro/habr/upload_files/70d/b1c/45f/70db1c45f41de6fbc6edd691ceaaadb9.png)
Её id будет com.example.login:id/login.
Если пользователь вводит следующие валидные данные email: admin@admin.ru и пароль: 1234, то ему показывается текст: Welcome ! user. Введём данные в поля и убедимся:
![](https://habrastorage.org/getpro/habr/upload_files/980/e69/e36/980e69e36471c8e2fd4df5e02f68e468.png)
Но, как вы можете заметить, в инспекторе ничего не поменялось, а нам нужно узнать id этого текстового поля. Ничего страшного, давайте просто нажмём на кнопку Refresh
![](https://habrastorage.org/getpro/habr/upload_files/3e7/247/9e8/3e72479e8f9796e377fda83fb9e67735.png)
и сделаем новый снимок экрана. К нам подтянулся новый снимок экрана, и мы можем теперь узнать id этого текстового поля com.example.login:id/succestext:
![](https://habrastorage.org/getpro/habr/upload_files/d42/a48/80f/d42a4880f27d561103cf0e4c1d7c38de.png)
Если же ввести в эмуляторе неверный пароль или почту, то будет ошибка авторизации и покажется соответствующий текст.
![](https://habrastorage.org/getpro/habr/upload_files/801/8df/5ad/8018df5adf88f258dfaf45db5ddf970d.png)
Вы, конечно, могли уже заметить, что данное сообщение об ошибке имеет точно такой же id, но если приглядеться, то текст ошибки в поле text совершенно иной. Это нам и потребуется.
Теперь, когда все id элементов мы выписали, давайте приступим к написанию тестов.
Настройка библиотек
Разрабатывать тесты мы будем в IntelliJ IDEA. Для этого запустим IDEA и создадим директорию, например, на рабочем столе и назовём её androidAutomation.
После того как мы создали дефолтный проект, давайте подключим к нему библиотеки:
![](https://habrastorage.org/getpro/habr/upload_files/752/c58/637/752c58637a3833f6e8c976b77e8fcbeb.png)
![](https://habrastorage.org/getpro/habr/upload_files/cf7/02e/555/cf702e555ae05e1fd5dd5de8ce27ecc9.png)
![](https://habrastorage.org/getpro/habr/upload_files/ad1/926/e93/ad1926e936ea65e403023e97b10027a4.png)
Для вашего удобства мы собрали все библиотеки в одном месте.
Откроем созданный проект и создадим директорию libs:
![](https://habrastorage.org/getpro/habr/upload_files/805/e15/0f5/805e150f5d0e289e7bb631f97c61db2e.png)
Далее поместим в нашу директорию скачанные библиотеки:
![](https://habrastorage.org/getpro/habr/upload_files/d45/8c3/2f6/d458c32f611477766146c0496b250861.png)
![](https://habrastorage.org/getpro/habr/upload_files/17d/8d2/64e/17d8d264ea49cb2fff738f595f955da6.png)
Теперь перейдём в наш проект, в раздел Project Structure, и добавим наши библиотеки из папки libs:
![](https://habrastorage.org/getpro/habr/upload_files/fcb/491/c68/fcb491c68bea3cd30defec3f9bd0e53b.png)
Мы добавили все необходимые для работы библиотеки, осталось создать директорию, куда мы поместим наше приложение. Создадим директорию apks и перетащим в неё наше приложение:
![](https://habrastorage.org/getpro/habr/upload_files/f46/f40/25d/f46f4025dbd053632038a82ea0145b91.png)
Разработка тестов
Теперь перейдём в директорию main — java и создадим наш первый класс, который назовём LoginTest, в нём мы и будем писать наши тесты:
![](https://habrastorage.org/getpro/habr/upload_files/1b7/9da/f42/1b79daf42d72130a4956f45a9da15423.png)
Для успешного запуска теста нам понадобятся методы setUp(), tearDown() и сам тест. Напишем метод setUp(), в котором пропишем все необходимые параметры для запуска, а именно:
platformName — версия ОС нашего эмулятора, в нашем случае это Android;
deviceName — имя эмулятора, которое отображается в Android Studio, в нашем случае это autoschool10 (название эмулятора может быть любым, но лучше не давать ему имя, написанное кириллицей);
platformVersion — это версия нашей ОС — Android 10;
automationName — автоматизируем с помощью Appium;
appPackage — пакет нашего приложения тестового com.example.login;
appActivity — та активити, то есть тот экран, который будет запускаться. В нашем приложении всего лишь один экран, и эта активность называется .ui.login.LoginActivity;
app — тут указываем полный путь до нашего приложения, в данном случае это "/Users/{имя_пользователя}/Desktop/androidAutomation/apks/login.apk".
В данной строке мы подключаем android driver (Appium Android Driver — инструмент автоматизации тестирования для устройств Android. Драйвер является частью инструмента автоматизации тестирования Appium mobile):
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
Система работает с помощью com.android.uiautomator.testrunner.UiAutomatorTestCase, размещённого на устройстве Android, который открывает SocketServer на порту 4723. Этот сервер получает команды, преобразует их в соответствующие команды Android UI Automator и запускает их на устройства.
Полный листинг кода представлен ниже:
public void setUp() throws Exception
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "autoschool10");
capabilities.setCapability("platformVersion", "10");
capabilities.setCapability("automationName", "Appium");
capabilities.setCapability("appPackage", "com.example.login");
capabilities.setCapability("appActivity", ".ui.login.LoginActivity");
capabilities.setCapability("app", "/Users/s.yakovlev/Desktop/androidAutomation/apks/login.apk");
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
Завершим работу драйвера в методе tearDown():
public void tearDown()
{
driver.quit();
}
Затем добавим аннотацию @before
— то, что выполняется перед тестом, @After
— то, что выполняется после теста, @Test
— добавляется у каждого теста.
![](https://habrastorage.org/getpro/habr/upload_files/842/195/c21/842195c21acd12bbc031ead4e9c904b0.png)
Всё, что нам остаётся, — это написать сами тесты. Мы напишем всего три теста. Первый будет проверять, что действительно у нас открылся экран Login. Второй будет проверять авторизацию с валидными данными, ну а третий, что логично, — авторизацию с невалидными данными.
Тест на проверку наличия Таббара
Напишем позитивный тест на проверку названия экрана. Мы объявим переменную, назовём её screenTitle, в которой сохраним наш элемент. Искать данный элемент мы будем по id, поэтому напишем findElementById. Чтобы убедиться, что элемент действительно есть, вызовем метод isDisplayed().
@Test
public void checkTitleScreen()
{
WebElement screenTitle = driver.findElementById("com.example.login:id/toolbar");
screenTitle.isDisplayed();
}
Тест на авторизацию с валидными данными
Перейдём к написанию теста на авторизацию с валидными данными. Последовательность действий будет ровно такой же. Задаём переменные emailInput и passInput, в которых сохраняем наши ранее найденные элементы.
Чтобы заполнить поле данными, по нему надо сначала произвести клик, для этого существует метод click(), а для заполнения данных мы будем использовать метод sendKeys(), в который уже и передаём те данные, которыми мы хотим заполнить наше поле.
@Test
public void validRegistrationTest()
{
WebElement emailInput = driver.findElementById("com.example.login:id/username");
emailInput.isDisplayed();
emailInput.click();
emailInput.sendKeys("admin@admin.ru");
WebElement passInput = driver.findElementById("com.example.login:id/password");
passInput.isDisplayed();
passInput.click();
passInput.sendKeys("1234");
WebElement signInButton = driver.findElementById("com.example.login:id/login");
signInButton.isDisplayed();
signInButton.click();
WebElement successAuthText = driver.findElementByXPath("//*[contains(@text, 'Welcome ! user')]");
successAuthText.isDisplayed();
}
Обратите внимание, что мы искали элементы по id, но текст “Welcome ! user” мы ищем по XPath. Это второй вариант поиска локаторов. XPath используется для навигации по элементам и атрибутам. Следующей конструкцией findElementByXPath("//[contains@textt, 'Welcome ! user')]"); мы ищем текст по наличию на всём экране. Методу contains() не требуется весь текст для правильной идентификации элемента, достаточно части текста, но важно, чтобы эта часть текста была уникальной.
![](https://habrastorage.org/getpro/habr/upload_files/584/02d/a07/58402da07a244272534230e2c5cfdbcc.png)
Тест на авторизацию с невалидными данными
Аналогичным образом напишем тест на авторизацию с невалидными данными:
@Test
public void validRegistrationTest()
{
WebElement emailInput = driver.findElementById("com.example.login:id/username");
emailInput.isDisplayed();
emailInput.click();
emailInput.sendKeys("user@user.ru");
WebElement passInput = driver.findElementById("com.example.login:id/password");
passInput.isDisplayed();
passInput.click();
passInput.sendKeys("1111");
WebElement signInButton = driver.findElementById("com.example.login:id/login");
signInButton.isDisplayed();
signInButton.click();
WebElement successAuthText = driver.findElementByXPath("//*[contains(@text, 'Login failed')]");
successAuthText.isDisplayed();
}
![](https://habrastorage.org/getpro/habr/upload_files/243/dcb/a85/243dcba85bfdabf1895465027d09a2df.png)
Наши тесты написаны и готовы к запуску. Для запуска всех тестов нажмём на зелёный треугольник около класса LoginTest:
![](https://habrastorage.org/getpro/habr/upload_files/bc3/020/a95/bc3020a95dbb63c38f5a8af64f102abb.png)
Важно: перед запуском убедитесь, что у вас запущен Appium Server GUI и запущен сам эмулятор.
Наши тесты запущены, и мы можем наблюдать на эмуляторе процесс прогона — поля заполняются данными; если тест проходит успешно, то он отмечается зелёной галочкой.
![](https://habrastorage.org/getpro/habr/upload_files/087/ec1/eb5/087ec1eb5776533653e9e14b623ea1d9.png)
После прогона мы можем посмотреть дефолтный отчёт. Он, конечно, не информативный, но всё равно мы можем увидеть, что наши тесты успешно пройдены.
![](https://habrastorage.org/getpro/habr/upload_files/f8b/5c1/e65/f8b5c1e65323e0c8de06e47732fa4b3b.png)
Вывод
Мы с вами рассмотрели, как пишутся тесты на языке Java на мобильное приложение под ОС Android. Конечно, данные тесты далеко не идеальны. На проектах обычно пишут целые фреймворки и используют паттерн PageObject. Но наша с вами задача была — написать свой первый тест, а начать можно и без паттерна PageObject.
AlexNecro
Здорово, что в современных системах разработки бизнес-приложений тестирование встроено в саму платформу. Я про 1С.