使用 kotlin 进行 Espresso webview 测试
Espresso webview test with kotlin
我正在尝试将 Espresso 示例从 Java 移植到 Kotlin,我收到 WebView version
的错误
我按原样使用 MainActivity.kt
这个名字,它很简单而且很好用:
class MainActivity : AppCompatActivity() {
@VisibleForTesting
val keyUrl2Load = "KEY_URL_TO_LOAD"
@VisibleForTesting
val webFormUrl = "file:///android_asset/web_form.html"
private var mWebView: WebView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mWebView = findViewById<View>(R.id.web_view) as WebView
true.also { mWebView!!.settings.javaScriptEnabled = it }
urlFromIntent(intent)?.let { mWebView!!.loadUrl(it) }
mWebView!!.requestFocus()
mWebView!!.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
return false
}
}
}
private fun urlFromIntent(intent: Intent): String? {
val url = intent.getStringExtra(keyUrl2Load)
return if (!TextUtils.isEmpty(url)) url else webFormUrl
}
}
然而,MainActivityTest.kt
看起来不太容易移植,因为:
package com.example.espressowebview101
import android.content.Intent
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.web.assertion.WebViewAssertions
import androidx.test.espresso.web.sugar.Web
import androidx.test.espresso.web.webdriver.DriverAtoms
import androidx.test.espresso.web.webdriver.Locator
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
//https://github.com/android/testing-samples/tree/main/ui/espresso/WebBasicSample/app/src
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
private val MACCHIATO = "Macchiato"
private val DOPPIO = "Doppio"
lateinit var scenario: ActivityScenario<MainActivity>
@get:Rule
var mActivityRule = activityScenarioRule<MainActivity>()
@After
fun enableJS() {
Web.onWebView().forceJavascriptEnabled()
}
@Test
fun typeTextInInput_clickButton_SubmitsForm() {
val intent = withWebFormIntent()
scenario = ActivityScenario.launch(intent)
// Selects the WebView in your layout. If you have multiple WebViews you can also use a
// matcher to select a given WebView, onWebView(withId(R.id.web_view)).
Web.onWebView() // Find the input element by ID
.withElement(DriverAtoms.findElement(Locator.ID, "text_input")) // Clear previous input
.perform(DriverAtoms.clearElement()) // Enter text into the input element
.perform(DriverAtoms.webKeys(MACCHIATO)) // Find the submit button
.withElement(
DriverAtoms.findElement(
Locator.ID,
"submitBtn"
)
) // Simulate a click via javascript
.perform(DriverAtoms.webClick()) // Find the response element by ID
.withElement(
DriverAtoms.findElement(
Locator.ID,
"response"
)
) // Verify that the response page contains the entered text
.check(
WebViewAssertions.webMatches(
DriverAtoms.getText(),
Matchers.containsString(MACCHIATO)
)
)
}
private fun withWebFormIntent(): Intent {
return Intent().also {
val keyUrl2Load = "KEY_URL_TO_LOAD"
val webFormUrl = "file:///android_asset/web_form.html"
it.putExtra(keyUrl2Load, webFormUrl)
}
}
}
我得到的错误是:
Connected to process 8963 on device 'google-pixel_3_xl-8AJY0LJFQ'.
java.lang.RuntimeException: Unable to resolve activity for: Intent { (has extras) }
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:387)
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:416)
at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:265)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:226)
at com.example.espressowebview101.MainActivityTest.typeTextInInput_clickButton_SubmitsForm(MainActivityTest.kt:36)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:154)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)
您正在尝试启动与 MainActivity 无关的 Intent
。它不知道它应该启动这个 activity.
你的 withWebFormIntent
应该 return 一个 Intent
告诉它启动 MainActivity
.
例如
private fun withWebFormIntent(context: Context): Intent {
return Intent(context, MainActivity::class.java).also {
val keyUrl2Load = "KEY_URL_TO_LOAD"
val webFormUrl = "file:///android_asset/web_form.html"
it.putExtra(keyUrl2Load, webFormUrl)
}
}
有关如何为 activity 构造意图的更多文档,请参阅 this。
我正在尝试将 Espresso 示例从 Java 移植到 Kotlin,我收到 WebView version
的错误我按原样使用 MainActivity.kt
这个名字,它很简单而且很好用:
class MainActivity : AppCompatActivity() {
@VisibleForTesting
val keyUrl2Load = "KEY_URL_TO_LOAD"
@VisibleForTesting
val webFormUrl = "file:///android_asset/web_form.html"
private var mWebView: WebView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mWebView = findViewById<View>(R.id.web_view) as WebView
true.also { mWebView!!.settings.javaScriptEnabled = it }
urlFromIntent(intent)?.let { mWebView!!.loadUrl(it) }
mWebView!!.requestFocus()
mWebView!!.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
return false
}
}
}
private fun urlFromIntent(intent: Intent): String? {
val url = intent.getStringExtra(keyUrl2Load)
return if (!TextUtils.isEmpty(url)) url else webFormUrl
}
}
然而,MainActivityTest.kt
看起来不太容易移植,因为:
package com.example.espressowebview101
import android.content.Intent
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.web.assertion.WebViewAssertions
import androidx.test.espresso.web.sugar.Web
import androidx.test.espresso.web.webdriver.DriverAtoms
import androidx.test.espresso.web.webdriver.Locator
import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers
import org.junit.After
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
//https://github.com/android/testing-samples/tree/main/ui/espresso/WebBasicSample/app/src
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
private val MACCHIATO = "Macchiato"
private val DOPPIO = "Doppio"
lateinit var scenario: ActivityScenario<MainActivity>
@get:Rule
var mActivityRule = activityScenarioRule<MainActivity>()
@After
fun enableJS() {
Web.onWebView().forceJavascriptEnabled()
}
@Test
fun typeTextInInput_clickButton_SubmitsForm() {
val intent = withWebFormIntent()
scenario = ActivityScenario.launch(intent)
// Selects the WebView in your layout. If you have multiple WebViews you can also use a
// matcher to select a given WebView, onWebView(withId(R.id.web_view)).
Web.onWebView() // Find the input element by ID
.withElement(DriverAtoms.findElement(Locator.ID, "text_input")) // Clear previous input
.perform(DriverAtoms.clearElement()) // Enter text into the input element
.perform(DriverAtoms.webKeys(MACCHIATO)) // Find the submit button
.withElement(
DriverAtoms.findElement(
Locator.ID,
"submitBtn"
)
) // Simulate a click via javascript
.perform(DriverAtoms.webClick()) // Find the response element by ID
.withElement(
DriverAtoms.findElement(
Locator.ID,
"response"
)
) // Verify that the response page contains the entered text
.check(
WebViewAssertions.webMatches(
DriverAtoms.getText(),
Matchers.containsString(MACCHIATO)
)
)
}
private fun withWebFormIntent(): Intent {
return Intent().also {
val keyUrl2Load = "KEY_URL_TO_LOAD"
val webFormUrl = "file:///android_asset/web_form.html"
it.putExtra(keyUrl2Load, webFormUrl)
}
}
}
我得到的错误是:
Connected to process 8963 on device 'google-pixel_3_xl-8AJY0LJFQ'.
java.lang.RuntimeException: Unable to resolve activity for: Intent { (has extras) }
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:387)
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:416)
at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:265)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:226)
at com.example.espressowebview101.MainActivityTest.typeTextInInput_clickButton_SubmitsForm(MainActivityTest.kt:36)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:154)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205)
您正在尝试启动与 MainActivity 无关的 Intent
。它不知道它应该启动这个 activity.
你的 withWebFormIntent
应该 return 一个 Intent
告诉它启动 MainActivity
.
例如
private fun withWebFormIntent(context: Context): Intent {
return Intent(context, MainActivity::class.java).also {
val keyUrl2Load = "KEY_URL_TO_LOAD"
val webFormUrl = "file:///android_asset/web_form.html"
it.putExtra(keyUrl2Load, webFormUrl)
}
}
有关如何为 activity 构造意图的更多文档,请参阅 this。