Developing Myself Everyday

 

사용자의 관점에서 애플리케이션 외부적으로 제대로 작동하는지 확인하는 것이 목표인 테스트는 개발자에게 유용하지만 충분하지는 않습니다.

 

이것만으로는 해당 요소가 올바르게 작동한다는 것을 완전하게 보증할 수는 없습니다. 그렇기 때문에 단위 테스트(Unit Test)가 필요합니다.

 

 

확인할 내용


단위 테스트는 일반적으로 다음과 같은 내용을 확인합니다.

 

1. 일반적인 유스케이스

이는 사용될 것이라고 예상되는 정상적인 입력 값에 대해 프로그램이 의도한 대로 작동하는지 확인하는 경우입니다.

fun get(list: List<Int>, index: Int): Int {
    return list[index]
}

@Test
fun `인덱스의 해당하는 값을 가져올 수 있어야 한다`() {
    val numbers = listOf(1, 2, 3, 4, 5)

    val element = get(numbers, 2)

    assertEquals(3, element)  // index 2의 값은 3
}

 

 

2. 일반적인 오류 케이스와 잠재적인 문제

제대로 동작하지 않을 것이라 예상되는 부분과, 문제가 발생했던 부분을 테스트합니다.

fun get(list: List<Int>, index: Int): Int {
    return list[index]
}

@Test
fun `유효하지 않은 인덱스에 접근하면 예외가 발생해야 한다`() {
    val numbers = listOf(1, 2, 3, 4, 5)

    // 유효하지 않은 인덱스(예: 인덱스 10)는 예외를 발생시켜야 한다.
    assertThrows(IndexOutOfBoundsException::class.java) {
        get(numbers, 10)  // 범위 밖의 인덱스
    }
}

@Test
fun `빈 리스트에서 값을 가져오려 할 때 예외가 발생해야 한다`() {
    val emptyList = emptyList<Int>()

    assertThrows(IndexOutOfBoundsException::class.java) {
        get(emptyList, 0)  // 빈 리스트에서 인덱스 0을 접근하면 예외 발생
    }
}

 


3. Edge 케이스와 잘못된 아규먼트

Edge 케이스는 주로 극단적인 매개변수로 발생하는 상황에 시스템이 정상적으로 동작하는지 확인합니다.

fun stringToInt(str: String): Int {
    return str.toInt()
}

@Test
fun `범위를 벗어난 값을 변환하면 예외가 발생해야 한다`() {
    // Int의 최대값을 넘어서는 문자열을 테스트
    val overflowString = "2147483648"  // Int.MAX_VALUE + 1
    
    assertThrows(NumberFormatException::class.java) {
        stringToInt(overflowString)  // 범위 초과
    }
}

 

 

단위 테스트의 장점


단위 테스트는 개발자가 만들고 있는 요소가 제대로 동작하는지를 빠르게 피드백해 주므로 개발하는 동안에 큰 도움이 됩니다. 그리고 아래와 같은 장점이 있습니다.

  1. 테스트가 잘 된 코드는 신뢰할 수 있습니다.
  2. 리팩터링이 두렵지 않게 됩니다.
  3. 수동으로 테스트하는 것보다 단위 테스트로 확인하는 것이 빠릅니다.

 

 

단위 테스트의 단점


다만 아래와 같은 단점도 존재합니다.

  1. 단위 테스트를 만들어야 하므로 시간이 걸립니다.
  2. 테스트를 활용할 수 있게 코드를 만들어야 합니다.
  3. 좋은 단위 테스트를 만드는 것이 어렵습니다.
profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!