Buscar..


Observaciones

Café exprés

La hoja de trucos Espresso te ayudará a escribir tus pruebas y lo que quieres probar:

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

También siempre un buen lugar de referencia es la documentación oficial:

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

Sugerencias avanzadas de video expreso de Google: https://www.youtube.com/watch?v=isihPOY2vS4

Solución de problemas

  • Cuando intente desplazarse, asegúrese de cerrar el teclado primero:

Vigilancia: no usar la versión "Espresso" no hará nada cuando se use fuera de ViewAction. Esto puede no ser obvio si tiene una importación en la versión de ViewAction ya que tienen exactamente el mismo nombre de método.

ViewActions.closeSoftKeyboard;
Espresso.closeSoftKeyboard();
  • Al ejecutar pruebas juntas en una suite en lugar de individualmente, tenga en cuenta que la Actividad de la prueba anterior todavía puede estar ejecutándose. No confíe en que se haya llamado a onDestroy () de la prueba anterior antes de las pruebas actuales enResume (). Resulta que esto es realmente un error : http://b.android.com/201513

Preparar espresso

En el archivo build.gradle de su módulo de aplicación de Android agregue las siguientes dependencias:

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'
}

Especificar el AndroidJUnitRunner para la testInstrumentationRunner parámetro en el build.gradle archivo.

android {

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

}

Además, agregue esta dependencia para proporcionar soporte burlón intencional

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

Y agrega este para soporte de prueba de webview

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

Crear clase de prueba de espresso

Coloque la siguiente clase java en src / android Test / java y ejecútelo.

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
  }

}

Abrir Cerrar CajónDisposición

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

Prueba de IU simple expreso

Herramientas de prueba de interfaz de usuario

Dos herramientas principales que actualmente se utilizan principalmente para las pruebas de UI son Appium y Espresso.

Apio Café exprés
prueba de caja negra prueba de caja blanca / gris
lo que ves es lo que puedes probar puede cambiar el funcionamiento interno de la aplicación y prepararla para la prueba, por ejemplo, guardar algunos datos en la base de datos o las preferencias compartidas antes de ejecutar la prueba
Se utiliza principalmente para pruebas de integración de extremo a extremo y flujos completos de usuarios. Probando la funcionalidad de una pantalla y / o flujo.
se puede abstraer para que la prueba escrita se pueda ejecutar en iOS y Android Solo Android
bien apoyado bien apoyado
Soporta pruebas en paralelo en múltiples dispositivos con rejilla de selenio. No fuera de la caja pruebas paralelas, existen complementos como Spoon hasta que sale el verdadero soporte de Google

Cómo agregar espresso al proyecto

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'
}

NOTA Si está utilizando las últimas bibliotecas de soporte, anotaciones, etc., debe excluir las versiones anteriores de espresso para evitar colisiones:

    // 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'
    }

Aparte de estas importaciones, es necesario agregar el corredor de pruebas de instrumentación de Android a build.gradle android.defaultConfig:

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

Configuración de dispositivo

Para pruebas no escamosas, se recomienda establecer las siguientes configuraciones en sus dispositivos:

  • Opciones de desarrollador / Deshabilitar animaciones - reduce la descamación de las pruebas
  • Opciones de desarrollador / Manténgase despierto: si tiene dispositivos dedicados para pruebas, esto es útil
  • Opciones de desarrollador / Tamaños de búfer del registrador: establezca un número más alto si ejecuta conjuntos de pruebas muy grandes en su teléfono
  • Accesibilidad / Retardo de toque y retención: largo para evitar problemas con el toque en el espresso

Bastante una configuración del mundo real ha? Bueno, ahora que está fuera del camino, veamos cómo configurar una pequeña prueba.

Escribiendo la prueba

Supongamos que tenemos la siguiente pantalla: Smple screen para prueba de expreso La pantalla contiene:

  • campo de entrada de texto - R.id.textEntry
  • botón que muestra snackbar con texto escrito cuando se hace clic - R.id.shownSnackbarBtn
  • snackbar que debe contener texto escrito por el usuario - android.support.design.R.id.snackbar_text

Ahora vamos a crear una clase que probará nuestro flujo:

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

Como te habrás dado cuenta, hay 3-4 cosas que podrías notar que vienen a menudo:

onView (withXYZ) <- viewMatchers con ellos puedes encontrar elementos en la pantalla

realizar (clic ()) <- verAcciones, puede ejecutar acciones en elementos que encontró anteriormente

cheque (coincide (isDisplayed ())) <- viewAssertions, cheques que desea hacer en las pantallas que encontró anteriormente

Todos estos y muchos otros se pueden encontrar aquí: https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/index.html

Eso es todo, ahora puede ejecutar la prueba haciendo clic derecho en el nombre de la clase / prueba y seleccionando Ejecutar prueba o con el comando:

./gradlew connectedFLAVORNAMEAndroidTest

Arriba navegación

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

Tenga en cuenta que esta es una solución alternativa y que chocará con otras Vistas que tienen la misma descripción de contenido.

Realizar una acción en una vista

Es posible realizar ViewActions en una vista usando el método de ejecución.
La clase ViewActions proporciona métodos de ayuda para las acciones más comunes, como:

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

Por ejemplo, para hacer clic en la vista:

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

Puede ejecutar más de una acción con una llamada de ejecución:

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

Si la vista con la que está trabajando se encuentra dentro de un ScrollView (vertical u horizontal), considere las acciones anteriores que requieren que la vista se muestre (como click() y typeText() ) con scrollTo() . Esto asegura que la vista se muestre antes de continuar con la otra acción:

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

Encontrar una vista con onView

Con los ViewMatchers puede encontrar la vista en la jerarquía de vista actual.

Para encontrar una vista, use el método onView() con un comparador de vista que seleccione la vista correcta. Los métodos onView() devuelven un objeto de tipo ViewInteraction .

Por ejemplo, encontrar una vista por su R.id es tan simple como:

onView(withId(R.id.my_view))

Encontrando una vista con un texto:

onView(withText("Hello World"))

Cafeteras personalizadas espresso

El espresso por defecto tiene muchos emparejadores que lo ayudan a encontrar vistas que necesita para hacer algunas comprobaciones o interacciones con ellas.

Los más importantes se pueden encontrar en la siguiente hoja de trucos:

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

Algunos ejemplos de matchers son:

  • withId (R.id.ID_of_object_you_are_looking_for);
  • withText ("Algún texto que esperas que tenga el objeto");
  • isDisplayed () <- verifique si la vista está visible
  • doesNotExist () <- comprueba que la vista no existe

Todos estos son muy útiles para el uso diario, pero si tiene vistas más complejas, escribir sus emparejadores personalizados puede hacer que las pruebas sean más legibles y pueda reutilizarse en diferentes lugares.

Hay 2 tipos de emparejadores más comunes que puede extender: TypeSafeMatcher BoundedMatcher

La implementación de TypeSafeMatcher requiere que verifique la instancia de la vista contra la que está afirmando, si es del tipo correcto que coincida con algunas de sus propiedades con el valor que proporcionó a un comparador.

Por ejemplo, el tipo de coincidencia segura que valida una vista de imagen tiene dibujable correcto:

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

El uso del emparejador podría ser envuelto así:

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

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

Los emparejadores limitados son similares, simplemente no tiene que hacer la verificación de tipo pero, como eso se hace automágicamente para usted:

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

Más sobre los matchers se puede leer en:

http://hamcrest.org/

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

Espresso general

Espresso de configuración:

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

ViewMatchers : una colección de objetos que implementan Matcher<? super View> interfaz. Puede pasar uno o más de estos al método onView para ubicar una vista dentro de la jerarquía de vista actual.

ViewActions : una colección de ViewActions que se puede pasar al método ViewInteraction.perform() (por ejemplo, click() ).

ViewAssertions : una colección de ViewAssertions que se puede pasar el método ViewInteraction.check() . La mayoría de las veces, utilizará la aserción de coincidencias, que utiliza un igualador de vista para afirmar el estado de la vista seleccionada actualmente.


Espresso cheat sheet de google

introduzca la descripción de la imagen aquí


Introduzca texto en EditarTexto

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

Realizar Clic en Vista

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

Se muestra la vista de comprobación

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

Agrupar una colección de clases de prueba en un conjunto de pruebas

Puede organizar la ejecución de sus pruebas de unidades instrumentadas definiendo una Suite .

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

Luego, en AndroidStudio puede ejecutar Gradle o establecer una nueva configuración como:

introduzca la descripción de la imagen aquí

Las suites de prueba se pueden anidar.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow