안드로이드 스튜디오

안드로이드 할 줄 몰라도 Ai로 개발부터 배포까지 가능할까 7 - 단위 테스트

yangcotton 2026. 3. 31. 14:51

이제 배포까지도 정말 얼마 남지 않았다.
기존 순서를 보자면 

1 아이디어 기획
2 요구사항 정의
3 기능 리스트 작성
4 와이어프레임
5 화면 정의서
6 아키텍처 설계
7 DB / API 설계
8 프로젝트 타임라인
9 개발 (Data → Domain → UI)
--- 여기까지 완료해서 GitHub에 올렸다 ! ---
10 단위 테스트
11 통합 테스트
12 버그 수정
13 배포

오늘은 단위테스트를 해볼 예정이다.

안드로이드 스튜디오를 이용하면 단위, 통합 테스트를 손 쉽게 할 수 가 있다!
https://developer.android.com/studio/test/test-in-android-studio?hl=ko

파일은 ~~Utils.kt로 따로 만들어주는게 좋다! 
파일 위치도 따로 만들어주면 관리하기 더 용이해진다.
app/
 └── src/
      ├── main/
      │    └── java/com/example/mgcs/
      │         └── util/   👈 여기
      │              └── ScoreUtils.kt
      │
      ├── test/            👈 단위 테스트
      └── androidTest/     👈 통합 테스트

ScoreUtils는 실제 앱에서 사용하는 코드

점수 계산
상태 판정

→ 앱에서도 쓰고
→ 테스트에서도 검증함

즉,

“테스트 대상 코드” = main에 있어야 함

왜 util로 빼는게 중요하냐!!

// MainActivity 안에 있음
fun calculateTotal(...) { ... }

→  테스트하기 어려움 (Activity 의존)

// ~~Utils.kt로 따로 만들어준다면
object ScoreUtils {
    fun calculateTotal(...) { ... }
}


→ 어디서든 사용 가능
→ 테스트도 바로 가능

ScoreUtils.kt : Score 계산 + 상태 판정

더보기

object ScoreUtils {

    fun calculateTotal(motor: Int, brainstem: Int, consciousness: Int): Int {
        return motor + brainstem + consciousness
    }

    fun getStatus(total: Int): String {
        return when (total) {
            in 3..8 -> "Grave"
            in 9..14 -> "Guarded"
            else -> "Good"
        }
    }
}

ScoreUtilsTest.kt :

더보기

import org.junit.Assert.assertEquals
import org.junit.Test

class ScoreUtilsTest {

    @Test
    fun `total score 계산 테스트`() {
        val result = ScoreUtils.calculateTotal(6, 6, 6)
        assertEquals(18, result)
    }

    @Test
    fun `Grave 판정 테스트`() {
        val result = ScoreUtils.getStatus(5)
        assertEquals("Grave", result)
    }

    @Test
    fun `Guarded 판정 테스트`() {
        val result = ScoreUtils.getStatus(10)
        assertEquals("Guarded", result)
    }

    @Test
    fun `Good 판정 테스트`() {
        val result = ScoreUtils.getStatus(18)
        assertEquals("Good", result)
    }


이런식으로 소스 개발 후 test 파일에서 우클릭 후 Run을 하면 테스트가 진행되는데

Test값을 잘못넣을 경우 fail이 떨어진다.

 

정상적으로 Test할 경우!

더보기

Executing tasks: [:app:testDebugUnitTest] in project C:\*******\AndroidStudioProjects\MGCS


> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:dataBindingMergeDependencyArtifactsDebug UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:packageDebugResources UP-TO-DATE
> Task :app:processDebugNavigationResources UP-TO-DATE
> Task :app:parseDebugLocalResources UP-TO-DATE
> Task :app:dataBindingGenBaseClassesDebug UP-TO-DATE
> Task :app:generateDebugRFile UP-TO-DATE
> Task :app:compileDebugKotlin UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:mapDebugSourceSetPaths UP-TO-DATE
> Task :app:compileDebugNavigationResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:bundleDebugClassesToRuntimeJar UP-TO-DATE
> Task :app:bundleDebugClassesToCompileJar UP-TO-DATE
> Task :app:preDebugUnitTestBuild UP-TO-DATE
> Task :app:javaPreCompileDebugUnitTest UP-TO-DATE
> Task :app:processDebugJavaRes UP-TO-DATE
> Task :app:compileDebugUnitTestKotlin
> Task :app:compileDebugUnitTestJavaWithJavac NO-SOURCE
> Task :app:processDebugUnitTestJavaRes UP-TO-DATE
> Task :app:testDebugUnitTest
BUILD SUCCESSFUL in 7s
27 actionable tasks: 2 executed, 25 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.3.1/userguide/configuration_cache_enabling.html

Build Analyzer results available
오후 4:08:45: Execution finished ':app:testDebugUnitTest'.

가장 중요한 JSON 저장 ! TEST

더보기

데이터 없어도 앱 정상 동작해야 함

@Test
fun `빈 JSON 테스트`() {

    val json = "[]"

    val type = object : TypeToken<List<MgcsRecord>>() {}.type
    val result: List<MgcsRecord> = Gson().fromJson(json, type)

    assertEquals(0, result.size)
}

정상보다 더 중요한 예외테스트!!!

더보기

@Test
fun `잘못된 JSON 테스트`() {

    val json = ""   // 완전 잘못된 데이터

    try {
        val type = object : TypeToken<List<MgcsRecord>>() {}.type
        Gson().fromJson<List<MgcsRecord>>(json, type)

    } catch (e: Exception) {
        assert(true) // 예외 발생하면 성공
    }
}

Executing tasks: [:app:testDebugUnitTest] in project C:\Users\HeeBean\AndroidStudioProjects\MGCS


> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:dataBindingMergeDependencyArtifactsDebug UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:packageDebugResources UP-TO-DATE
> Task :app:processDebugNavigationResources UP-TO-DATE
> Task :app:parseDebugLocalResources UP-TO-DATE
> Task :app:dataBindingGenBaseClassesDebug UP-TO-DATE
> Task :app:generateDebugRFile UP-TO-DATE
> Task :app:compileDebugKotlin UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:checkDebugAarMetadata UP-TO-DATE
> Task :app:mapDebugSourceSetPaths UP-TO-DATE
> Task :app:compileDebugNavigationResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugMainManifest UP-TO-DATE
> Task :app:processDebugManifest UP-TO-DATE
> Task :app:processDebugManifestForPackage UP-TO-DATE
> Task :app:processDebugResources UP-TO-DATE
> Task :app:bundleDebugClassesToRuntimeJar UP-TO-DATE
> Task :app:bundleDebugClassesToCompileJar UP-TO-DATE
> Task :app:preDebugUnitTestBuild UP-TO-DATE
> Task :app:javaPreCompileDebugUnitTest UP-TO-DATE
> Task :app:processDebugJavaRes UP-TO-DATE
> Task :app:compileDebugUnitTestKotlin
> Task :app:compileDebugUnitTestJavaWithJavac NO-SOURCE
> Task :app:processDebugUnitTestJavaRes UP-TO-DATE
> Task :app:testDebugUnitTest
BUILD SUCCESSFUL in 5s
27 actionable tasks: 2 executed, 25 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.3.1/userguide/configuration_cache_enabling.html

Build Analyzer results available
오후 3:15:30: Execution finished ':app:testDebugUnitTest'.

단위 테스트 커버 범위:
✅ 점수 계산
✅ 상태 판정
✅ JSON 파싱
✅ 차트 필터링
✅ Activity 실행
✅ RecyclerView 클릭


다음 게시물은 통합테스트로 돌아오겠다.

 

통합 테스트 커버 범위:

 □ 데이터 없을 때 크래시 없음
 □ chartType null 처리
 □ JSON 깨져도 앱 안죽음
 □ 화면 회전 시 데이터 유지
 □ GraphActivity index 오류 없음
 □ 리스트 ↔ 그래프 sync 오류 없음