코드 커버리지를 보면서 유닛 테스트 작성

대상 독자



Kotlin에서 개발하는 Android 엔지니어

소개



여러분, 단위 테스트를 작성합니까?
코드 커버리지는 어떻습니까?

코드 커버리지란?



소스 코드의 테스트된 비율입니다.
측정 방법이 몇 가지 있습니다만, 이번에는 2개만 소개합니다.

명령 망라(C0)



소스 코드의 각 명령문이 실행 중인지 여부.
fun hoge(x: Int) {
    println("hoge")
    if (x > 0) {
        println("fuga")
    }
}
hoge(x = 1) 그냥 C0:100%

분기망라(C1)



소스 코드의 각 조건이 실행 중인지 여부.
fun hoge(x: Int) {
    println("hoge")
    if (x > 0) {
        println("fuga")
    }
}
hoge(x = 1)hoge(x = 0)에서 C1:100%

코드 커버리지, 뭔가 기뻐요?



유닛 테스트가 충분합니까? 판단 기준 중 하나로 사용할 수 있습니다.
예를 들어 기존 코드의 리팩토링을 생각해 봅시다.

기존 코드


fun hoge(x: Int): String {
    if (x >= 3) return "many"
    if (x == 2) return "two"
    if (x == 1) return "one"
    if (x == 0) return "zero"
    return "other"
}

단위 테스트 작성


@Test
fun hogeTest() {
    assert(hoge(3) == "many")
    assert(hoge(2) == "two")
    assert(hoge(1) == "one")
    assert(hoge(0) == "zero")
}


그렇지만, 이 유닛 테스트로 충분한 것일까···?

그래서 코드 커버리지!

코드 커버리지를 측정하는 방법


  • Android Studio

  • JaCoCo 이번은 이쪽을 소개
  • Other...?

  • JaCoCo 준비



    기본 설정이라면
    Kotlin이 측정 대상이 아닙니다

    arturdm/jacoco-android-gradle-plugin Issue 37JaCoCo 설정을 참고하면 OK

    ※ 상기의 설정은 build variants 도 고려되고 있어 스테키

    커버리지 결과 보기


    $ gradlew jacocoDebugReport 실행 후,
    app/build/reports/jacoco/jacocoDebugReport/html/index.html를 엽니다.

    전체 앱 보고서





    클래스별 보고서





    클래스의 각 함수에 대한 보고서





    소스 코드 레벨 보고서





    녹색: 분기 망라 OK
    황:분기 망라 NG(한쪽의 분기 밖에 실행되지 않는, 등)
    빨간색: 한 번도 실행되지 않음

    테스트 코드를 더한다



    커버리지 보고서를 보면 유닛 테스트에 부족한 것으로 나타났습니다.
    테스트 코드를 추가합시다.
    @Test
    fun hogeTest() {
        assert(hoge(3) == "many")
        assert(hoge(2) == "two")
        assert(hoge(1) == "one")
        assert(hoge(0) == "zero")
        assert(hoge(-1) == "other") // ★追加テストコード
    }
    

    무사, 커버리지 100%





    이제 어느 정도 신뢰할 수 있는 단위 테스트를 할 수 있었습니다.
    그래서 리팩토링도 무섭지 않습니다.

    Kotlin처럼 보자.


    fun hoge(x: Int): String =
        when {
            x >= 3 -> "many"
            x == 2 -> "two"
            x == 1 -> "one"
            x == 0 -> "zero"
            else -> "other"
        }
    



    분기 망라 100% & 유닛 테스트도 다니고 있으므로, 괜찮을 것 같습니다.

    보충


  • 커버리지 100 % 그래서 단위 테스트 완벽, 아니
  • 심지어 판단 기준 중 하나로 사용할 수 있습니다

  • 커버리지 100% 불필요
  • 예를 들어 단위 테스트 작성하기 어려운 부분은 수동으로 확인해도 좋다고 생각합니다

  • 좋은 웹페이지 즐겨찾기