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

Тестирование является важной частью процесса разработки приложений. Для Android оно имеет особенную важность, поскольку используемые устройства довольно сильно отличаются друг от друга по следующим параметрам:

  • Размер и разрешение экрана
  • Версия Android
  • Типоразмер устройства
  • Набор инструкций процессора
  • Наличие передней камеры, поддержка NFC, внешняя клавиатура и пр.

Приложения для Android следует тестировать на множестве устройств.

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

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

В этой статье рассматривается несколько средств для автоматического тестирования функциональности. При этом речь идет только о средствах, входящих в состав Android SDK или распространяющихся с открытым исходным кодом.

Принцип автоматического тестирования

Наша задача — с наибольшей точностью автоматизировать действия, выполняемые вручную. Рассмотрим эти действия. Будем использовать несколько приложений и несколько устройств с Android.

Для каждого приложения и каждого устройства нужно выполнить следующие действия:

  1. Установить приложение на устройство
  2. Запустить приложение
  3. Протестировать приложение, используя выбранный метод
  4. Удалить приложение
  5. Сбросить устройство в исходное состояние

На каждом этапе нужно собирать и анализировать данные (журналы и снимки экрана). Ниже описываются средства для автоматизации этих действий.

Управление устройствами Android

Прежде всего необходимо выбрать компьютер, который будет использоваться для запуска автоматических тестов, и установить на нем Android SDK. В данном примере я использую настольный компьютер с операционной системой Linux*. На каждом устройстве необходимо отключить экран блокировки и увеличить «время перед переходом в спящий режим» до максимального значения. Для некоторых методик тестирования также нужно отключить изменение ориентации экрана.

В составе Android SDK предусмотрено две программы для управления устройствами с Android: ADB и monkeyrunner*. Сейчас мы подробно рассмотрим автоматизацию действий, применяемых при тестировании вручную.

Управление устройствами Android с помощью ADB

ADB (Android Debug Bridge) — это программа командной строки для управления устройствами с Android. Домашняя страница ADB: http://developer.android.com/tools/help/adb.html

Программа ADB находится в папке <android_sdk>/platform-tools/. Следует указать эту папку в переменной среды PATH.

Проверка установки ADB

Установите и настройте Android SDK, затем подключите к компьютеру устройства с Android и выполните команду:

adb devices

По этой команде будет показан список всех подключенных устройств с Android. Если список устройств не пуст, то ADB исправно работает.

Работа с несколькими устройствами

Чтобы выбрать устройство, с которым должна работать программа ADB, используйте параметр «-s».

adb -s [серийный_номер] [команда]

Например:

adb -s [серийный_номер] logcat

Серийный номер устройства можно получить в выходных данных команды «adb devices». Параметр -s позволяет работать одновременно с несколькими подключенными устройствами.

Основные команды ADB

 

Открыть консоль на устройстве:

adb shell

Выполнить команду на устройстве:

adb shell [команда]

В состав Android входит множество стандартных команд Linux: ls, cat, dmesg, ...

Установить приложение из APK-файла:

adb install example.apk

Удалить приложение:

adb uninstall [пакет]

Получить имя пакета из APK-файла:

aapt dump badging example.apk | grep "пакет"

Загрузить файл с устройства на компьютер:

adb pull [путь на устройстве] [файл]

Отправить файл с компьютера на устройство:

adb push [файл] [путь на устройстве]

 

Примечание:

К большинству папок на устройстве с Android возможен доступ только для чтения. Доступ на запись доступен только к папкам /sdcard (но из этой папки невозможно запускать программы) и /data/local/tmp.

Запустить приложение:

adb shell am start -n [пакет]/[действие]

Запустить определенное действие.

Имя действия можно извлечь из APK-файла:

aapt dump badging example.apk | grep "запускаемое_действие"

 

Чтение журалов

Logcat — это средство командной строки для чтения журналов с устройств Android.

Домашняя страница Logcat: http://developer.android.com/tools/help/logcat.html

Читать журналы с устройства (блокировка до нажатия клавиш Ctrl-C):

adb logcat

Очистить буфер журнала на устройстве:

adb logcat -c

Записать буфер журнала на устройстве (отображение текущего содержимого буфера, без блокировки):

adb logcat -d

Пример:

adb logcat -c # clear the buffer log
# Action
adb logcat -d > file.log # save the current contents of the log buffer to file.log

 

Получение снимков экрана с помощью screencap

Программа screencap сохраняет снимок текущего экрана в графический файл:

adb shell screencap /sdcard/screen.png
adb pull /sdcard/screen.png screen.png
adb shell rm /sdcard /screen.png

Программа screencap доступна на смартфонах с Android 4.x и более поздними версиями. На более ранних версиях Android можно получать снимки экрана с помощью monkeyrunner.

Скрипт BASH для тестирования приложения с помощью ADB

Скрипт: app_test.sh

Управление устройствами Android с помощью MonkeyRunner

Программа monkeyrunner предоставляет интерфейсы API для скриптов, управляющих устройствами Android. Можно написать скрипт Python*, устанавливающий приложение Android, запускающий его, получающий снимки экрана и сохраняющий их на компьютере. Для запуска скриптов Monkeyrunner использует Jython*.

Домашняя страница monkeyrunner и справочник по API: http://developer.android.com/tools/help/monkeyrunner_concepts.html

Чтение журналов с помощью monkeyrunner

Файл log.py:

# coding: utf-8
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

def log(fn, device):
    msg = device.shell('logcat -d')
    f_log = open(fn, 'at')
    if msg is None:
        msg = 'None'
    f_log.write(msg.encode('utf-8'))
    f_log.close()    
    device.shell('logcat -c')

if __name__ == '__main__':
    device = MonkeyRunner.waitForConnection()
    device.shell('logcat -c') # Clear logs buffer
    # ...
    log('example.log', device) # Write logs

Запуск:

monkeyrunner log.py

Сценарий будет записывать данные журнала в файл example.log в текущей папке.

Получение снимков экрана с помощью MonkeyRunner

Файл screen.py:

# coding: utf-8
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

if __name__ == '__main__':
    device = MonkeyRunner.waitForConnection()
    image = device.takeSnapshot()
    image.writeToFile('screenshot.png','png')

Запуск:

monkeyrunner screen.py

Сценарий делает снимок экрана и сохраняет его в файл screenshot.png в текущей папке.

Пример управления устройством с помощью monkeyrunner

Скрипт: monkeyrunner_test.py

Запуск:

monkeyrunner monkeyrunner_test.py

Методы автоматического тестирования

Тестирование с помощью Monkey*

Предположим, что тестируемое устройство попало в лапы крайне любопытной и деятельной обезьяны: программа Monkey имитирует именно такую ситуацию. Программа Monkey, входящая в состав Android SDK, отправляет поток случайных действий пользователя. В командной строке можно указать количество действий пользователя, долю действий каждого типа и имя пакета (чтобы программа Monkey не вышла за пределы тестируемого приложения и не начала, к примеру, рассылать SMS-сообщения всем контактам из адресной книги).

Примеры и список параметров приведены на домашней странице Monkey: http://developer.android.com/tools/help/monkey.html

Основным преимуществом программы Monkey является отсутствие каких бы то ни было затрат на обслуживание. Кроме того, нагрузочное тестирование может выявлять сложные и малозаметные ошибки.

Недостатки тестирования с помощью Monkey:

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

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

Тестирование с помощью MonkeyRunner

MonkeyRunner позволяет не только создавать сценарии для управления устройствами с Android, но и создавать сценарии для тестирования приложения на определенном устройстве.

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

  • Гибкость.

Недостатки:

  • Сложность написания скриптов, даже в простых случаях.

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

Тестирование с помощью getevent и sendevent

Программы getevent и sendevent позволяют пользователю записывать последовательность действий и затем воспроизводить ее. Для запуска этих программ не требуются права доступа root.

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

  • Последовательности событий можно записать без дополнительных затрат в ходе ручного тестирования, если оно проводится.
  • Для записи последовательности событий не требуются навыки программирования.

Недостатки:

  •  
  • Последовательности необходимо записывать отдельно для каждого приложения и для каждого устройства. При изменении интерфейса приложение потребуется переделать все записанные действия.
  • Этот метод не проверяет состояние приложения во время тестирования. Если отклик приложения задерживается (например, из-за длительной загрузки веб-страницы), то результаты тестирования будут неверными.
  • Воспроизведение быстрых и сложных последовательностей занимает больше времени, чем их запись. Поэтому такой метод не всегда подходит для тестирования динамических игр, где важно быстрое реагирование.

Запись последовательности событий:

# Record event sequence
# Do actions on the device, press Ctrl-C to finish
adb shell getevent -t > events.txt
# Convert event sequence to script
./decode_events.py events.txt > events.sh
# Load the script to the device
adb push events.sh /data/local/tmp/
# Set the permissions
adb shell chmod 755 /data/local/tmp/events.sh
# Run script
adb shell sh /data/local/tmp/events.sh

Скрипт: decode_events.py

Тестирование с помощью Robotium*

Robotium не входит в состав Android SDK, эта программа распространяется с открытым исходным кодом. Домашняя страница Robotium: http://code.google.com/p/robotium/.

Сценарии Robotium определяют действия на уровне пользовательского интерфейса приложений, а не на уровне устройства ввода.

Например, в сценарии требуется коснуться кнопки «ОК». В этом случае скрипт monkeyrunner будет построен следующим образом: «имитировать касание экрана в точке с координатами (x0, y0)». Скрипт Robotium будет построен иначе: «нажать кнопку с текстом «ОК».

Описание действий на уровне интерфейса позволяет сделать тестовый скрипт независимым от расположения и размеров элементов интерфейса, разрешения и ориентации экрана.

Кроме того, в Robotium можно проверять реакцию приложения на действия. Например, предположим, что после нажатия кнопки «ОК» должен появиться список с элементом «Элемент 1». В Robotium можно проверять имена элементов списков. Проверка состояния приложения после каждого шага позволяет с легкостью находить шаг, на котором произошла ошибка.

Недостатки:

  •  
  • Для каждого приложения требуется разрабатывать тестовый сценарий на языке Java*. Для этого требуется время и навыки программирования.
  • При смене интерфейса приложения потребуется переделать последовательность событий.
  • Созавать сценарии Robotium сложнее, чем записывать события с помощью getevent / sendevent.

В целом, Robotium позволяет создавать тестовые сценарии высшего качества с разумными затратами.

Сравнение методов тестирования

Метод тестирования Преимущества Недостатки

Monkey — поток случайных действий пользователей

Затраты на обслуживание отсутствуют.

Независимость от устройства.

Нагрузочное тестирование может выявлять сложные и малозаметные ошибки.

Качество тестирования может различаться для разных приложений.

Сложно воспроизводить последовательность действий, вызвавших ошибку, в отчетах об ошибках.

Monkey не проверяет состояние приложения во время тестирования.

MonkeyRunner — скрипт для управления устройством

Гибкость

Сложность написания сценариев, даже для простых приложений.

Getevent/sendevent — запись и воспроизведение действий пользователя

Для записи последовательности событий не требуются навыки программирования.

Записанная последовательность действий подойдет только для одного устройства при фиксированной ориентации экрана.

При смене интерфейса приложения необходимо переделывать последовательность событий.

Этот метод не проверяет состояние приложения во время тестирования.

Robotium — API тестовых скриптов для проверки состояния

Действия описываются на уровне пользовательского интерфейса приложения.

Скрипт может не зависеть от разрешения и ориентации экрана.

Скрипт может проверять состояние приложения после действий.

Сложность написания сценариев на языке Java.

При изменении интерфейса приложения необходимо переделывать скрипт.

Анализ результатов

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

Анализ журнала

Можно выполнить поиск строк:

  • I/DEBUG
  • FATAL EXCEPTION
  • WIN DEATH

TВ этот список можно добавить сообщения об ошибках, обнаруженные при тестировании вручную.

Анализ снимков экрана

Можно подготовить набор снимков экрана в основные моменты тестирования и сравнивать их с содержимым экрана при автоматическом тестировании. Это позволит определить, правильно ли проходит автоматическое тестирование.

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

Monkeyrunner позволяет сравнивать два снимка экрана с определенным допустимым расхождением (в процентах):

image1 = device.takeSnapshot()
# ...
image2 = device.takeSnapshot()
if image2.sameAs(image1, 0.1):
    print 'image1 and image2 are the same (10%)'

К сожалению, не существует API MonkeyImage для загрузки изображения из файла. Можно самостоятельно написать функцию для сравнения изображений с помощью, например, Python* Imaging Library.

Сброс устройства в исходное состояние

После тестирования необходимо сбросить устройства в исходное состояние. Это можно сделать несколькими способами:

  • Нажать кнопку «Назад» несколько раз.
  • Перезагрузить устройство.
  • Перезапустить процесс-оболочку.

Первый вариант обычно является наиболее целесообразным.

Многократное нажатие кнопки «Назад»

Нажатие кнопки «Назад» с помощью monkeyrunner:

for i in xrange(0, 10):
    device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
    time.sleep(0.5)

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

Заключение

В этой статье мы обсудили некоторые методы автоматического тестирования приложений Android. Мы рассмотрели преимущества и недостатки методов автоматического тестирования.

Также рассказано о средствах Monkey и monkeyrunner, входящих в состав Android SDK, и о программе Robotium.

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