2021.4.14 작성
참고 - https://black-jin0427.tistory.com/111
#0 UI 테스트
단일 앱 내에서 사용자 상호작용을 테스트하면 사용자가 앱과 상호작용할 때 예상치 못한 결과가 발생하거나 불만족스러운 경험을 하지 않도록 할 수 있습니다. 앱의 사용자 인터페이스(UI)가 올바르게 작동하는지 확인해야 한다면 UI 테스트를 만드는 습관을 들여야 합니다.
#1 Espresso를 이용한 UI 테스트 방법
- 먼저 build.gradle에 필요한 라이브러리를 넣습니다.
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
- 에뮬레이터의 애니메이션을 끕니다.
Espresso UI 테스트의 경우 애니메이션을 끄는 것이 가장 좋습니다
- 테스트 기기에서 설정> 개발자 옵션으로 이동합니다 .
- 창 애니메이션 배율 , 전환 애니메이션 배율 및 Animator 기간 배율의 세 가지 설정을 비활성화합니다 .
- src/androidText/java 에 HelloWorldEspressoTest 파일을 생성합니다.
@RunWith(AndroidJUnit4.class)
class HelloWorldEspressoTest {
@Rule
val mActivityRule = ActivityTestRule(MainActivity.class)
@Test
fun listGoesOverTheFold() {
//editText 에 Hello World! 입력하고 키보드를 내립니다.
Espresso.onView(withId(R.id.editText)).perform(typeText("Hello World!"), closeSoftKeyboard());
//textView 의 값이 "Hello World!" 인지 확인합니다.
Espresso.onView(withId(R.id.textView)).check(matches(withText("Hello World!")));
//button 을 클릭합니다.
Espresso.onView(withId(R.id.button)).perform(click());
}
}
#2 Mockito란?
Mockito는 객체를 Mocking하는데 사용되는 Java 기반의 라이브러리입니다. JUnit과 함께 Unit Test를 작성하는데 사용됩니다. Android도 Unit Test를 작성하는데 공식적으로 Mockito를 사용하도록 권장하고 있습니다.
(mocking : 쉽게 말해서 흉내낸다는 것을 의미한다.)
여기서 Mockito를 이용해서 Android Jetpack Navigation을 테스트 해보려 합니다.
#3 Mockito를 이용한 테스트 방법 (Navigation)
- build.gradle에 코드를 추가해줍니다.
// Dependencies for Android instrumented unit tests
androidTestImplementation "org.mockito:mockito-core:$mockitoVersion"
androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito:$dexMakerVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
TaskFragmentTest
파일을 생성해줍니다.
먼저 해당 파일인 TaskFragment
에 들어가서 클래스 이름을 우클릭 후, Generate -> Test를 클릭해서 TaskFragmentTest
파일을 생성해줍니다.
이때 ServiceLocator는 object로 선언한 LocalDatabase입니다.
먼저 ServiceLocator 예제입니다.
object ServiceLocator {
private var database: ToDoDatabase? = null
@Volatile
var tasksRepository: TasksRepository? = null
fun provideTasksRepository(context: Context): TasksRepository {
synchronized(this) {
return tasksRepository ?: createTasksRepository(context)
}
}
private fun createTasksRepository(context: Context): TasksRepository {
val newRepo = DefaultTasksRepository(TasksRemoteDataSource, createTaskLocalDataSource(context))
tasksRepository = newRepo
return newRepo
}
private fun createTaskLocalDataSource(context: Context): TasksDataSource {
val database = database ?: createDataBase(context)
return TasksLocalDataSource(database.taskDao())
}
private fun createDataBase(context: Context): ToDoDatabase {
val result = Room.databaseBuilder(
context.applicationContext,
ToDoDatabase::class.java, "Tasks.db"
).build()
database = result
return result
}
}
그런 다음 테스트를 진행할 Repository와 LocalDatabase를 Set합니다.
@RunWith(AndroidJUnit4::class)
@MediumTest
@ExperimentalCoroutinesApi
class TasksFragmentTest {
private lateinit var repository: TasksRepository
@Before
fun initRepository() {
repository = FakeAndroidTestRepository()
ServiceLocator.tasksRepository = repository
}
@After
fun cleanupDb() = runBlockingTest {
ServiceLocator.resetRepository()
}
}
clickTask_navigateToDetailFragmentOne
테스트 메서드를 만든 뒤 테스트를 진행합니다.
@Test
fun clickTask_navigateToDetailFragmentOne() = runBlockingTest {
repository.saveTask(Task("TITLE1", "DESCRIPTION1", false, "id1"))
repository.saveTask(Task("TITLE2", "DESCRIPTION2", true, "id2"))
// GIVEN - On the home screen
val scenario = launchFragmentInContainer<TasksFragment>(Bundle(), R.style.AppTheme)
val navController = mock(NavController::class.java)
scenario.onFragment {
Navigation.setViewNavController(it.view!!, navController)
}
// WHEN - Click on the first list item
onView(withId(R.id.tasks_list))
.perform(RecyclerViewActions.actionOnItem<RecyclerView.ViewHolder>(
hasDescendant(withText("TITLE1")), click()))
// THEN - Verify that we navigate to the first detail screen
verify(navController).navigate(
TasksFragmentDirections.actionTasksFragmentToTaskDetailFragment( "id1")
)
}
'IT > Android (안드로이드)' 카테고리의 다른 글
Android N.4-6 Implementing Login on Android with FirebaseUI (0) | 2025.04.21 |
---|---|
Android N.4-5 Testing: Survey of Advanced Topics (0) | 2025.04.21 |
Android N.4-3 Testing: Basics (0) | 2025.04.21 |
Android N.4-2 Virtual Treasure Hunt with Geofences (0) | 2025.04.21 |
Android N.4-1 Wandering in Google maps with Kotlin (0) | 2025.04.21 |