Espresso Web

Espresso-Web est un point d'entrée permettant d'utiliser les composants de l'interface utilisateur Android WebView. Espresso-Web réutilise les Atoms de l'API WebDriver populaire pour examiner et contrôler le comportement d'une WebView.

Quand utiliser Espresso-Web ?

Utilisez Espresso-Web pour tester vos applications hybrides, en particulier l'intégration des composants d'interface utilisateur natifs de votre application avec ses composants d'interface utilisateur WebView. Vous pouvez utiliser l'API Espresso-Web conjointement avec d'autres API Espresso pour interagir entièrement avec les éléments Web dans des objets WebView.

Si vous ne devez tester que le WebView lui-même, et non les interactions entre WebView et les composants natifs de votre application, envisagez d'écrire un test Web général à l'aide d'un framework tel que WebDriver. Si vous utilisez un framework de test Web, vous n'avez pas besoin d'utiliser d'appareil Android ni de machine virtuelle Java, ce qui rend vos tests plus rapides et plus fiables. Cela dit, Espresso-Web vous permet de réutiliser vos atomes WebDriver personnalisés, ce qui vous offre une grande flexibilité, en particulier lors de l'écriture de tests que vous prévoyez d'exécuter à la fois sur des applications Web autonomes et sur des applications incluant une UI Android.

Fonctionnement

Comme pour la méthode onData() d'Espresso, une interaction WebView comprend plusieurs Atoms. Les interactions WebView utilisent une combinaison du langage de programmation Java et d'un pont JavaScript pour effectuer leur travail. Étant donné qu'il n'y a aucun risque d'introduction de conditions de concurrence en exposant les données de l'environnement JavaScript (tout ce qu'Espresso voit du côté Java est une copie isolée), le renvoi de données à partir d'objets Web.WebInteraction est entièrement pris en charge, ce qui vous permet de vérifier toutes les données renvoyées par une requête.

Qu'est-ce qu'un WebDriver Atom ?

Le framework WebDriver utilise Atoms pour rechercher et manipuler des éléments Web de manière programmatique. Les Atoms sont utilisés par WebDriver pour permettre la manipulation du navigateur. Un Atom est semblable au concept ViewAction, une unité autonome qui effectue une action dans votre interface utilisateur. Vous exposez Atoms à l'aide d'une liste de méthodes définies, telles que findElement() et getElement(), pour piloter le navigateur du point de vue de l'utilisateur. Toutefois, si vous utilisez directement le framework WebDriver, les Atoms doivent être correctement ordonnés, ce qui nécessite une logique assez complexe.

Dans Espresso, les classes Web et Web.WebInteraction encapsulent ce code récurrent et donnent une impression d'Espresso pour interagir avec les objets WebView. Ainsi, dans le contexte d'un WebView, Atoms est utilisé en remplacement des ViewMatchers et ViewActions traditionnels d'Espresso.

L'API a alors l'air assez simple:

Kotlin

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion)

Java

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion);

Pour en savoir plus, consultez la documentation de Selenium sur Atoms.

Implémenter WebView

Suivez les conseils indiqués dans les sections suivantes pour utiliser WebView dans les tests de votre application.

Colis

Pour inclure Espresso-Web dans votre projet, procédez comme suit:

  1. Ouvrez le fichier build.gradle de votre application. Il ne s'agit généralement pas du fichier build.gradle de premier niveau, mais du fichier app/build.gradle.
  2. Ajoutez la ligne suivante dans les dépendances:

    Groovy

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.4.0'
        

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.4.0')
        
  3. Espresso-Web n'est compatible qu'avec Espresso 2.2 ou version ultérieure et les versions 0.3 ou ultérieures de la bibliothèque de test. Veillez donc à mettre également à jour ces lignes:

    Groovy

        androidTestImplementation 'androidx.test:runner:1.4.0'
        androidTestImplementation 'androidx.test:rules:1.4.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
        

    Kotlin

        androidTestImplementation('androidx.test:runner:1.4.0')
        androidTestImplementation('androidx.test:rules:1.4.0')
        androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')
        

Utilisation courante des API

La méthode onWebView() est le point d'entrée principal lorsque vous utilisez WebView sur Android à l'aide d'Espresso. Cette méthode permet d'effectuer des tests Espresso-Web, par exemple:

Kotlin

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))

Java

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));

Dans cet exemple, Espresso-Web localise un élément DOM dont l'ID est "link_2" et clique dessus. L'outil vérifie ensuite que WebView envoie une requête GET contenant la chaîne "navigation_2.html".

Compatibilité avec JavaScript

Lors de l'exécution des tests, le système effectue toutes les interactions WebView à l'aide de JavaScript. Par conséquent, pour que l'évaluation JavaScript soit compatible, vous devez activer JavaScript dans la WebView testée.

Vous pouvez forcer l'activation de JavaScript en appelant forceJavascriptEnabled() en tant qu'action dans votre activité testée, comme indiqué dans l'extrait de code suivant.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

Interactions Web courantes

Voici quelques interactions courantes avec les objets Web.WebInteraction:

  • withElement() fait référence à un élément DOM dans la WebView.

    Exemple :

    Kotlin

    onWebView().withElement(findElement(Locator.ID, "teacher"))
    

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
    
  • withContextualElement() fait référence à un élément DOM dont le champ d'application est défini dans la WebView, par rapport à un autre élément DOM. Vous devez d'abord appeler withElement() pour établir l'objet Web.WebInteraction de référence (élément DOM).

    Exemple :

    Kotlin

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
    

    Java

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"));
    
  • check() évalue une condition et vérifie qu'elle renvoie true.

    Exemple :

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")))
    

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")));
    
  • perform() exécute une action dans un composant WebView, par exemple un clic sur un élément.

    Exemple :

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())
    

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
    
  • reset() rétablit l'état initial de la WebView. Cela est nécessaire lorsqu'une action précédente (un clic, par exemple) introduit une modification de navigation qui rend les objets ElementReference et WindowReference inaccessibles.

    Remarque:Bien que l'utilisation de reset() soit utile lors des assertions sur des workflows de plusieurs pages, tels que l'envoi de formulaires, vos tests doivent généralement avoir une portée limitée et se concentrer sur une seule page.

    Exemple :

    Kotlin

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()
    

    Java

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();
    

Exemple

L'exemple suivant vérifie si, après avoir saisi du texte dans une WebView et sélectionné un bouton Submit (Envoyer), le même texte apparaît dans un autre élément de la même WebView:

Kotlin

const val MACCHIATO = "Macchiato"

@RunWith(AndroidJUnit4::class)
class MyEspressoWebTestSuite {

    @Test fun typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        val webFormIntent = Intent()
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent)

        // Selects the WebView in your layout. If you have multiple WebView
        // objects, you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)))
    }
}

Java

public static final String MACCHIATO = "Macchiato";

@Test
public void typeTextInInput_clickButton_SubmitsForm() {
    // Create an intent that displays a web form.
    Intent webFormIntent = new Intent();
    // ...

    // Lazily launch the Activity with a custom start Intent per test.
    ActivityScenario.launchActivity(webFormIntent);

    // Selects the WebView in your layout. If you have multiple WebView objects,
    // you can also use a matcher to select a given WebView,
    // onWebView(withId(R.id.web_view)).
    onWebView()
        // Find the input element by ID.
        .withElement(findElement(Locator.ID, "text_input"))

        // Clear previous input and enter new text into the input element.
        .perform(clearElement())
        .perform(DriverAtoms.webKeys(MACCHIATO))

        // Find the "Submit" button and simulate a click using JavaScript.
        .withElement(findElement(Locator.ID, "submitBtn"))
        .perform(webClick())

        // Find the response element by ID, and verify that it contains the
        // entered text.
        .withElement(findElement(Locator.ID, "response"))
        .check(webMatches(getText(), containsString(MACCHIATO)));
}

Ressources supplémentaires

Pour en savoir plus sur l'utilisation d'Espresso-Web dans les tests Android, consultez les ressources suivantes.

Exemples

  • WebBasicSample : utilisez Espresso-Web pour interagir avec les objets WebView.