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 interface nativa do app com os componentes da interface WebView. Você pode usar a API do Espresso-Web com outras APIs do Espresso para interagir de maneira completa com os elementos da Web dentro de objetos WebView.

Se for necessário testar apenas o WebView, e não as interações entre o WebView e os componentes nativos do app, crie um teste da Web geral usando um framework como o WebDriver. Se você usa um framework de teste da Web, não precisa usar um dispositivo Android ou uma máquina virtual Java, o que torna os testes mais rápidos e confiáveis. Dito isso, o Espresso-Web permite reutilizar os atoms personalizados do WebDriver, o que oferece muita flexibilidade, especialmente ao programar testes que você planeja executar em apps da Web autônomos e que incluem uma interface do Android.

Como funciona

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

O que é um Atom do WebDriver?

O framework do WebDriver usa Atoms para encontrar e manipular elementos da Web de maneira 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 executa uma ação na interface. Para expor Atoms, use uma lista de métodos definidos, como findElement() e getElement(), para direcionar o navegador do ponto de vista do usuário. No entanto, se você usar o framework WebDriver diretamente, os Atoms precisarão ser orquestrados corretamente, o que exige uma lógica muito detalhada.

No Espresso, as classes Web e Web.WebInteraction encapsulam esse código boilerplate e proporcionam uma experiência semelhante à do Espresso para interagir com objetos WebView. Portanto, no contexto de um WebView, os Atoms são usados como uma substituição dos métodos 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 abaixo 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. Geralmente, esse não é o arquivo build.gradle de nível superior, mas app/build.gradle.
  2. Adicione a seguinte linha nas dependências:

    Groovy

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

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.4.0')
        
  3. O Espresso-Web é compatível apenas com o Espresso 2.2 ou mais recente e versão 0.3 ou mais recente da biblioteca de testes. Portanto, atualize essas linhas também:

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

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, como estes:

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 ID é "link_2" e clica nele. Em seguida, a ferramenta verifica se a WebView envia uma solicitação GET contendo a string "navigation_2.html".

Compatibilidade com JavaScript

Ao executar seus testes, o sistema realiza todas as interações da WebView usando JavaScript. Portanto, para oferecer suporte à avaliação do JavaScript, o WebView em teste precisa ter o JavaScript ativado.

É possível forçar a ativação do JavaScript chamando forceJavascriptEnabled() como uma ação na sua atividade em teste, conforme mostrado no snippet de código abaixo.

@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 na 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 de referência (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 uma 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 a WebView para o 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 usar reset() seja útil ao fazer 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 abaixo testa se, depois de inserir texto em uma WebView e selecionar o botão Submit, o mesmo texto aparece em um elemento diferente na mesma 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 abaixo.

Exemplos

  • WebBasicSample: use o Espresso-Web para interagir com objetos WebView.