Espresso-Web — это точка входа для работы с компонентами пользовательского интерфейса Android WebView. Espresso-Web использует атомы из популярного API WebDriver для анализа и управления поведением WebView.
Когда использовать Espresso-Web
Используйте Espresso-Web для тестирования своих гибридных приложений, особенно интеграции собственных компонентов пользовательского интерфейса вашего приложения с компонентами пользовательского интерфейса WebView
. Вы можете использовать Espresso-Web API совместно с другими API Espresso для полноценного взаимодействия с веб-элементами внутри объектов WebView
.
Если вам нужно протестировать только сам WebView
, а не взаимодействие между WebView
и нативными компонентами вашего приложения, рассмотрите возможность написания общего веб-теста с использованием фреймворка, например WebDriver . При использовании фреймворка для веб-тестирования вам не потребуется устройство Android или виртуальная машина Java, что обеспечивает более быстрое и надежное выполнение тестов. При этом Espresso-Web позволяет повторно использовать ваши собственные атомы WebDriver, что обеспечивает большую гибкость, особенно при написании тестов, которые вы планируете запускать как для отдельных веб-приложений, так и для приложений с пользовательским интерфейсом Android.
Как это работает
Подобно методу onData()
в Espresso, взаимодействие WebView
состоит из нескольких объектов Atom. Взаимодействие WebView
использует для своей работы сочетание языка программирования Java и JavaScript-моста. Поскольку отсутствует вероятность возникновения условий гонки при предоставлении данных из среды JavaScript (всё, что Espresso видит на стороне Java, представляет собой изолированную копию), возврат данных из объектов Web.WebInteraction
полностью поддерживается, что позволяет проверять все данные, возвращаемые запросом.
Что такое WebDriver Atom?
Фреймворк WebDriver использует атомы для программного поиска и управления веб-элементами. Атомы используются WebDriver для управления браузером. Концептуально атом аналогичен ViewAction
— автономному блоку, выполняющему действие в пользовательском интерфейсе. Вы предоставляете атомы с помощью списка определённых методов, таких как findElement()
и getElement()
, для управления браузером с точки зрения пользователя. Однако при непосредственном использовании фреймворка WebDriver атомы необходимо правильно организовать, что требует довольно сложной логики.
В Espresso классы Web
и Web.WebInteraction
обёртывают этот шаблон и придают взаимодействие с объектами WebView в стиле Espresso. Таким образом, в контексте WebView
атомы используются в качестве замены традиционным ViewMatchers
и ViewActions
Espresso.
API тогда выглядит довольно просто:
Котлин
onWebView() .withElement(Atom) .perform(Atom) .check(WebAssertion)
Ява
onWebView() .withElement(Atom) .perform(Atom) .check(WebAssertion);
Более подробную информацию можно найти в документации Selenium по Atoms .
Реализовать WebView
Следуйте инструкциям, приведенным в следующих разделах, для работы с WebView
в тестах вашего приложения.
Пакеты
Чтобы включить Espresso-Web в свой проект, выполните следующие шаги:
- Откройте файл
build.gradle
вашего приложения. Обычно это не файлbuild.gradle
верхнего уровня, аapp/build.gradle
. Добавьте следующую строку в зависимости:
Круто
androidTestImplementation 'androidx.test.espresso:espresso-web:3.6.1'
Котлин
androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
Espresso-Web совместим только с Espresso 2.2 или выше и версией 0.3 или выше тестовой библиотеки, поэтому обязательно обновите и эти строки:
Круто
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Котлин
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
Распространенное использование API
Метод onWebView()
— это основная точка входа при работе с WebView на Android с использованием Espresso. Он используется для выполнения тестов Espresso-Web, таких как:
Котлин
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")))
Ява
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")));
В этом примере Espresso-Web находит элемент DOM с идентификатором "link_2"
и щёлкает по нему. Затем инструмент проверяет, отправляет ли WebView GET-запрос, содержащий строку "navigation_2.html"
.
Поддержка JavaScript
При выполнении тестов система выполняет все взаимодействия с WebView с помощью JavaScript. Поэтому для поддержки оценки JavaScript в тестируемом WebView должен быть включен JavaScript.
Вы можете принудительно включить JavaScript, вызвав forceJavascriptEnabled()
как действие в тестируемой активности , как показано в следующем фрагменте кода.
@RunWith(AndroidJUnit4::class) class MyTestSuite { @get:Rule val activityScenarioRule = activityScenarioRule<MyWebViewActivity>() @Test fun testWebViewInteraction() { onWebView().forceJavascriptEnabled() } }
Распространенные веб-взаимодействия
К распространенным взаимодействиям с объектами Web.WebInteraction
относятся следующие:
withElement()
ссылается на элемент DOM внутри WebView.Пример:
Котлин
onWebView().withElement(findElement(Locator.ID, "teacher"))
Ява
onWebView().withElement(findElement(Locator.ID, "teacher"));
withContextualElement()
ссылается на DOM-элемент в WebView, относящийся к другому DOM-элементу. Для установки объектаWeb.WebInteraction
(DOM-элемента) сначала необходимо вызвать методwithElement()
.Пример:
Котлин
.withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name"))
Ява
.withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name"));
check()
оценивает условие, проверяя, что оно принимает значениеtrue
.Пример:
Котлин
onWebView() .withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name")) .check(webMatches(getText(), containsString("Socrates")))
Ява
onWebView() .withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name")) .check(webMatches(getText(), containsString("Socrates")));
perform()
выполняет действие в WebView, например, щелчок по элементу.Пример:
Котлин
onWebView() .withElement(findElement(Locator.ID, "teacher")) .perform(webClick())
Ява
onWebView() .withElement(findElement(Locator.ID, "teacher")) .perform(webClick());
reset()
возвращает WebView в исходное состояние. Это необходимо, когда предыдущее действие, например, щелчок, приводит к изменению навигации, которое делает объекты ElementReference и WindowReference недоступными.Примечание: Хотя использование
reset()
полезно при формировании утверждений для многостраничных рабочих процессов, таких как отправка форм, ваши тесты, как правило, должны быть ограничены по области применения и сосредоточены на одной странице.Пример:
Котлин
onWebView() .withElement(...) .perform(...) .reset()
Ява
onWebView() .withElement(...) .perform(...) .reset();
Пример
В следующем примере проверяется, появится ли тот же текст в другом элементе того же WebView после ввода текста в WebView и нажатия кнопки «Отправить» :
Котлин
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))) } }
Ява
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))); }
Дополнительные ресурсы
Дополнительную информацию об использовании Espresso-Web в тестах Android можно найти в следующих ресурсах.
Образцы
- WebBasicSample : использование Espresso-Web для взаимодействия с объектами
WebView
.