Quantcast
Channel: Статьи Intel Developer Zone
Viewing all articles
Browse latest Browse all 357

Автоматическое тестирование Android с UiAutomator

$
0
0

Я хочу рассказать вам о замечательном инструменте для автоматического тестирования пользовательского интерфейса в приложениях Android - UiAutomator. Вы можете найти всю актуальную документацию здесь:  http://developer.android.com/tools/help/uiautomator/index.htmlи http://developer.android.com/tools/testing/testing_ui.html

У UiAutomator есть свои плюсы и минусы.

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

  • Он может быть использован на дисплеях устройств с различным разрешением.
  • События можно привязывать к элементам управления Android UI. К примеру, кликайте на кнопку с текстом «Ок» вместо того, чтобы кликать по расположению координат (x=450, y=550).
  • Инструмент может воспроизводить сложную последовательность действий пользователя.
  • Он всегда выполняет одну и ту же последовательность действий, позволяя нам собирать данные о производительности на разных устройствах.
  • Он может многократно выполняться на различных устройствах без изменения Java-кода.
  • Может использовать аппаратные кнопки на устройствах.

Недостатки:

  • Его сложно использовать с OpenGL- и HTML5-приложениями, поскольку они не имеют компонентов Android UI.
  • Время, затрачиваемое на написание JavaScript.

Разработка скрипта

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

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

  1. Найти и запустить приложение
  2. Создать и отправить SMS-сообщения

Как видите, это очень просто.

Подготовка к тесту

Для анализа интерфейса будем использовать uiautomatorviewer.

Uiautomatorviewer показывает разделенный скриншот всех компонентов UI в Node Detail, чтобы вы могли видеть их разнообразные свойства. Там же в свойствах вы можете найти искомый элемент.

Настройка среды разработки

Если вы используете Eclipse*:

  1. Создайте новый Java-проект в Eclipse. Мы назовем наш проект: SendMessage.
  2. Клик правой кнопкой на вашем проекте в ProjectExplorerи затем клик на Properties.
  3. В Propertiesвыберите JavaBuildPath  и добавьте требуемые библиотеки:

 

Если вы пользуетесь иной средой разработки, убедитесь что файлы android.jar и uiautomator.jar добавлены в настройки проекта. 

Кликните AddLibrary JUnit  и там выберите JUnit3, чтобы добавить поддержку для JUnitКликните Add External JARs ...В <android-sdk>/platforms/directory выберите последнюю версию SDK. Также в этой директории выберите файлы uiautomator.jar и android.jar

Создание скрипта

Создайте проект в ранее созданном новом файле с классом Java. Назовите его SendMessage. Этот класс унаследован из класса UiAutomatorTestCase. Используя Ctrl + Shift + o (для Eclipse), добавьте требуемые библиотеки.

Создайте три функции для тестирования этого приложения:

  1. Найти и запустить приложение
  2. Отправить SMS-сообщения
  3. Выйти в главное меню приложения

Создайте функцию, от которой будут запускаться все эти опции, – своего рода основную функцию:

public void test() {
	// 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());
	}

Все наименования классов, текст на кнопках и пр. - из uiautomatorviewer.

Посылка SMS-сообщения

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

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();
	}

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

Чтобы добавить возможность передавать параметры в скрипт, мы можем точно определить число адресатов и сами сообщения. Функция 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, имя параметра и значение. К примеру, мое приложение отсылает номер для отправки " 777777 »:-e to 777777

Есть и некоторые подвохи. К примеру, данное приложение не понимает некоторые символы, и происходит сбой. Вот некоторые из этих символов: space, &, <, > , (,) , ", ' , а также некоторые символы Unicode. При внедрении в скрипт я заменил эти символы текстовой строкой, например пробел : blogspaceblog. Получается, когда скрипт запускает UiAutomator, мы используем скрипт, который будет обрабатывать наши входные параметры. Мы добавляем в функцию test(), проверку наличия опций, парсим параметры и заменяем их реальными символами. Ниже представлен образец кода, наглядно демонстрирующий всё, что мы ввели ранее:

if (toParam != null) {
			toParam = toParam.replace("blogspaceblog", "");
			toParam = toParam.replace("blogamperblog", "&");
			toParam = toParam.replace("bloglessblog", "<");
			toParam = toParam.replace("blogmoreblog", ">");
			toParam = toParam.replace("blogopenbktblog", "(");
			toParam = toParam.replace("blogclosebktblog", ")");
			toParam = toParam.replace("blogonequoteblog", "'");
			toParam = toParam.replace("blogtwicequoteblog", """);
			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();
		}
	}

Исходный код

Вот и наш код:

package blog.send.message;
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) {
			toParam = toParam.replace("blogspaceblog", "");
			toParam = toParam.replace("blogamperblog", "&");
			toParam = toParam.replace("bloglessblog", "<");
			toParam = toParam.replace("blogmoreblog", ">");
			toParam = toParam.replace("blogopenbktblog", "(");
			toParam = toParam.replace("blogclosebktblog", ")");
			toParam = toParam.replace("blogonequoteblog", "'");
			toParam = toParam.replace("blogtwicequoteblog", """);
			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();
		}
		findAndRunApp();
	    	sendMessage(toNumber, text);
	    	exitToMainWindow();
	}
	// 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);
		}
	}
}

Компиляция и выполнение тестирования UiAutomator

  1. Чтобы сгенерировать файлы конфигурации для экспериментальной сборки, выполните следующую команду из командной строки:
    <android-sdk>/tools/androidсоздать uitest-проект -n<name> -<target-id> -p<path>
    где <
    name>- это имя проекта, который был создан для тестирования UiAutomator (в нашем случае: SendMessage), <target-id>- выбор устройства и AndroidAPILevel (вы можете получить перечень установленных устройств с помощью команды <android-sdk> / tools / androidlisttargets), и <path> это путь к директории, где содержится проект.
  2. Вы должны экспортировать переменную среды ANDROID_HOME:
    • На Windows:
      установите ANDROID_HOME=<путь_к_вашему_sdk>
    • На UNIX:
      экспортируйте ANDROID_HOME=<путь_к_вашему_sdk>
  3. Откройте директорию с файлом проекта build.xml, который был создан на этапе 1, и выполните команду: antbuild
  4. Скопируйте скомпилированный файл JAR на устройство, используя adb push:
    adbpush<путь_к_output_jar> /data/local/tmp/
    В нашем случае это:

    adbpush<project_dir>/bin/SendMessage.jar /data/local/tmp/
  5. И выполните скрипт:
    adb shell uiautomator runtest /data/local/tmp/SendMessage.jar –c blog.send.message.SendMessage

Об авторе

Егор Чураев (egor.churaev@intel.com) – Стажер по программному обеспечению

Дополнительные материалы:


Viewing all articles
Browse latest Browse all 357

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>