Поиск…


замечания

Эспрессо

Шрифт Espresso поможет вам написать ваши тесты и то, что вы хотите проверить:

https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/

Также всегда хорошим местом для справки является официальная документация:

https://google.github.io/android-testing-support-library/docs/espresso/index.html

Расширенные предложения для эспрессо-видео от Google: https://www.youtube.com/watch?v=isihPOY2vS4

Поиск проблемы

  • При попытке прокрутки сначала закройте клавиатуру:

Watchout: не использование версии «Espresso» не будет делать ничего, если используется вне ViewAction. Это может быть не очевидно, если у вас есть импорт в версии ViewAction, поскольку у них есть точно такое же имя метода.

ViewActions.closeSoftKeyboard;
Espresso.closeSoftKeyboard();
  • При выполнении тестов вместе в наборе, а не отдельно, имейте в виду, что активность из предыдущего теста все еще может выполняться. Не полагайтесь на предыдущий тест onDestroy (), который вызывается перед текущими тестами onResume (). Оказывается, это на самом деле ошибка : http://b.android.com/201513

Настройка эспрессо

В файле build.gradle вашего Android-приложения добавьте следующие зависимости:

dependencies {   
    // Android JUnit Runner     
    androidTestCompile 'com.android.support.test:runner:0.5'
    // JUnit4 Rules
    androidTestCompile 'com.android.support.test:rules:0.5'
    // Espresso core
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
    // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
    androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
    //UI Automator tests
    androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.2.2'
}

Укажите AndroidJUnitRunner для testInstrumentationRunner параметра в build.gradle файле.

android {

  defaultConfig {
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }

}

Кроме того, добавьте эту зависимость для обеспечения намеренной насмешливой поддержки

androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'

И добавьте это для поддержки тестирования веб-просмотра

// Espresso-web for WebView support
androidTestCompile 'com.android.support.test.espresso:espresso-web:2.2.2'

Создать тестовый класс Espresso

Поместите следующий java-класс в src / androidTest / java и запустите его.

public class UITest {

  @Test public void Simple_Test() {
    onView(withId(R.id.my_view))         // withId(R.id.my_view) is a ViewMatcher
        .perform(click())                // click() is a ViewAction
        .check(matches(isDisplayed()));  // matches(isDisplayed()) is a ViewAssertion
  }

}

Развернуть Свернуть DrawerLayout

public final class DrawerLayoutTest  {

  @Test public void Open_Close_Drawer_Layout() {
    onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer());
    onView(withId(R.id.drawer_layout)).perform(actionCloseDrawer());
  }

  public static ViewAction actionOpenDrawer() {
    return new ViewAction() {
      @Override public Matcher<View> getConstraints() {
        return isAssignableFrom(DrawerLayout.class);
      }

      @Override public String getDescription() {
        return "open drawer";
      }

      @Override public void perform(UiController uiController, View view) {
        ((DrawerLayout) view).openDrawer(GravityCompat.START);
      }
    };
  }

  public static ViewAction actionCloseDrawer() {
    return new ViewAction() {
      @Override public Matcher<View> getConstraints() {
        return isAssignableFrom(DrawerLayout.class);
      }

      @Override public String getDescription() {
        return "close drawer";
      }

      @Override public void perform(UiController uiController, View view) {
        ((DrawerLayout) view).closeDrawer(GravityCompat.START);
      }
    };
  }
  
}

Эспрессо простой тест пользовательского интерфейса

Инструменты тестирования UI

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

Appium Эспрессо
тест черного ящика тестирование белого / серого ящика
то, что вы видите, это то, что вы можете проверить может изменить внутреннюю работу приложения и подготовить его для тестирования, например, сохранить некоторые данные в базе данных или sharedpreferences перед запуском теста
используемые в основном для интеграции тестов конца и конца и целых потоков пользователей тестирование функциональности экрана и / или потока
может быть абстрагирован, так что тестовое исполнение может быть выполнено на iOS и Android Только Android
хорошо поддерживается хорошо поддерживается
поддерживает параллельное тестирование на нескольких устройствах с селеновой сеткой Не из параллельного тестирования, плагины, такие как Spoon, существуют до тех пор, пока не появится истинная поддержка Google

Как добавить эспрессо в проект

dependencies {
  // Set this dependency so you can use Android JUnit Runner
  androidTestCompile 'com.android.support.test:runner:0.5'
  // Set this dependency to use JUnit 4 rules
  androidTestCompile 'com.android.support.test:rules:0.5'
  // Set this dependency to build and run Espresso tests
  androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
  // Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.2.2'
}

ПРИМЕЧАНИЕ. Если вы используете последние библиотеки поддержки, аннотации и т. Д., Вы должны исключить старые версии из эспрессо, чтобы избежать коллизий:

    // there is a conflict with the test support library (see http://stackoverflow.com/questions/29857695)
    // so for now re exclude the support-annotations dependency from here to avoid clashes
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    // exclude a couple of more modules here because of <http://stackoverflow.com/questions/29216327> and
    // more specifically of <https://code.google.com/p/android-test-kit/issues/detail?id=139>
    // otherwise you'll receive weird crashes on devices and dex exceptions on emulators
    // Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
    androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude group: 'com.android.support', module: 'design'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    //excluded specific packages due to https://code.google.com/p/android/issues/detail?id=183454
    androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

    androidTestCompile('com.android.support.test.espresso:espresso-web:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

    androidTestCompile('com.android.support.test:runner:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }
    androidTestCompile('com.android.support.test:rules:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude module: 'support-annotations'
        exclude module: 'recyclerview-v7'
        exclude module: 'support-v4'
        exclude module: 'support-v7'
    }

Помимо этого импорта необходимо добавить контрольный бегун для андроидов для сборки.gradle android.defaultConfig:

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

Настройка устройства

Для не-flaky-теста рекомендуется установить следующие настройки на ваших устройствах:

  • Параметры разработчика / Отключить анимацию - уменьшает шелушение тестов
  • Возможности разработчика / Будьте бодрым - если у вас есть специализированные устройства для тестов, это полезно
  • Параметры разработчика / размеры буфера регистратора - установите более высокий номер, если на вашем телефоне запущены очень большие тестовые пакеты
  • Доступность / Touch & Hold delay - долго, чтобы избежать проблем с нажатием на эспрессо

Достаточно установка из реального мира? Ну, теперь, когда это с пути, давайте посмотрим, как настроить небольшой тест

Написание теста

Предположим, что у нас есть следующий экран: Мягкий экран для теста эспрессо Экран содержит:

  • текстовое поле ввода - R.id.textEntry
  • кнопка, которая показывает закуску с напечатанным текстом при нажатии - R.id.shownSnackbarBtn
  • snackbar, который должен содержать пользовательский текст - android.support.design.R.id.snackbar_text

Теперь давайте создадим класс, который будет проверять наш поток:

/**
* Testing of the snackbar activity.
**/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SnackbarActivityTest{
    //espresso rule which tells which activity to start
    @Rule
    public final ActivityTestRule<SnackbarActivity> mActivityRule = 
        new ActivityTestRule<>(SnackbarActivity.class, true, false);


    @Override
    public void tearDown() throws Exception {
        super.tearDown();
        //just an example how tear down should cleanup after itself
        mDatabase.clear();
        mSharedPrefs.clear();
    }
    
    @Override
    public void setUp() throws Exception {
        super.setUp();
        //setting up your application, for example if you need to have a user in shared
        //preferences to stay logged in you can do that for all tests in your setup
        User mUser = new User();
        mUser.setToken("randomToken");
    }
    
    /**
    *Test methods should always start with "testXYZ" and it is a good idea to 
    *name them after the intent what you want to test
    **/
    @Test
    public void testSnackbarIsShown() {
        //start our activity
        mActivityRule.launchActivity(null);
        //check is our text entry displayed and enter some text to it
        String textToType="new snackbar text";
        onView(withId(R.id.textEntry)).check(matches(isDisplayed()));
        onView(withId(R.id.textEntry)).perform(typeText(textToType));
        //click the button to show the snackbar
        onView(withId(R.id.shownSnackbarBtn)).perform(click());
        //assert that a view with snackbar_id with text which we typed and is displayed
        onView(allOf(withId(android.support.design.R.id.snackbar_text), 
        withText(textToType))) .check(matches(isDisplayed()));
    }
}

Как вы заметили, есть 3-4 вещи, которые вы могли заметить часто:

onView (withXYZ) <- viewMatchers с ними вы можете найти элементы на экране

выполнить (click ()) <- viewActions, вы можете выполнять действия над элементами, которые вы ранее обнаружили

check (matches (isDisplayed ())) <- viewAssertions, проверки, которые вы хотите сделать на экранах, которые вы ранее обнаружили

Все эти и многие другие можно найти здесь: https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/index.html

То есть, теперь вы можете запустить тест либо щелкнув правой кнопкой мыши по имени / тесту класса, либо выбрав команду «Запустить тест» или с помощью команды:

./gradlew connectedFLAVORNAMEAndroidTest

Вверх Навигация

@Test
public void testUpNavigation() {
    intending(hasComponent(ParentActivity.class.getName())).respondWith(new Instrumentation.ActivityResult(0, null));

    onView(withContentDescription("Navigate up")).perform(click());

    intended(hasComponent(ParentActivity.class.getName()));
}

Обратите внимание, что это обходное решение и столкнется с другими представлениями, которые имеют одно и то же описание содержимого.

Выполнение действия в представлении

С помощью метода выполнения ViewActions просматривать ViewActions в представлении.
Класс ViewActions предоставляет вспомогательные методы для наиболее распространенных действий, таких как:

ViewActions.click()
ViewActions.typeText()
ViewActions.clearText()

Например, чтобы щелкнуть по виду:

onView(...).perform(click());
onView(withId(R.id.button_simple)).perform(click());

Вы можете выполнить более одного действия с помощью одного вызова:

onView(...).perform(typeText("Hello"), click());

Если представление, с которым вы работаете, находится внутри ScrollView (вертикальное или горизонтальное), рассмотрите предыдущие действия, которые требуют отображения вида (например, click() и typeText() ) с помощью scrollTo() . Это гарантирует, что представление отображается до перехода к другому действию:

onView(...).perform(scrollTo(), click());

Поиск представления с помощью onView

С помощью ViewMatchers вы можете найти представление в текущей иерархии представлений.

Чтобы найти представление, используйте метод onView() с onView() вида, который выбирает правильный вид. onView() возвращают объект типа ViewInteraction .

Например, поиск вида по его R.id так же просто, как:

onView(withId(R.id.my_view))

Поиск представления с текстом:

onView(withText("Hello World"))

Эспрессо

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

Наиболее важные из них можно найти в следующем чит-листе:

https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/

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

  • withId (R.id.ID_of_object_you_are_looking_for);
  • withText («Некоторый текст, который вы ожидаете от объекта»);
  • isDisplayed () <- проверка - вид видимый
  • doesNotExist () <- проверить, что вид не существует

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

Существует 2 наиболее распространенных типа матчи, которые вы можете расширить: TypeSafeMatcher BoundedMatcher

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

Например, введите безопасный соединитель, который проверяет изображение, имеет правильную возможность:

public class DrawableMatcher extends TypeSafeMatcher<View> {

    private @DrawableRes final int expectedId;
    String resourceName;
    
    public DrawableMatcher(@DrawableRes int expectedId) {
        super(View.class);
        this.expectedId = expectedId;
    }

    @Override
    protected boolean matchesSafely(View target) {
        //Type check we need to do in TypeSafeMatcher
        if (!(target instanceof ImageView)) {
            return false;
        }
        //We fetch the image view from the focused view
        ImageView imageView = (ImageView) target;
        if (expectedId < 0) {
            return imageView.getDrawable() == null;
        }
        //We get the drawable from the resources that we are going to compare with image view source
        Resources resources = target.getContext().getResources();
        Drawable expectedDrawable = resources.getDrawable(expectedId);
        resourceName = resources.getResourceEntryName(expectedId);

        if (expectedDrawable == null) {
            return false;
        }
        //comparing the bitmaps should give results of the matcher if they are equal
        Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
        Bitmap otherBitmap = ((BitmapDrawable) expectedDrawable).getBitmap();
        return bitmap.sameAs(otherBitmap);
    }


    @Override
    public void describeTo(Description description) {
        description.appendText("with drawable from resource id: ");
        description.appendValue(expectedId);
        if (resourceName != null) {
            description.appendText("[");
            description.appendText(resourceName);
            description.appendText("]");
        }
    }
}

Использование соединителя можно обернуть следующим образом:

  public static Matcher<View> withDrawable(final int resourceId) {
    return new DrawableMatcher(resourceId);
}

 onView(withDrawable(R.drawable.someDrawable)).check(matches(isDisplayed()));

Ограниченные шаблоны похожи, вам просто не нужно делать проверку типа, но, поскольку это делается автоматически для вас:

 /**
 * Matches a {@link TextInputFormView}'s input hint with the given resource ID
 *
 * @param stringId
 * @return
 */
public static Matcher<View> withTextInputHint(@StringRes final int stringId) {
    return new BoundedMatcher<View, TextInputFormView>(TextInputFormView.class) {
        private String mResourceName = null;

        @Override
        public void describeTo(final Description description) {
            //fill these out properly so your logging and error reporting is more clear
            description.appendText("with TextInputFormView that has hint ");
            description.appendValue(stringId);
            if (null != mResourceName) {
                description.appendText("[");
                description.appendText(mResourceName);
                description.appendText("]");
            }
        }

        @Override
        public boolean matchesSafely(final TextInputFormView view) {
            if (null == mResourceName) {
                try {
                    mResourceName = view.getResources().getResourceEntryName(stringId);
                } catch (Resources.NotFoundException e) {
                    throw new IllegalStateException("could not find string with ID " + stringId, e);
                }
            }
            return view.getResources().getString(stringId).equals(view.getHint());
        }
    };
}

Подробнее о помощниках можно прочитать:

http://hamcrest.org/

https://developer.android.com/reference/android/support/test/espresso/matcher/ViewMatchers.html

Общий эспрессо

Настройка эспрессо:

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'

ViewMatchers - коллекция объектов, реализующих Matcher<? super View> . Вы можете передать один или несколько из них методу onView чтобы найти представление в текущей иерархии представлений.

ViewActions - коллекция ViewActions которая может быть передана ViewInteraction.perform() (например, click() ).

ViewAssertions - коллекция ViewAssertions которая может быть передана ViewInteraction.check() . В большинстве случаев вы будете использовать утверждение совпадений, которое использует совпадение View для утверждения состояния выбранного в данный момент вида.


Кошелек для эспрессо от Google

введите описание изображения здесь


Введите текст в EditText

onView(withId(R.id.edt_name)).perform(typeText("XYZ"));
        closeSoftKeyboard();

Выполнить

 onView(withId(R.id.btn_id)).perform(click());

Отображается проверка просмотра

 onView(withId(R.id.edt_pan_number)).check(ViewAssertions.matches((isDisplayed())));

Группировать коллекцию тестовых классов в тестовом наборе

Вы можете организовать выполнение ваших инструментальных тестов, определяющих Suite .

/**
 * Runs all unit tests.
 */
@RunWith(Suite.class)
@Suite.SuiteClasses({MyTest1.class , 
         MyTest2.class, 
         MyTest3.class})
public class AndroidTestSuite {}

Затем в AndroidStudio вы можете работать с градиентом или настраивать новую конфигурацию, например:

введите описание изображения здесь

Набор тестов может быть вложен.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow