Android Espresso:如何在遵循一个 activity 多个片段架构时测试特定片段
Android Espresso: How do I test a specific Fragment when following one activity to several fragment architecture
我的应用包含一个 Activity
多个 Fragments
。
我想用 Espresso 测试 Fragments
的 UI。不过我运行陷入了一个问题。
如何测试未添加到 onCreate
中的 Activity
的 Fragment
。我在 Fragments
中看到的所有示例都涉及在 onCreate
中添加 Fragment
。
那么我怎样才能告诉 Espresso 转到特定的 Fragment
并从那里开始呢?
谢谢
Espresso 只有在显示时才能测试 Fragments
。这要求它们由 Activity
显示。
根据您当前的设置,您必须使用 Espresso click()
以您的方式(就像用户那样)达到您实际想要测试的 Fragment
。
在我的一个项目中,我有一个显示 Fragments
的 ViewPager
。对于那些 Fragments
我使用自定义 FragmentTestRule
来单独测试它们。我可以直接启动每个 Fragment
并使用 Espresso 来测试它。参见 。
您还可以:
- 不要使用
Fragments
。 Activities
更容易测试。您可以单独测试每个 Activity
。在大多数情况下,Fragments
与 Activities
相比没有任何优势。 Fragments
只会增加实施和测试的难度。
- 使您的
FragmentActivity
在创建时直接显示某个 Fragment
。例如。通过为您的 FragmentActivity
提供额外的特殊意图。但这会向您的应用添加测试代码,这通常不是一个好的解决方案。
只需使用 Activity 的 SupportFragmentManager 显示片段。
例如 (Kotlin) ActivityTestRule:
@Rule
@JvmField
var activityRule = ActivityTestRule(MainActivity::class.java)
只需在测试前执行此操作:
@Before
fun setup() {
activityRule.activity.supportFragmentManager.beginTransaction().replace(R.id.main_activity_container_for_your_fragments, FragmentToShow(), "fragment-tag").commitAllowingStateLoss()
Thread.sleep(500)
}
如果您使用的是导航架构组件,则可以通过在测试开始时深度链接到目标片段(使用适当的参数)来立即测试每个片段。
@Rule
@JvmField
var activityRule = ActivityTestRule(MainActivity::class.java)
protected fun launchFragment(destinationId: Int,
argBundle: Bundle? = null) {
val launchFragmentIntent = buildLaunchFragmentIntent(destinationId, argBundle)
activityRule.launchActivity(launchFragmentIntent)
}
private fun buildLaunchFragmentIntent(destinationId: Int, argBundle: Bundle?): Intent =
NavDeepLinkBuilder(InstrumentationRegistry.getInstrumentation().targetContext)
.setGraph(R.navigation.navigation)
.setComponentName(MainActivity::class.java)
.setDestination(destinationId)
.setArguments(argBundle)
.createTaskStackBuilder().intents[0]
destinationId 是导航图中的片段目的地 ID。这是您准备好启动片段后将完成的调用示例:
launchFragment(R.id.target_fragment, targetBundle())
private fun targetBundle(): Bundle? {
val bundle = Bundle()
bundle.putString(ARGUMENT_ID, "Argument needed by fragment")
return bundle
}
这里也回答的比较详细:
所以,根据几家公司的模式和推荐做法。您需要为每个视图编写有针对性的封闭测试,无论是 activity、片段、对话框片段还是自定义视图。
首先你需要通过gradle将以下库导入到你的项目中,如果你使用gradle的方式如下
debugImplementation 'androidx.fragment:fragment-testing:1.2.0-rc03'
debugImplementation 'androidx.test:core:1.3.0-alpha03'
对于 Kotlin,debugImplementation 'androidx.test:core-ktx:1.3.0-alpha03'
为了独立于 activity 测试片段,您可以 start/launch 按以下方式进行测试:
@Test
fun sampleTesting(){
launchFragmentInContainer<YourFragment>()
onView(withId(R.id.sample_view_id)).perform(click())
}
这样,您可以从 activity 中独立测试您的片段,这也是实现封闭和有针对性的 ui 测试的推荐方法之一。有关完整详细信息,您可以从 android 文档
中阅读片段测试文档
https://developer.android.com/training/basics/fragments/testing
而且我发现这个包含大量测试示例的存储库非常有用,尽管它非常限于具有超级简单测试的测试用例的复杂性。虽然它可以是 guide 开始。
我的应用包含一个 Activity
多个 Fragments
。
我想用 Espresso 测试 Fragments
的 UI。不过我运行陷入了一个问题。
如何测试未添加到 onCreate
中的 Activity
的 Fragment
。我在 Fragments
中看到的所有示例都涉及在 onCreate
中添加 Fragment
。
那么我怎样才能告诉 Espresso 转到特定的 Fragment
并从那里开始呢?
谢谢
Espresso 只有在显示时才能测试 Fragments
。这要求它们由 Activity
显示。
根据您当前的设置,您必须使用 Espresso click()
以您的方式(就像用户那样)达到您实际想要测试的 Fragment
。
在我的一个项目中,我有一个显示 Fragments
的 ViewPager
。对于那些 Fragments
我使用自定义 FragmentTestRule
来单独测试它们。我可以直接启动每个 Fragment
并使用 Espresso 来测试它。参见
您还可以:
- 不要使用
Fragments
。Activities
更容易测试。您可以单独测试每个Activity
。在大多数情况下,Fragments
与Activities
相比没有任何优势。Fragments
只会增加实施和测试的难度。 - 使您的
FragmentActivity
在创建时直接显示某个Fragment
。例如。通过为您的FragmentActivity
提供额外的特殊意图。但这会向您的应用添加测试代码,这通常不是一个好的解决方案。
只需使用 Activity 的 SupportFragmentManager 显示片段。
例如 (Kotlin) ActivityTestRule:
@Rule
@JvmField
var activityRule = ActivityTestRule(MainActivity::class.java)
只需在测试前执行此操作:
@Before
fun setup() {
activityRule.activity.supportFragmentManager.beginTransaction().replace(R.id.main_activity_container_for_your_fragments, FragmentToShow(), "fragment-tag").commitAllowingStateLoss()
Thread.sleep(500)
}
如果您使用的是导航架构组件,则可以通过在测试开始时深度链接到目标片段(使用适当的参数)来立即测试每个片段。
@Rule
@JvmField
var activityRule = ActivityTestRule(MainActivity::class.java)
protected fun launchFragment(destinationId: Int,
argBundle: Bundle? = null) {
val launchFragmentIntent = buildLaunchFragmentIntent(destinationId, argBundle)
activityRule.launchActivity(launchFragmentIntent)
}
private fun buildLaunchFragmentIntent(destinationId: Int, argBundle: Bundle?): Intent =
NavDeepLinkBuilder(InstrumentationRegistry.getInstrumentation().targetContext)
.setGraph(R.navigation.navigation)
.setComponentName(MainActivity::class.java)
.setDestination(destinationId)
.setArguments(argBundle)
.createTaskStackBuilder().intents[0]
destinationId 是导航图中的片段目的地 ID。这是您准备好启动片段后将完成的调用示例:
launchFragment(R.id.target_fragment, targetBundle())
private fun targetBundle(): Bundle? {
val bundle = Bundle()
bundle.putString(ARGUMENT_ID, "Argument needed by fragment")
return bundle
}
这里也回答的比较详细:
所以,根据几家公司的模式和推荐做法。您需要为每个视图编写有针对性的封闭测试,无论是 activity、片段、对话框片段还是自定义视图。
首先你需要通过gradle将以下库导入到你的项目中,如果你使用gradle的方式如下
debugImplementation 'androidx.fragment:fragment-testing:1.2.0-rc03'
debugImplementation 'androidx.test:core:1.3.0-alpha03'
对于 Kotlin,debugImplementation 'androidx.test:core-ktx:1.3.0-alpha03'
为了独立于 activity 测试片段,您可以 start/launch 按以下方式进行测试:
@Test
fun sampleTesting(){
launchFragmentInContainer<YourFragment>()
onView(withId(R.id.sample_view_id)).perform(click())
}
这样,您可以从 activity 中独立测试您的片段,这也是实现封闭和有针对性的 ui 测试的推荐方法之一。有关完整详细信息,您可以从 android 文档
中阅读片段测试文档https://developer.android.com/training/basics/fragments/testing
而且我发现这个包含大量测试示例的存储库非常有用,尽管它非常限于具有超级简单测试的测试用例的复杂性。虽然它可以是 guide 开始。