Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usecase 들 UnitTest #346

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open

Usecase 들 UnitTest #346

wants to merge 8 commits into from

Conversation

2taezeat
Copy link
Collaborator

@2taezeat 2taezeat commented Dec 14, 2023

Issue

Overview

  • Kotest, mockk 사용
  • throttleFirst UnitTest
  • AutomaticallyLoginUseCase UnitTest
  • GetPlaylistUseCase UnitTest
  • GetPlaylistsUseCase UnitTest

@2taezeat 2taezeat added 🔎 test Testing 🤖 android android labels Dec 14, 2023
@2taezeat 2taezeat added this to the 🔧 etc milestone Dec 14, 2023
@2taezeat 2taezeat self-assigned this Dec 14, 2023
@2taezeat 2taezeat changed the title Android/test/343 Domain UnitTest Dec 14, 2023
@2taezeat 2taezeat linked an issue Dec 14, 2023 that may be closed by this pull request
Copy link

github-actions bot commented Dec 14, 2023

Test Results

14 tests   14 ✔️  1s ⏱️
  6 suites    0 💤
  6 files      0

Results for commit 9edfcab.

♻️ This comment has been updated with latest results.

@2taezeat 2taezeat changed the title Domain UnitTest Usecase 들 UnitTest Dec 14, 2023
Comment on lines +11 to +23
fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> {
var job: Job = Job().apply { complete() }

return onCompletion { job.cancel() }.run {
flow {
coroutineScope {
collect { value ->
if (!job.isActive) {
emit(value)
job = launch { delay(windowDuration) }
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

바뀐 코드가 의도를 이해하기 어려운 것 같아.
테스트 코드 때문이라면, 테스트를 작성하기 위해 기존보다 어려운 코드를 작성하는 게 옳은 일인지 생각해봐야 할 것 같아.


`when`("windowDuration 을 400 만큼 주면") {
val result = mutableListOf<Int>()
runTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runTest를 사용한 이유가 무엇일까?

val result = mutableListOf<Int>()
runTest {
testFlow.throttleFirst(400)
.onEach { result.add(it) }
Copy link
Member

@HamBP HamBP Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testFlow가 cold flow라 List로 변환하는 방법으로도 테스트할 수 있을 것 같아

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비즈니스 로직에 대한 테스트의 given, when, then은 비개발자도 이해할 수 있게 작성하면 좋을 것 같아.
"accessToken가 존재한다", "true를 반환한다"를 비즈니스 로직에 가까운 말로 바꾸면, 로그인 기록이 존재한다, 자동 로그인에 성공한다와 같이 변경할 수 있지 않을까?

Comment on lines +29 to +36
`when`("accessToken이 존재 한다면") {
val validToken = "Bearer ~~"
coEvery { userTokenRepository.getAccessToken() } returns validToken
coEvery { authRepository.verifyToken(validToken) } returns true
val result = automaticallyLoginUseCase.invoke()

then("true 를 반환 한다") { result shouldBe true }
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accessToken이 존재하면 유효하지 않은 토큰이라도 로그인에 성공하는 걸까?

Comment on lines +14 to +37
given("GetPlaylistUsecase 를 호출 하는 상황에서") {
val playlistRepository: PlaylistRepository = mockk()
val getPlaylistUseCase = GetPlaylistUseCase(playlistRepository)
val dummyRecentPlaylist = listOf(
Music(
id = "odio",
title = "dis",
artist = "epicurei",
imageUrl = "https://duckduckgo.com/?q=dolorum",
musicUrl = "https://search.yahoo.com/search?p=volutpat"
)
)

val dummyNormalPlaylist = listOf(
Music(
id = "feugiat",
title = "fabellas",
artist = "adolescens",
imageUrl = "https://www.google.com/#q=sollicitudin",
musicUrl = "http://www.bing.com/search?q=invenire"
)
)

`when`("playlistId이 RECENT_PLAYLIST_ID 이라면") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given과 when이 바뀐 것 같아. given, when, then은 AAA패턴과 거의 유사해.
given(arrange) : 무엇이 주어졌을 때
when(act) : 어떤 행동을 하면
then(assert) : 결과
지금은 given에서 행동을 정의하고, when에서 값을 주는 거 같아

emit(dummyNormalPlaylist)
}
val result = getPlaylistUseCase.invoke(playlistId = testPlaylistId).first()
then("getPlaylist 를 호출 한다") { result shouldBe dummyNormalPlaylist }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"getPlaylist를 호출한다"

  1. 화이트 박스 테스트임을 암시하고 있어. 블랙 박스 테스트로는 불가능할까?
  2. 설명하는 내용은 함수의 호출인데, 실제로는 반환값을 검증하고 있어.

)

then("recentMusics 들로 새로운 Playlist를 만들고 합치고, id로 정렬한 새로운 Playlist를 반환한다.") {
result.first() shouldBe excepted
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excepted -> expected 오타인 거 같아

Comment on lines +49 to +61
`when`("playlistId이 RECENT_PLAYLIST_ID 이라면") {
every { playlistRepository.getPlaylists() } returns flow { emit(dummyPlaylists) }
every { playlistRepository.getRecentPlaylist() } returns flow { emit(dummyRecentMusics) }
val result = getPlaylistsUseCase.invoke().first()
val excepted = Playlist(
id = RECENT_PLAYLIST_ID,
title = "최근 재생 목록",
thumbnailUrl = "https://duckduckgo.com/?q=dolorum",
trackSize = 2,
)

then("recentMusics 들로 새로운 Playlist를 만들고 합치고, id로 정렬한 새로운 Playlist를 반환한다.") {
result.first() shouldBe excepted
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재생 목록과 다른 재생목록들을 합쳐서 반환하는지를 검증하고 싶은 것 같은데, 최근 재생 목록을 검증하는 이유가 있을까?

Copy link
Member

@HamBP HamBP left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 사용자 관점에서 비즈니스 로직을 테스트한다기보다 코드가 동작하는지 테스트한다는 느낌이 드는 거 같아. 사용자 관점에서 로직을 검증하면 더 좋을 것 같아.

그리고 가능하다면 블랙박스 테스트로 작성하는 게 좋아. 지금 코드는 UseCase 내부 구현을 꼼꼼히 확인하고 작성한 거 같아.

@2taezeat
Copy link
Collaborator Author

좋은 의견 감사합니다~! 좀 더 개선해보겠습니다~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Usecase 들 UnitTest
2 participants