Participe do evento ⁠#Android11: apresentação de lançamento da versão Beta no dia 3 de junho.

Espresso Web

Espresso-Web é um ponto de entrada para trabalhar com componentes de IU do Android WebView. O Espresso-Web reutiliza Atoms da conhecida API WebDriver (em inglês) para examinar e controlar o comportamento de um WebView.

Quando usar o Espresso-Web

Use o Espresso-Web para testar seus apps híbridos, especialmente a integração dos componentes da IU nativa do app com os componentes da IU do WebView. Você pode usar a API do Espresso-Web com outras APIs do Espresso para interagir de maneira completa com os elementos da Web em objetos WebView.

Se você precisa testar o WebView, e não as interações entre o WebView e os componentes nativos do app, programe um teste geral da Web usando um framework como WebDriver. Se você usa um framework de testes da Web, não precisa de um dispositivo Android ou uma máquina virtual Java. Assim, os testes serão executados de forma mais rápida e confiável. Dito isso, o Espresso-Web permite reutilizar atoms personalizados do WebDriver, o que oferece muita flexibilidade, especialmente ao programar testes que você pretende executar em apps autônomos da Web e em apps que incluem uma IU do Android.

Como funciona

Assim como o método onData() do Espresso, uma interação do WebView inclui vários Atom. As interações do WebView usam uma combinação da linguagem de programação Java e uma ponte JavaScript para fazer o trabalho delas. Como não é possível introduzir disputas expondo dados do ambiente JavaScript, porque tudo o que o Espresso vê no lado baseado em Java é uma cópia isolada, o retorno de dados de objetos Web.WebInteraction é totalmente compatível. Assim, é possível verificar todos os dados retornados de uma solicitação.

O que é um Atom do WebDriver?

O framework do WebDriver usa Atoms para localizar e manipular elementos da Web de forma programática. Os Atoms são usados pelo WebDriver para permitir a manipulação do navegador. Conceitualmente, um Atom é semelhante a uma ViewAction, uma unidade independente que realiza uma ação na IU. Para expor Atoms, use uma lista de métodos definidos, como findElement() e getElement(), para direcionar o navegador a partir do ponto de vista do usuário. No entanto, se você usa o framework do WebDriver diretamente, os Atoms precisam ser corretamente orquestrados, o que exige uma lógica bastante detalhada.

Dentro do Espresso, as classes Web e Web.WebInteraction unem esse código clichê e proporcionam uma experiência semelhante à do Expresso para interagir com objetos do WebView. Portanto, no contexto de um WebView, os Atoms são usados como uma substituição dos tradicionais ViewMatchers e ViewActions do Espresso.

A API é bastante simples:

Kotlin

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

Java

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

Para saber mais, leia a documentação do Selenium sobre Atoms (em inglês).

Implementar o WebView

Siga as orientações mostradas nas seções a seguir para trabalhar com o WebView nos testes do app.

Pacotes

Para incluir o Espresso-Web no projeto, siga estas etapas:

  1. Abra o arquivo build.gradle do seu app. Normalmente, esse não é o arquivo build.gradle de nível superior, mas app/build.gradle.
  2. Adicione a seguinte linha nas dependências:

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
        
  3. O Espresso-Web é compatível apenas com o Espresso 2.2 ou posterior e com a biblioteca de teste 0.3 ou posterior. Por isso, atualize estas linhas também:

        androidTestImplementation 'androidx.test:runner:1.1.0'
        androidTestImplementation 'androidx.test:rules:1.1.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
        

Uso comum da API

O método onWebView() é o principal ponto de entrada ao trabalhar com o WebView no Android usando o Espresso. Use esse método para realizar testes do Espresso-Web, por exemplo:

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

Nesse exemplo, o Espresso-Web localiza um elemento DOM cujo código é "link_2" e clica nele. A ferramenta verifica se o WebView envia uma solicitação GET que contém a string "navigation_2.html".

Compatibilidade com JavaScript

Ao executar seus testes, o sistema realiza todas as interações do WebView por meio de JavaScript. Portanto, para oferecer compatibilidade com a avaliação do JavaScript, o WebView em teste precisa ter o JavaScript ativado.

Para forçar a ativação do JavaScript, chame forceJavascriptEnabled() como uma ação na sua atividade em teste, conforme mostrado no snippet de código a seguir.

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

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

Interações comuns na Web

As interações comuns com objetos Web.WebInteraction incluem o seguinte:

  • withElement() faz referência a um elemento DOM no WebView.

    Exemplo:

    Kotlin

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

    Java

        onWebView().withElement(findElement(Locator.ID, "teacher"));
        
  • withContextualElement() faz referência a um elemento DOM com escopo no WebView, em relação a outro elemento DOM. Chame withElement() primeiro para estabelecer o objeto Web.WebInteraction (elemento DOM).

    Exemplo:

    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() avalia uma condição para garantir que ela seja resolvida como true.

    Exemplo:

    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() executa uma ação dentro de um WebView, como clicar em um elemento.

    Exemplo:

    Kotlin

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

    Java

        onWebView()
            .withElement(findElement(Locator.ID, "teacher"))
            .perform(webClick());
        
  • reset(): reverte o WebView ao estado inicial. Isso é necessário quando uma ação anterior, como um clique, introduz uma mudança na navegação que torna os objetos ElementReference e WindowReference inacessíveis.

    Observação: embora o uso de reset() seja útil durante a criação de declarações em relação a fluxos de trabalho de várias páginas, como envios de formulários, seus testes geralmente precisam ter escopo limitado e foco em uma única página.

    Exemplo:

    Kotlin

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

    Java

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

Exemplo

O exemplo a seguir testa se, depois de inserir um texto em um WebView e selecionar o botão Submit, o mesmo texto é exibido em outro elemento desse 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)));
    }
    

Outros recursos

Para saber mais sobre o uso do Espresso-Web em testes do Android, consulte os recursos a seguir.

Exemplos

  • WebBasicSample (em inglês): use o Espresso-Web para interagir com objetos WebView.