Как вы тестируете приложение для Android в нескольких видах деятельности? - PullRequest
79 голосов
/ 19 ноября 2009

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

Поскольку у нас так много рабочих процессов, нам необходимо создать автоматические тесты, которые охватывают несколько действий, чтобы мы могли тестировать рабочий процесс от начала до конца. Например, используя пример банкомата, мы хотели бы ввести действительный PIN-код, проверить, что отправляет нас в главное меню, выбрать снятие наличных, убедиться, что мы находимся на экране снятия наличных и т. Д., И т. Д., И в конечном итоге окажемся вернуться в главное меню или «выйти».

Мы поиграли с тестовыми API, которые поставляются с Android (например, ActivityInstrumentationTestCase2), а также с Positron , но ни один из них не способен к тестированию за пределами одного Activity, и хотя в этих инструментах мы можем найти некоторую полезность для некоторых модульных тестов, они не будут соответствовать нашим потребностям в сценариях тестирования, которые охватывают несколько видов деятельности.

Мы открыты для платформы xUnit, создания сценариев, записи / воспроизведения графического интерфейса пользователя и т. Д. И будем благодарны за любые советы.

Ответы [ 14 ]

65 голосов
/ 28 ноября 2009

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

Я искал все это, но не могу поверить, что нигде не опубликовано ни одного ответа. Я подошел очень близко. Я определенно могу запускать тесты, которые охватывают действия сейчас, но моя реализация, похоже, имеет некоторые временные проблемы, когда тесты не всегда проходят надежно. Это единственный известный мне пример того, как успешно проходят испытания по нескольким действиям. Надеюсь, мое извлечение и анонимизация не привели к ошибкам. Это упрощенный тест, в котором я ввожу имя пользователя и пароль в действие входа в систему, а затем наблюдаю, как на другом «приветствии» отображается правильное приветственное сообщение:

package com.mycompany;

import android.app.*;
import android.content.*;
import android.test.*;
import android.test.suitebuilder.annotation.*;
import android.util.*;
import android.view.*;
import android.widget.*;

import static org.hamcrest.core.Is.*;
import static org.hamcrest.core.IsNull.*;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.*;
import static com.mycompany.R.id.*;

public class LoginTests extends InstrumentationTestCase {

   @MediumTest
   public void testAValidUserCanLogIn() {

      Instrumentation instrumentation = getInstrumentation();

      // Register we are interested in the authentication activiry...
      Instrumentation.ActivityMonitor monitor = instrumentation.addMonitor(AuthenticateActivity.class.getName(), null, false);

      // Start the authentication activity as the first activity...
      Intent intent = new Intent(Intent.ACTION_MAIN);
      intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      intent.setClassName(instrumentation.getTargetContext(), AuthenticateActivity.class.getName());
      instrumentation.startActivitySync(intent);

      // Wait for it to start...
      Activity currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Type into the username field...
      View currentView = currentActivity.findViewById(username_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyUsername");

      // Type into the password field...
      currentView = currentActivity.findViewById(password_field);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(EditText.class));
      TouchUtils.clickView(this, currentView);
      instrumentation.sendStringSync("MyPassword");

      // Register we are interested in the welcome activity...
      // this has to be done before we do something that will send us to that
      // activity...
      instrumentation.removeMonitor(monitor);
      monitor = instrumentation.addMonitor(WelcomeActivity.class.getName(), null, false);

      // Click the login button...
      currentView = currentActivity.findViewById(login_button;
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(Button.class));
      TouchUtils.clickView(this, currentView);

      // Wait for the welcome page to start...
      currentActivity = getInstrumentation().waitForMonitorWithTimeout(monitor, 5);
      assertThat(currentActivity, is(notNullValue()));

      // Make sure we are logged in...
      currentView = currentActivity.findViewById(welcome_message);
      assertThat(currentView, is(notNullValue()));
      assertThat(currentView, instanceOf(TextView.class));
      assertThat(((TextView)currentView).getText().toString(), is("Welcome, MyUsername!"));
   }
}

Этот код явно не очень читабелен. На самом деле я извлек ее в простую библиотеку с английским API, так что я могу просто сказать что-то вроде этого:

type("myUsername").intoThe(username_field);
click(login_button);

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

22 голосов
/ 27 января 2010

Взгляните на Robotium
'среда тестирования с открытым исходным кодом, созданная для того, чтобы сделать автоматическое тестирование приложений Android «черным ящиком» значительно быстрее и проще, чем то, что возможно при тестировании инструментария Android «из коробки».

Домашняя страница: http://www.robotium.org/
Источник: http://github.com/jayway/robotium

Обратите внимание, что проект Robotium поддерживается компанией, для которой я работаю

8 голосов
/ 21 января 2010

Вы всегда можете использовать Robotium. Он поддерживает тестирование черного ящика, как и Selenium, но для Android. Вы найдете его на Robotium.org

4 голосов
/ 28 января 2013

Я удивлен, что никто не упомянул некоторые из ведущих инструментов автоматического функционального тестирования . По сравнению с Robotium, они не требуют написания кода Java.

MonkeyTalk : инструмент с открытым исходным кодом, поддерживаемый компанией Gorilla Logic. Плюсы: обеспечивает запись, а также язык сценариев более высокого уровня, более простой для нетехнических пользователей, и является кросс-платформенным (включая iOS). Учитывая эти преимущества как требования, мы сочли это лучшим решением. Это также позволяет настроить сверх того, что можно сделать на их языке сценариев с использованием Javascript.

Calabash-Android : инструмент с открытым исходным кодом для функций в стиле огурца. Плюсы: напишите функции на языке Gherkin, который является бизнес-читабельным, предметно-ориентированным языком, который позволяет описывать поведение программного обеспечения без подробного описания его реализации. Аналогичная, но не точная поддержка доступна для iOS в cucumber-ios . Возможности записи не так хороши, поскольку они дают двоичный вывод.

Пара других ссылок:

3 голосов
/ 12 июля 2012

Нашел это полезным с парой модификаций. Во-первых, getInstrumentation().waitForIdleSync() вылечит слабость, о которой говорит SingleShot а также InstrumentationTestCase имеет функцию lauchActivity, которая может заменить начальные строки активности.

3 голосов
/ 01 июня 2012

Прежде всего, используйте «ActivityInstrumentationTestCase2», а не «InstrumentationTestCase», в качестве базового класса. Я использую Robotium и регулярно тестирую несколько видов деятельности. Я обнаружил, что должен указать активность входа в систему как общий тип (и аргумент класса для конструктора).

Конструктор ActivityInstrumentationTestCase2 игнорирует аргумент пакета и не требует его. Конструктор, принимающий пакет, устарел.

Из Javadocs: "ActivityInstrumentationTestCase2 (String pkg, Class activityClass) Этот конструктор устарел. используйте ActivityInstrumentationTestCase2 (Class) вместо "

Использование рекомендованного базового класса позволяет платформе обрабатывать определенные шаблоны, такие как начало вашей деятельности. Это делается с помощью вызова getActivity (), если необходимо.

3 голосов
/ 18 августа 2011

Я создал инструмент записи и воспроизведения для Android и сделал его доступным на GitHub . Он прост в настройке и использовании, не требует программирования, работает с реальными устройствами (которые не нужно рутировать) и автоматически сохраняет скриншоты при воспроизведении тестов.

2 голосов
/ 25 ноября 2012

Вы можете сделать это следующим образом, чтобы избежать несинхронного ожидания ожидания:

final Button btnLogin = (Button) getActivity().findViewById(R.id.button);
Instrumentation instrumentation = getInstrumentation();

// Register we are interested in the authentication activity...
Instrumentation.ActivityMonitor aMonitor = 
        instrumentation.addMonitor(mynextActivity.class.getName(), null, false);

getInstrumentation().runOnMainSync(new Runnable() {
         public void run() {
             btnLogin.performClick();
         }
     });

getInstrumentation().waitForIdleSync();

//check if we got at least one hit on the new activity
assertTrue(getInstrumentation().checkMonitorHit(aMonitor, 1)); 
1 голос
/ 22 ноября 2011

Я работаю над тем же самым, и я, вероятно, пойду с вариацией принятого ответа на этот вопрос, но я встречал Расчет ( gitHub ) во время моих поисков решения.

0 голосов
/ 20 мая 2015

Попробуйте тестирование инструмента Обезьяна

Шаг 1:

открыть андроид студийный терминал (Инструменты-> открыть терминал)

Шаг 2:

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

 export PATH=$PATH:/home/adt-bundle-linux-x86-20140702/sdk/platform-tools

Шаг 3:

добавьте эту команду обезьяны в терминал и нажмите enter ..

увидеть магию в вашем эмуляторе.

adb shell monkey -p com.example.yourpackage -v 500

500 - это счетчик частоты или количество событий, отправляемых на тестирование.

Вы можете изменить это количество ..

Дополнительная справка,

http://www.tutorialspoint.com/android/android_testing.htm

http://androidtesting.blogspot.in/2012/04/android-testing-with-monkey-tool.html

...