JUnit, TDD , 클린코드 연습

문자열 계산기

쭈녁 2023. 2. 9. 18:52

요구사항

  • 사용자가 입력한 문자열 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현해야 한다.
  • 문자열 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다. 즉, 수학에서는 곱셈, 나눗셈이 덧셈, 뺄셈 보다 먼저 계산해야 하지만 이를 무시한다.
  • 예를 들어 "2 + 3 * 4 / 2"와 같은 문자열을 입력할 경우 2 + 3 * 4 / 2 실행 결과인 10을 출력해야 한다.

 

최초 코드 작성

public class StringCalculator {
    @Test
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] split = scanner.nextLine().split(" ");
        int length = split.length;
        int[] numArr = new int[(length / 2)+1];
        String[] strArr = new String[length / 2];

        for (int i = 0; i <length ; i++) {
            if (i % 2 == 0) {
                numArr[i/2]=Integer.parseInt(split[i]);
            }
            if(i%2==1){
                strArr[i / 2] = split[i];
            }
        }
        int sum = numArr[0];
        for (int i = 0; i < length / 2; i++) {
            if (strArr[i].equals("+")) {
                sum = sum + numArr[i + 1];
                System.out.println("sum = " + sum);
            }
            if (strArr[i].equals("-")) {
                sum = sum - numArr[i + 1];
                System.out.println("sum = " + sum);
            }
            if (strArr[i].equals("*")) {
                sum = sum * numArr[i + 1];
                System.out.println("sum = " + sum);
            }
            if (strArr[i].equals("/")) {
                sum = sum / numArr[i + 1];
                System.out.println("sum = " + sum);
            }
        }
        assertThat(calculator).isEqualTo(10);
    }

단위 테스트를 활용하기 위함이 아닌 요구사항에 맞는 결과값을 도출하기 위한 지저분한 코딩 결과가 나왔다.

이를 개선하기 위하여 각 기능을 메서드화 하고 각 기능을 단위별로 테스트 하도록 리펙토링하였다. 리펙토링 결과는 아래와 같다.

 

단위 테스트를 위한 메서드화(기능 구현)

public class StringCalculator {

    //문자열에서 숫자 뽑아내기
    public static int[] splitNum(String str) {
        String[] split = str.split(" ");
        int[] result = new int[(split.length / 2) + 1];
        for (int i = 0; i < split.length; i = i + 2) {
            result[i / 2] = Integer.parseInt(split[i]);
        }
        return result;
    }

    //문자열에서 연산 기호 뽑아내기
    public static String[] splitString(String str) {
        String[] split = str.split(" ");
        String[] result = new String[split.length / 2];
        for (int i = 1; i < split.length; i = i + 2) {
            result[i / 2] = split[i];
        }
        return result;
    }

    //순서대로 연산하기
    public static int calculator(String str) {
        int[] splitNum = splitNum(str);
        String[] splitString = splitString(str);
        int sum = splitNum[0];
        for (int i = 0; i < splitString.length; i++) {
            switch (splitString[i]) {
                case "+":
                    sum = sum + splitNum[i + 1];
                    break;
                case "-":
                    sum = sum - splitNum[i + 1];
                    break;
                case "*":
                    sum = sum * splitNum[i + 1];
                    break;
                case "/":
                    sum = sum / splitNum[i + 1];
                    break;

            }
        }
        return sum;
    }


    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String split = scanner.nextLine();

        int calculator = calculator(split);

        System.out.println("calculator = " + calculator);
    }

}

기능에 대한 구현은 StringCalculator 클래스에서 작성하고 테스트를 위한 클래스를 나누어 진행하였다. 기존 코드에서 숫자 뽑아오기, 연산 기호 뽑아오기, 연산하기를 메서드화 하여 각 기능별로 테스트 할 수 있도록 수정하였다.

테스트 코드

class StringCalculatorTest {

    StringCalculator sc = new StringCalculator();

    @Test
    void splitNum() {
        //given
        String input = "22 + 33 * 44 / 55";
        //when
        int[] ints = sc.splitNum(input);
        //then
        assertThat(ints).containsExactly(22, 33, 44, 55);
    }

    @Test
    void splitString() {
        //given
        String input = "22 + 33 * 44 / 55";
        //when
        String[] strings = sc.splitString(input);
        //then
        assertThat(strings).containsExactly("+", "*", "/");
    }

    @Test
    void calculator() {
        //given
        String input = "22 + 33 * 44 / 55";
        //when
        int calculator = sc.calculator(input);
        //then
        assertThat(calculator).isEqualTo(44);
    }

}

특정 String 값이 주어졌을때 각 메서드별로 결과 값이 기대값과 일치하는지 확인하는 테스트 코드를 작성하였다.

'JUnit, TDD , 클린코드 연습' 카테고리의 다른 글

프로젝트 테스트 코드 작성  (0) 2024.04.27
MockMvc 테스트  (0) 2024.04.07