- PVSM.RU - https://www.pvsm.ru -
Тестирование — это очень важный процесс во время разработки приложений. В случае Android, тестирование приложения следует производить на большом количестве устройств, в связи с тем, что многие из них имеют значительные различия по характеристикам (разрешение экрана, версия Android и т.д.). Процесс тестирования приложения вручную на большом количестве устройств может быть трудоемок, утомителен и подвержен ошибкам. Более эффективный и надежный подход состоит в автоматизации тестирования пользовательского интерфейса. С помощью UIAutomator можно разработать тест-скрипт, который будет работать на множестве Android устройств
с одинаковой точностью и воспроизводимостью.
UIAutomator разрабатывается корпорацией Google и поставляется вместе с Android SDK. UIAutomator – это аналог инструмента UIAutomation компании Apple для тестирования Android приложений. Android SDK предоставляет следующие инструменты для поддержки автоматизированного функционального тестирования пользовательского интерфейса:
Чтобы использовать эти инструменты, необходимо установить следующие компоненты среды Android:
UIAutomator постоянно дорабатывается, поэтому самую свежую документацию можно найти на сайте: http://developer.android.com/tools/help/UIAutomator/index.html [1].
Преимущества UIAutomator, для тестирования приложений:
Но есть и недостатки:
Тестирование приложения с помощью UIAutomator состоит из следующих шагов:
Для ознакомления с технологиями UIAutomator далее будет представлена простая програма, осуществляющая несложные действия с устройством. В качестве тестируемого приложения будет использовано стандартное Android приложение — Messaging, а UIAutomator будет отправлять SMS-сообщение на определенный номер.
Определим действия, которые будут реализованы в тесте:
Как видите, все достаточно просто.
Для анализа пользовательского интерфейса приложения будет использоваться UIAutomatorviewer. UIAutomatorviewer делает снимок экрана устройства, который подключен к компьютеру, а также предоставляет удобный графический интерфейс для отображения иерархии слоев и просмотра свойств каждого компонента интерфейса в отдельности. Наличие этой информации значительно упрощает процесс создания UIAutomator скрипта.
Для анализа пользовательского интерфейса необходимо:
$ UIAutomatorviewer
Если UIAutomatorviewer не может разложить изображение на компоненты, значит, приложение написано с использованием HTML 5 или OpenGL.
Если вы используете Eclipse:
При использовании другой среды разработки, убедитесь, что файлы UIAutomator.jar и android.jar добавлены в настройки проекта.
Чтобы рассказать обо всех возможностях, которыми обладает UIAutomator для создания тест-скриптов, потребуется достаточно большое количество времени. Всю подробную информцию можно найти на сайте: http://developer.android.com/tools/help/UIAutomator/index.html [1]
Для начала необходимо создать в проекте «SendMessage» новый файл с Java классом, например под именем SendMessage. Этот класс должен быть унаследован от класса UIAutomatorTestCase. Чтобы добавить библиотеку в Eclipse, достаточно воспользоваться сочетанием клавиш Ctrl+Shift+o. Аналогичным образом добавляются и другие библиотеки, поэтому не буду больше заострять на этом внимание.
Создадим три функции для тестирования основного функционала приложения:
Первая функция, запускающая все эти методы, своего рода main функция, будет выглядеть следующим образом:
public void test() {
// Here will be called for all other functions
}
Функция будет осуществлять следующие действия: нажать на кнопку Home, для перехода в главном окно, открыть меню и найти значок с нужным приложением, запустить это приложение.
private void findAndRunApp() throws UiObjectNotFoundException {
// Go to main screen
getUiDevice().pressHome();
// Find menu button
UiObject allAppsButton = new UiObject(new UiSelector()
.description("Apps"));
// Click on menu button and wait new window
allAppsButton.clickAndWaitForNewWindow();
// Find App tab
UiObject appsTab = new UiObject(new UiSelector()
.text("Apps"));
// Click on app tab
appsTab.click();
// Find scroll object (menu scroll)
UiScrollable appViews = new UiScrollable(new UiSelector()
.scrollable(true));
// Set the swiping mode to horizontal (the default is vertical)
appViews.setAsHorizontalList();
// Find Messaging application
UiObject settingsApp = appViews.getChildByText(new UiSelector()
.className("android.widget.TextView"), "Messaging");
// Open Messaging application
settingsApp.clickAndWaitForNewWindow();
// Validate that the package name is the expected one
UiObject settingsValidation = new UiObject(new UiSelector()
.packageName("com.android.mms"));
assertTrue("Unable to detect Messaging",
settingsValidation.exists());
}
Все названия классов, текста на кнопках и т.д. были получены с помощью UIAutomatorviewer.
В этой функции реализуем поиск и нажатие на кнопку создания нового сообщения, ввод номера телефона, текста сообщения и его последующая отправка. Номер и текст будут передаваться через аргументы функции:
private void sendMessage(String toNumber, String text) throws UiObjectNotFoundException {
// Find and click New message button
UiObject newMessageButton = new UiObject(new UiSelector()
.className("android.widget.TextView").description("New message"));
newMessageButton.clickAndWaitForNewWindow();
// Find to box and enter the number into it
UiObject toBox = new UiObject(new UiSelector()
.className("android.widget.MultiAutoCompleteTextView").instance(0));
toBox.setText(toNumber);
// Find text box and enter the message into it
UiObject textBox = new UiObject(new UiSelector()
.className("android.widget.EditText").instance(0));
textBox.setText(text);
// Find send button and send message
UiObject sendButton = new UiObject(new UiSelector()
.className("android.widget.ImageButton").description("Send"));
sendButton.click();
}
Поле для номера и поле для сообщения мы не смогли бы найти по каким-либо особым признакам, поскольку ни текста, ни какого-либо описания у этих форм нет. Поэтому находим их с помощью метода instance. Этим методом можно получить элемент по его порядковому номеру в иерархии интерфейса.
Реализуем возможность получения в качестве параметров номера телефона получателя, а также текст сообщения. В функцию test() необходимо добавить инициализацию параметров по умолчанию, которые в должны быть перезаписаны пользовательскими значениями, если они были переданы в качестве аргументов соответствующей функции:
// Default parameters
String toNumber = "123456";
String text = "Test message";
String toParam = getParams().getString("to");
String textParam = getParams().getString("text");
if (toParam != null) {
// Remove spaces
toNumber = toParam.trim();
}
if (textParam != null) {
text = textParam.trim();
}
Таким образом, можно передавать параметры через командную строчку в скрипт. Это можно делать с помощью ключа –e. После него передается 2 значения: имя параметра и значение. Например, для передачи номера «777777», в качестве номера получателя, передадим параметры: -e to 777777. Для получения этих параметров в скрипте используется метод: getParams().
Но тут есть и несколько подводных камней. Например, не получается передать текст с некоторыми символами, UIAutomator их не воспринимает (пробел, &, <, >, (, ), “, ’, и т.д., а так же юникодные символы). Для этого предлагаю делать замену этих символов при подаче их в скрипт какой-нибудь строкой, например, пробел заменим строкой: blogspaceblog. Это удобно, когда для запуска скрипта UIAutomator используем скрипт, который будет обрабатывать входные параметры. Добавим в проверку входных параметров парсинг и замену этих строк:
if (toParam != null) {
toNumber = toParam.trim();
}
if (textParam != null) {
textParam = textParam.replace("blogspaceblog", " ");
textParam = textParam.replace("blogamperblog", "&");
textParam = textParam.replace("bloglessblog", "<");
textParam = textParam.replace("blogmoreblog", ">");
textParam = textParam.replace("blogopenbktblog", "(");
textParam = textParam.replace("blogclosebktblog", ")");
textParam = textParam.replace("blogonequoteblog", "'");
textParam = textParam.replace("blogtwicequoteblog", """);
text = textParam.trim();
}
Эта функция самая простая из всех тех, которые мы реализовывали до этого. Она нажимает кнопку назад, до тех пор, пока не найдет кнопку для создания нового сообщения.
private void exitToMainWindow() {
// Find New message button
UiObject newMessageButton = new UiObject(new UiSelector()
.className("android.widget.TextView").description("New message"));
// Press back button while new message button doesn't exist
while(!newMessageButton.exists()) {
getUiDevice().pressBack();
}
}
Для того, чтобы логировать результаты теста, можно использовать стандартный буффер Android. Для работы с ним необходимо подключить библиотеку в скрипте:
import android.util.Log;
Всю информацию, которая интересна можно записывать в логи. Это можно делать с помощью функции:
Log.i(String title, String title);
Логи можно читать с устройства с помощью команды:
$ adb logcat
Более подробную информацию по logcat можно найти на официальном сайте: developer.android.com/tools/help/logcat.html [2]
Таким образом, у нас получился такой код:
package blog.send.message;
import android.util.Log;
import com.android.UIAutomator.core.UiObject;
import com.android.UIAutomator.core.UiObjectNotFoundException;
import com.android.UIAutomator.core.UiScrollable;
import com.android.UIAutomator.core.UiSelector;
import com.android.UIAutomator.testrunner.UIAutomatorTestCase;
public class SendMessage extends UIAutomatorTestCase {
public void test() throws UiObjectNotFoundException {
// Default parameters
String toNumber = "123456";
String text = "Test message";
String toParam = getParams().getString("to");
String textParam = getParams().getString("text");
if (toParam != null) {
toNumber = toParam.trim();
}
if (textParam != null) {
textParam = textParam.replace("blogspaceblog", " ");
textParam = textParam.replace("blogamperblog", "&");
textParam = textParam.replace("bloglessblog", "<");
textParam = textParam.replace("blogmoreblog", ">");
textParam = textParam.replace("blogopenbktblog", "(");
textParam = textParam.replace("blogclosebktblog", ")");
textParam = textParam.replace("blogonequoteblog", "'");
textParam = textParam.replace("blogtwicequoteblog", """);
text = textParam.trim();
}
Log.i("SendMessageTest", "Start SendMessage");
findAndRunApp();
sendMessage(toNumber, text);
exitToMainWindow();
Log.i("SendMessageTest", "End SendMessage");
}
// Here will be called for all other functions
private void findAndRunApp() throws UiObjectNotFoundException {
// Go to main screen
getUiDevice().pressHome();
// Find menu button
UiObject allAppsButton = new UiObject(new UiSelector()
.description("Apps"));
// Click on menu button and wait new window
allAppsButton.clickAndWaitForNewWindow();
// Find App tab
UiObject appsTab = new UiObject(new UiSelector()
.text("Apps"));
// Click on app tab
appsTab.click();
// Find scroll object (menu scroll)
UiScrollable appViews = new UiScrollable(new UiSelector()
.scrollable(true));
// Set the swiping mode to horizontal (the default is vertical)
appViews.setAsHorizontalList();
// Find Messaging application
UiObject settingsApp = appViews.getChildByText(new UiSelector()
.className("android.widget.TextView"), "Messaging");
// Open Messaging application
settingsApp.clickAndWaitForNewWindow();
// Validate that the package name is the expected one
UiObject settingsValidation = new UiObject(new UiSelector()
.packageName("com.android.mms"));
assertTrue("Unable to detect Messaging",
settingsValidation.exists());
}
private void sendMessage(String toNumber, String text) throws UiObjectNotFoundException {
// Find and click New message button
UiObject newMessageButton = new UiObject(new UiSelector()
.className("android.widget.TextView").description("New message"));
newMessageButton.clickAndWaitForNewWindow();
// Find to box and enter the number into it
UiObject toBox = new UiObject(new UiSelector()
.className("android.widget.MultiAutoCompleteTextView").instance(0));
toBox.setText(toNumber);
// Find text box and enter the message into it
UiObject textBox = new UiObject(new UiSelector()
.className("android.widget.EditText").instance(0));
textBox.setText(text);
// Find send button and send message
UiObject sendButton = new UiObject(new UiSelector()
.className("android.widget.ImageButton").description("Send"));
sendButton.click();
}
private void exitToMainWindow() {
// Find New message button
UiObject newMessageButton = new UiObject(new UiSelector()
.className("android.widget.TextView").description("New message"));
// Press back button while new message button doesn't exist
while(!newMessageButton.exists()) {
getUiDevice().pressBack();
sleep(500);
}
}
}
$ <android-sdk>/tools/android create uitest-project -n <name> -t <target-id> -p <path>
Где <name>
— имя проекта, который создавался для теста UIAutomator (в нашем случае: SendMessage), <target-id> — выбор устройства и Android API Level (можно получить список установленных устройств командой: <android-sdk>/tools/android list targets) и <path>
— путь к директории с проектом.
set ANDROID_HOME=<path_to_your_sdk>
export ANDROID_HOME=<path_to_your_sdk>
$ ant build
$ adb push <path_to_output_jar> /data/local/tmp/
Для нашего случая:
$ adb push <project_dir>/bin/SendMessage.jar /data/local/tmp/
$ adb shell UIAutomator runtest /data/local/tmp/SendMessage.jar –c blog.send.message.SendMessage -e to 777777
Использование UIAutomator очень удобно для качественного тестирования приложений на большом количестве девайсов. С помощью этой технологии можно создавать различные Demo для демонстрации приложения.
Автор: echuraev
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/news/50916
Ссылки в тексте:
[1] http://developer.android.com/tools/help/UIAutomator/index.html: http://developer.android.com/tools/help/UIAutomator/index.html
[2] developer.android.com/tools/help/logcat.html: http://developer.android.com/tools/help/logcat.html
[3] Источник: http://habrahabr.ru/post/205864/
Нажмите здесь для печати.