[JUnit] Bad Test

반응형

이번글에서는 prime number 예제를 통해 좋은 test code를 작성하는 방법에 대해 알아보도록 하겠습니다.

1. Check Prime Number

먼저 아래와 같이 Prime Number 인지 아닌지를 확인하는 NumberValidator 클래스가 있다고 가정해보겠습니다.

NumberValidator

public class NumberValidator {
    public boolean isItPrime(int number) {
        int maxDivisor = (int)Math.sqrt(number);
        for(int i=2;i<=maxDivisor;i++) {
            if(number % i==0)
                return false;
        }
        return true;
    }
}

위의 isItPrime 메서드는 input number를 적절히 계산해 prime number 일 경우 true를 그렇지 않을 경우에는 false를 return 하도록 설계되었습니다.

위의 business logic을 테스트하는 test code는 아래와 같습니다.

NumberValidatorTests

public class NumberValidatorTests {

    @Test
    public void checkPrimeNumber(){

        Integer numbers[] = {1, 15, 23, 25, 60, 61, 63, 79, 207};
        NumberValidator validator = new NumberValidator();

        for(int i=0; i< numbers.length; i++){
            boolean isPrime = true;
            int maxDivisor = (int) Math.sqrt(numbers[i]);
            for(int counter = 2; counter <= maxDivisor; counter++){
                if(numbers[i] % counter ==0){
                    isPrime = false;
                }
            }

            assertEquals(isPrime, validator.isItPrime(numbers[i]));
        }
    }
}

위의 test code는 먼저 numbers 배열에 담긴 숫자들 중 prime number인 숫자들과 prime number가 아닌 숫자들을 구분합니다.

다음으로 prime number인 숫자를 isItPrime 메서드에 넣었을때 결과값으로 true를 return 하는지와 prime number가 아닌 숫자를 isItPrime 메서드에 넣었을때 결과값으로 false를 return 하는지를 test 합니다.

테스트 해보겠습니다.

image.png

짠 😎~ 위와 같이 test가 통과했습니다.

만약 뭔가 이상한걸 눈치채셨다면, 이미 당신은 고수.. 입니다.

그렇습니다. 위의 test code는 뭔가 이상합니다. 다시한번 아래의 빨간색 부분을 살펴보겠습니다.

image.pngimage.png

눈치 채셨나요? 맞습니다. 현재 위에서 작성한 test code는 지나치게 business logic을 반복하고 있습니다. 따라서 위의 test를 수행할 경우 동일한 logic을 2번 수행하는 것과 다름없는 것 입니다.

따라서 위와 같은 bad test를 refactoring 할 필요가 있습니다.

2. Refactoring

test code에서는 위와 같은 logic을 수행할 필요가 전혀 없습니다. 단지 우리는 어떠한 값을 던져 주었을때, 원하는 결과값을 return 하는가? 만 정적으로 확인해보면 됩니다. 따라서 우리는 다음과 같이 test code를 변경할 수 있습니다.

NumberValidatorTests

public class NumberValidatorTests {

    @Test
    public void checkPrimeNumbers()
    {
        Integer numbers[] = {1,23,61,79};
        NumberValidator validator = new NumberValidator();

        for (int i = 0; i < numbers.length; i++) {
            assertEquals(true, validator.isItPrime(numbers[i]));
        }
    }

    @Test
    public void checkNonPrimeNumbers()
    {
        Integer numbers[] = {15,25,60,63,207};
        NumberValidator validator = new NumberValidator();

        for (int i = 0; i < numbers.length; i++) {
            assertEquals(false, validator.isItPrime(numbers[i]));
        }
    }
}

기존 1개의 test가 2개의 test로 분리되었습니다.

해석해보면 checkPrimeNumbers는 prime number를 isItPrime 메서드의 input으로 넣을 경우 true 값을 return 하는지 확인합니다. 반대로 checkNonPrimeNumbers는 non prime number를 isItPrime 메서드의 input으로 넣을 경우 false를 return 하는지 확인합니다.

테스트 해보겠습니다.

image.png

위와 같이 테스트가 통과했습니다. 이로써 우리는 더이상 test code 내부에서 business logic을 작성하지 않게 되었습니다. 👏👏👏


참고 자료 : https://www.udemy.com/course/practical-test-driven-development-for-java-programmers/


추천서적

 

자바와 JUnit을 활용한 실용주의 단위 테스트

COUPANG

www.coupang.com

파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음


반응형

'JUnit' 카테고리의 다른 글

[JUnit] MockMvc  (0) 2020.08.20
[JUnit] Spy  (0) 2020.08.20
[JUnit] Mock & Mockito -2  (0) 2020.08.20
[JUnit] Mock & Mockito -1  (0) 2020.08.20
[JUnit] Stub  (0) 2020.08.20

댓글

Designed by JB FACTORY