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:
- Abra o arquivo
build.gradle
do seu app. Normalmente, esse não é o arquivobuild.gradle
de nível superior, masapp/build.gradle
. Adicione a seguinte linha nas dependências:
androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
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. ChamewithElement()
primeiro para estabelecer o objetoWeb.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 comotrue
.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
.