我正在努力使UI测试运行可靠,我有一个MVVM设置,其中包含一个带有UseModel的ViewModel片段。根据UseCase的结果,我向用户显示以下四个视图之一:加载,错误,无结果和结果视图。 片段布局的重要部分:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_postbox"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/light_grey_06_dark_black"
app:visibleOrGone="@{postboxViewModel.viewData.hasData}" />
<include
android:id="@+id/includedNoResults"
layout="@layout/view_no_results_postbox"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:visibleOrGone="@{postboxViewModel.viewData.hasNoResults}" />
<include
android:id="@+id/includedError"
layout="@layout/view_error_postbox"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:viewModel="@{postboxViewModel}"
app:visibleOrGone="@{postboxViewModel.viewData.hasError}" />
<include
android:id="@+id/includedLoading"
layout="@layout/view_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:visibleOrGone="@{postboxViewModel.viewData.isLoading}" />
</FrameLayout>
在测试类中,我不调用API,仅从UseCase返回本地模拟数据。 测试班:
@RunWith(AndroidJUnit4::class)
@LargeTest
class PostBoxFragmentTest : KoinTest {
@MockK(relaxed = true)
lateinit var loadPostboxUseCase: LoadPostboxUseCase
@Before
fun setup() {
MockKAnnotations.init(this)
if (GlobalContext().getOrNull() != null) {
stopKoin()
}
startKoin {
androidContext(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext)
val testKoinViewModule = module {
viewModel {
PostboxViewModel(
application = get(),
mapper = PostboxItemListMapper(PostboxItemMapper(get())),
loadPostboxUseCase = loadPostboxUseCase
)
}
}
modules(listOf(testKoinViewModule))
}
}
@After
fun tearDown() {
unmockkAll()
stopKoin()
}
@Test
fun showLoadingViewTest() {
// Given
coEvery {
loadPostboxUseCase.load()
} returns flowOf(Resource.loading())
// When
launchFragmentInContainer<PostboxFragment>(themeResId = R.style.AppTheme)
// Then
onView(withId(R.id.includedLoading)).check(
matches(isDisplayed())
)
}
@Test
fun showNoResultsViewTest() {
// Given
coEvery {
loadPostboxUseCase.load()
} returns flowOf(Resource.success(emptyPostBoxDummyData))
// When
launchFragmentInContainer<PostboxFragment>(themeResId = R.style.AppTheme)
// Then
onView(withId(R.id.includedNoResults)).check(
matches(isDisplayed())
)
}
//2 more tests for results and error
现在的问题是,当我随机同时运行所有4个测试时,其中一个或两个失败了:
androidx.test.espresso.base.DefaultFailureHandler $ AssertionFailedWithCauseError:'在屏幕上显示给用户'与所选视图不匹配。 预期:向用户显示在屏幕上 得到了:“ ConstraintLayout {id = 2131362084,res-name = includedLoading,可见性= GONE,宽度= 0,高度= 0,has-focus = false,has-focusable = false,has-window-focus = true,可点击= false,已启用= true,is-focused = false,is-focusable = false,is-layout-requested = true,is-selected = false,layout-params = android.widget.FrameLayout $ LayoutParams @ b329d0,标记= null,root-is-layout-requested = false,has-input-connection = false,x = 0.0,y = 0.0,child-count = 1}“
如果我分别运行测试,则可以正常工作-即使失败的测试也可以。我的猜测是,仿真器太快(动画禁用)或片段太慢。我用IdlingResource尝试过,如此处所述 Instrumental Test: Better Espresso without sleep,但没有帮助,我得到了相同的行为。 由于UI测试对于CI管道是强制性的,因此如果所有这些测试都能可靠运行,那就太好了。 :)
如果您需要更多代码或信息,请提前告知我!