Skip to content

Commit 21a487b

Browse files
authored
Merge pull request #38 from min486/feature/unit-test
feat: Unit test 적용
2 parents 2d4adb3 + 780d490 commit 21a487b

File tree

12 files changed

+651
-63
lines changed

12 files changed

+651
-63
lines changed

.github/workflows/ci_build.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ jobs:
4242
echo "naver.client.id=$NAVER_CLIENT_ID" >> local.properties
4343
echo "naver.client.secret=$NAVER_CLIENT_SECRET" >> local.properties
4444
45+
# Unit Test 실행
46+
- name: Run Unit Tests
47+
run: ./gradlew testDebugUnitTest
48+
49+
# 테스트 결과 저장
50+
- name: Upload Test Results
51+
if: always()
52+
uses: actions/upload-artifact@v4
53+
with:
54+
name: test-results
55+
path: app/build/reports/tests/testDebugUnitTest
56+
retention-days: 7
57+
4558
- name: Build Debug APK
4659
run: ./gradlew assembleDebug # 디버그 APK 빌드 명령어 실행
4760

app/build.gradle.kts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,20 @@ dependencies {
134134
implementation(libs.lottie.compose)
135135
// preferences datastore
136136
implementation(libs.datastore.preferences)
137+
// coroutines
138+
implementation(libs.coroutines.core)
139+
implementation(libs.coroutines.android)
140+
141+
// Unit Test
142+
testImplementation(libs.kotest.runner)
143+
testImplementation(libs.kotest.assertion)
144+
testImplementation(libs.mockk)
145+
testImplementation(libs.kotlinx.coroutines.test)
137146

138-
testImplementation(libs.junit)
139-
androidTestImplementation(libs.androidx.junit)
140-
androidTestImplementation(libs.androidx.espresso.core)
141-
androidTestImplementation(libs.androidx.ui.test.junit4)
142147
debugImplementation(libs.androidx.ui.tooling)
143-
debugImplementation(libs.androidx.ui.test.manifest)
148+
}
149+
150+
// Kotest 사용을 위한 JUnit5 설정
151+
tasks.withType<Test> {
152+
useJUnitPlatform()
144153
}

app/src/main/java/com/min/dnapp/data/repository/LocalSearchRepositoryImpl.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.min.dnapp.data.repository
22

3-
import android.net.http.HttpEngine
4-
import android.util.Log
53
import com.min.dnapp.data.remote.LocalSearchResponse
64
import com.min.dnapp.data.remote.LocalSearchService
75
import com.min.dnapp.domain.model.LocalPlace
@@ -21,7 +19,7 @@ class LocalSearchRepositoryImpl @Inject constructor(
2119
) : LocalSearchRepository {
2220
override fun searchPlaces(query: String): Flow<Resource<List<LocalPlace>>> = flow {
2321
// 로딩 상태 방출
24-
emit(Resource.Loading())
22+
emit(Resource.Loading)
2523

2624
try {
2725
val response: LocalSearchResponse = api.search(

app/src/main/java/com/min/dnapp/presentation/find/FindViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class FindViewModel @Inject constructor(
3131
// 공유된 기록 목록 가져오기
3232
try {
3333
val sharedRecords = getSharedRecordUseCase()
34-
Log.d("record", "loaFindData - sharedRecords: $sharedRecords")
34+
// Log.d("record", "loaFindData - sharedRecords: $sharedRecords")
3535
val successState = FindUiState.Success(
3636
records = sharedRecords
3737
)
@@ -40,7 +40,7 @@ class FindViewModel @Inject constructor(
4040
_uiState.value = FindUiState.Success(
4141
records = emptyList()
4242
)
43-
Log.e("record", "기록 목록 조회 실패", e)
43+
// Log.e("record", "기록 목록 조회 실패", e)
4444
}
4545
}
4646
}

app/src/main/java/com/min/dnapp/presentation/home/HomeViewModel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class HomeViewModel @Inject constructor(
4545
val successState: HomeUiState.Success
4646
try {
4747
val user = getUserDataUseCase(uid)
48-
Log.d("home", "loadHomeData - user: $user")
48+
// Log.d("home", "loadHomeData - user: $user")
4949

5050
successState = mapUserToHomeUiState(user)
5151

@@ -58,7 +58,7 @@ class HomeViewModel @Inject constructor(
5858
// 여행기록 정보 로드 및 상태 업데이트
5959
try {
6060
val userRecords = getUserRecordUseCase()
61-
Log.d("home", "loadHomeData - userRecords: $userRecords")
61+
// Log.d("home", "loadHomeData - userRecords: $userRecords")
6262
val finalSuccessState = successState.copy(
6363
records = userRecords
6464
)
@@ -67,7 +67,7 @@ class HomeViewModel @Inject constructor(
6767
_uiState.value = successState.copy(
6868
records = emptyList()
6969
)
70-
Log.e("home", "기록 정보 로드 실패", e)
70+
// Log.e("home", "기록 정보 로드 실패", e)
7171
}
7272
}
7373
}

app/src/main/java/com/min/dnapp/presentation/write/RecordWriteViewModel.kt

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class RecordWriteViewModel @Inject constructor(
4242
private val _completeSaveRecord = Channel<Unit>()
4343
val completeSaveRecordFlow = _completeSaveRecord.receiveAsFlow()
4444

45-
private val _snackbarMessage = MutableSharedFlow<SnackbarMessage>()
45+
// 최근에 발행된 메시지 1개 저장
46+
private val _snackbarMessage = MutableSharedFlow<SnackbarMessage>(replay = 1)
4647
val snackbarMessage = _snackbarMessage.asSharedFlow()
4748

4849
// 이전 검색 작업을 취소하기 위한 Job
@@ -57,15 +58,15 @@ class RecordWriteViewModel @Inject constructor(
5758
*/
5859
fun updateTitle(newText: String) {
5960
_uiState.value = _uiState.value.copy(recordTitle = newText)
60-
Log.d("write", "updateTitle - newText : $newText")
61+
// Log.d("write", "updateTitle - newText : $newText")
6162
}
6263

6364
/**
6465
* 내용 - textField의 입력 값 업데이트
6566
*/
6667
fun updateContent(newText: String) {
6768
_uiState.value = _uiState.value.copy(recordContent = newText)
68-
Log.d("write", "updateContent - newText : $newText")
69+
// Log.d("write", "updateContent - newText : $newText")
6970
}
7071

7172
/**
@@ -83,15 +84,15 @@ class RecordWriteViewModel @Inject constructor(
8384
*/
8485
fun updateEmotion(emotionType: EmotionType) {
8586
_uiState.value = _uiState.value.copy(selectedEmotion = emotionType)
86-
Log.d("write", "selectEmotion - emotionType : $emotionType")
87+
// Log.d("write", "selectEmotion - emotionType : $emotionType")
8788
}
8889

8990
/**
9091
* 선택된 날씨 업데이트
9192
*/
9293
fun updateWeather(weatherType: WeatherType) {
9394
_uiState.value = _uiState.value.copy(selectedWeather = weatherType)
94-
Log.d("write", "selectWeather - weatherType : $weatherType")
95+
// Log.d("write", "selectWeather - weatherType : $weatherType")
9596
}
9697

9798
/**
@@ -104,7 +105,7 @@ class RecordWriteViewModel @Inject constructor(
104105
if (newQuery.isBlank()) {
105106
// 진행중인 검색 작업 취소
106107
searchJob?.cancel()
107-
Log.d("naver", "updateQuery - newQuery blank")
108+
// Log.d("naver", "updateQuery - newQuery blank")
108109
}
109110
}
110111

@@ -116,7 +117,7 @@ class RecordWriteViewModel @Inject constructor(
116117

117118
// 검색어가 빈 경우
118119
if (currentQuery.isBlank()) {
119-
Log.d("naver", "searchPlace - newQuery blank")
120+
// Log.d("naver", "searchPlace - newQuery blank")
120121
return
121122
}
122123

@@ -131,28 +132,28 @@ class RecordWriteViewModel @Inject constructor(
131132
// 로딩 시작
132133
_uiState.value = _uiState.value.copy(searchState = _uiState.value.searchState.copy(
133134
isLoading = true,
134-
places = result.data ?: emptyList(),
135+
places = emptyList(),
135136
error = null
136137
))
137-
Log.d("naver", "search for $currentQuery : Loading...")
138+
// Log.d("naver", "search for $currentQuery : Loading...")
138139
}
139140
is Resource.Success -> {
140141
// 성공
141142
_uiState.value = _uiState.value.copy(searchState = _uiState.value.searchState.copy(
142143
isLoading = false,
143-
places = result.data ?: emptyList(),
144+
places = result.data,
144145
error = null
145146
))
146-
Log.d("naver", "search success : ${result.data?.size}")
147+
// Log.d("naver", "search success : ${result.data?.size} 개")
147148
}
148149
is Resource.Error -> {
149150
// 에러
150151
_uiState.value = _uiState.value.copy(searchState = _uiState.value.searchState.copy(
151152
isLoading = false,
152-
places = result.data ?: emptyList(),
153-
error = result.message ?: "알 수 없는 에러 발생"
153+
places = emptyList(),
154+
error = result.message
154155
))
155-
Log.e("naver", "search error : ${result.message}")
156+
// Log.e("naver", "search error : ${result.message}")
156157
}
157158
}
158159
}
@@ -173,7 +174,7 @@ class RecordWriteViewModel @Inject constructor(
173174
places = emptyList(),
174175
error = null
175176
))
176-
Log.d("naver", "result cleared")
177+
// Log.d("naver", "result cleared")
177178
}
178179

179180
/**
@@ -188,15 +189,15 @@ class RecordWriteViewModel @Inject constructor(
188189
*/
189190
fun updateOverseas(newText: String) {
190191
_uiState.value = _uiState.value.copy(overseasPlace = newText)
191-
Log.d("write", "updateOverseas - newText : $newText")
192+
// Log.d("write", "updateOverseas - newText : $newText")
192193
}
193194

194195
/**
195196
* 공유여부 설정 상태 업데이트
196197
*/
197198
fun updateShare(newChecked: Boolean) {
198199
_uiState.value = _uiState.value.copy(isShareChecked = newChecked)
199-
Log.d("write", "updateShare - newChecked : $newChecked")
200+
// Log.d("write", "updateShare - newChecked : $newChecked")
200201
}
201202

202203
/**
@@ -218,7 +219,7 @@ class RecordWriteViewModel @Inject constructor(
218219
*/
219220
fun onPhotoSelected(uri: Uri?) {
220221
_uiState.value = _uiState.value.copy(selectedImageUri = uri)
221-
Log.d("write", "onPhotoSelected - uri : $uri")
222+
// Log.d("write", "onPhotoSelected - uri : $uri")
222223
}
223224

224225
/**
@@ -249,7 +250,7 @@ class RecordWriteViewModel @Inject constructor(
249250
_completeSaveRecord.send(Unit)
250251
}.onFailure { exception ->
251252
// 저장 실패
252-
Log.e("write", "saveRecord - exception : $exception")
253+
// Log.e("write", "saveRecord - exception : $exception")
253254
}
254255

255256
_uiState.update { it.copy(isSaving = false) }
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.min.dnapp.util
22

3-
sealed class Resource<T>(val data: T? = null, val message: String? = null) {
4-
class Success<T>(data: T) : Resource<T>(data)
5-
class Error<T>(message: String, data: T? = null) : Resource<T>(data, message)
6-
class Loading<T>(data: T? = null) : Resource<T>(data)
7-
}
3+
sealed class Resource<out T> {
4+
data class Success<out T>(val data: T) : Resource<T>()
5+
data class Error(val message: String) : Resource<Nothing>()
6+
data object Loading : Resource<Nothing>()
7+
}

app/src/test/java/com/min/dnapp/ExampleUnitTest.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)