目前我正在用Espresso实现UI测试/仪器测试,以测试FragmentMovie加载状态和成功状态由于有多个测试库和其他东西,我测试仪器必须包含hilt弹射
UI测试场景:
1.加载状态时,检查我的加载进度条并显示文本加载
1.当处于成功状态时,隐藏正在加载,并显示回收视图
1.已完成
问题
运行测试时跳过Loading state
。@Test
将在ViewModel postValue
Success状态后运行。因此,我无法在加载状态时进行测试。
当我不写onView(withId(R.id.progressBar)).check(matches(isDisplayed()))
时,测试通过,但我想在加载状态时进行测试。
可能的修复方法,将delay(10000)
添加到我的视图模型中,这将延长加载状态的持续时间,但是,我的测试仍处于等待成功状态。
目前我没有使用IdlingResource,因为它不能解决我的问题,
实际场景:
1.片段运行,
1.视图模型提取数据,
1.视图模型加载,
1.查看模型成功,
1.片段测试运行,
- viewAssert失败,
预期值:
1.片段运行,
1.视图模型提取数据,
1.视图模型加载, - FragmentTest检查进度条,
1.查看模型成功,
1.碎片测试检查回收视图,
1.已完成
为什么?怎么做?
代码
片段影片中的观察者
private val viewModel: MovieViewModel by viewModels()
[...]
viewModel.movie.observe(viewLifecycleOwner, {
Log.d(TAG, "viewModelgetMovie: ${it.status}")
when (it.status) {
Status.LOADING -> {
Toast.makeText(requireContext(), "loading..", Toast.LENGTH_SHORT).show()
}
Status.SUCCESS -> {
binding.progressBar.visibility = View.GONE
binding.txLoading.visibility = View.GONE
if (it.data != null) {
list.addAll(it.data)
movieAdapter.notifyDataSetChanged()
}
}
Status.ERROR -> {
binding.progressBar.visibility = View.VISIBLE
binding.txLoading.text = it.message
Toast.makeText(requireContext(), "${it.message}", Toast.LENGTH_SHORT).show()
}
}
})
视图模型
@HiltViewModel
class MovieViewModel @Inject constructor(
private val repository: MovieRepository,
private val dispatcher: CoroutineDispatcher
) : ViewModel() {
// new code
private val moviePost = MutableLiveData<ResourceHelper<ArrayList<MovieData>>>()
val movie: LiveData<ResourceHelper<ArrayList<MovieData>>>
get() = moviePost
init {
fetchMovie()
}
private fun fetchMovie() {
viewModelScope.launch(dispatcher) {
moviePost.postValue(ResourceHelper.loading(null))
repository.getMovie(1).let { movie ->
moviePost.postValue(movie)
}
}
}
}
影片片段测试
package com.unlink.moviecatalogue6.ui.movie
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.unlink.moviecatalogue6.MainActivity
import com.unlink.moviecatalogue6.R
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
@LargeTest
class MovieFragmentTest {
@get:Rule(order = 0)
var hiltRule = HiltAndroidRule(this)
@get:Rule(order = 1)
var activityRule = ActivityScenarioRule(MainActivity::class.java)
@Before
fun setUp() {
hiltRule.inject()
}
@After
fun tearDown() {
}
@Test
fun happyPath() {
onView(withId(R.id.progressBar)).check(matches(isDisplayed())) // error
// how can i test on loading?
onView(withId(R.id.recycleMovie)).check(matches(isDisplayed()))
}
}
错误
androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'is displayed on the screen to the user' doesn't match the selected view.
Expected: is displayed on the screen to the user
Got: "ProgressBar{id=2131231016, res-name=progressBar, visibility=GONE, width=1080, height=44, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=true, is-selected=false, layout-params=androidx.constraintlayout.widget.ConstraintLayout$LayoutParams@a455ee2, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0}"
显示错误是因为我的进度条消失了。因为我的测试检查成功状态后的进度条。
屏幕截图
正在加载状态,但我的测试未运行@Test
loading state
成功状态,然后@测试开始
success state
导致错误视图已消失
error
如有任何答复,我们将不胜感激。
1条答案
按热度按时间qgelzfjb1#
我认为这样做的一个方法是在加载之前在测试中使用testDispatcher暂停调度程序,然后手动恢复它。
请注意,您应该将加载移出视图模型范围。
您可以在此处阅读更多信息:https://developer.android.com/codelabs/advanced-android-kotlin-training-testing-survey#4