- 이 글은 자바지기(박재성)님의 강의를 개인적인 공부를 위해 정리한 글입니다.
- 우아한테크세미나_TDD 리팩토링
📖 단위 테스트 실습 - 문자열 계산기
- 다음 요구사항을 JUnit을 활용해 단위 테스트 코드를 추가해 구현한다.
기능 요구사항
- 사용자가 입력한 문자열 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현해야 한다.
- 문자열 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다. 즉, 수학에서는 곱셈, 나눗셈이 덧셈, 뺄셈보다 먼저 계산해야 하지만 이를 무시한다.
- 예를 들어 "2 + 3 * 4 / 2"와 같은 문자열을 입력할 경우 2 + 3 * 4 / 2 실행 결과인 10을 출력해야 한다.
계산기(사칙연산) 부분 구현
public int add(int a, int b){
return a + b;
}
public int subtract(int a, int b){
return a - b;
}
public int multiply(int a, int b){
return a * b;
}
public int divide(int a, int b){
try{
return a / b;
} catch (Exception e){
System.out.println("0으로 나눌 수 없습니다!");
}
return 0;
}
}
우선 사칙연산 부분을 각각의 메서드로 나누어 하나의 메서드가 하나의 일만 할 수 있도록(사칙연산에서는 당연한 얘기이지만) 구현했다.
divide메서드 (나눗셈) 부분에서는 분모가 0인 경우를 대비하여 try catch구문으로 예외처리를 해주었으며
만약 0으로 나누어 주었을 경우 0을 리턴하도록 설계했다.
public int calculate(int firstvalue, char operator, int secondvalue){
if(operator == '+')
return add(firstvalue, secondvalue);
if(operator == '-')
return subtract(firstvalue, secondvalue);
if(operator == '*')
return multiply(firstvalue,secondvalue);
if(operator == '/')
return divide(firstvalue, secondvalue);
else System.out.println("잘못된 값 입력");
throw new RuntimeException();
}
실제로 계산을 실행하는 calculate메서드에서는 입력된 연산자의 값에 따라 위에서 만들어 두었던 사칙연산 메서드들을 이용해 결과값을
int형으로 return 하도록 설계했다.
공백 단위로 나누어주기
public String[] seperate(String str){
return str.split(" ");
}
문자열 형태의 식이 인자로 들어왔을 경우 split을 이용해 공백을 기준으로 나누어 주는 부분을 구현하였다.
그리고 나누어진 문자들을 집어넣어 String [] 배열 타입으로 return 해 주었다.
split에 관한 내용 -> 링크
문자를 숫자로 바꾸어주기
public int toInt(String str){
return Integer.parseInt(str);
}
사칙연산 메서드를 이용하기 위해서는 문자를 숫자로 바꾸어주는 과정이 필요하다.
이를 위해 parseInt를 활용한다. Integer.parseInt(str)는 문자가 인자로 들어오면 이를 숫자로 바꾸어 주는 메서드이다.
parseInt 관한 내용 -> 링크
문자열을 계산하는 부분
public int calculateString(String[] str){
int result = toInt(str[0]); //미리 작성했던 메소드를 이용
for(int i = 0; i < str.length - 2; i += 2){
result = calculate(result, str[i + 1].charAt(0), toInt(str[i + 2])); //charAt 을 이용해서 String 한글자를 char로 변경
}
return result;
}
이 부분이 살짝 복잡한데 우선 바로 위에서 미리 작성해 두었던 toInt메서드를 활용해 Stirng [] 배열에 저장된 문자 중
가장 첫 번째 문자를 int result로써 저장해둔다. 그리고 앞에서부터 순서대로 (숫자 연산자 숫자) 묶음으로 계산해 나간다.
따라서 for문에서 i가 2씩 증가하고 str.lengt - 2 전까지 반복되는 것이다. (그렇지 않다면 index를 벗어나 에러가 발생한다.)
최종적으로 나온 결과를 int형 result에 저장한다.
여기까지가 실제 로직을 구현한 프로덕션 코드이다.
다음은 이를 테스트해보는 테스트 코드를 보자
📖 테스트 코드
package study;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class StringCalTest {
StringCal calculator;
@BeforeEach
public void SetUp(){
calculator = new StringCal();
}
@Test
@DisplayName("더하기 테스트")
void addtest(){
assertThat(4).isEqualTo(calculator.add(1,3));
}
@Test
@DisplayName("빼기 테스트")
void substracttest(){
assertThat(4).isEqualTo(calculator.subtract(6,2));
}
@Test
@DisplayName("곱하기 테스트")
void multiplytest(){
assertThat(4).isEqualTo(calculator.multiply(2,2));
}
@Test
@DisplayName("나누기 테스트")
void dividetest(){
assertThat(0).isEqualTo(calculator.divide(8,0));
}
@Test
@DisplayName("문자열 나눠주기")
void sep(){
String str = "1 + 3";
String[] result = {"1" , "+", "3"};
assertThat(result).isEqualTo(calculator.seperate(str));
}
@Test
@DisplayName("문자열 계산하기")
void strcal(){
String str = "1 + 3 + 5 + 7 + 9";
String[] result = calculator.seperate(str);
int num = 25;
assertThat(num).isEqualTo(calculator.calculateString(result));
}
}
JUnit5의 assertJ의 assertThat(actual). isEqualTo(expected); 를 적극 활용하여 테스트 코드를 작성해 보았다.
관련 내용은 이전 포스팅을 참고하기 바란다. 링크
테스트 확인
테스트 결과 모두 잘 작동하는 것을 확인할 수 있었다.
'JAVA with TDD, Clean Code' 카테고리의 다른 글
JAVA(자바) 단위 테스트 실습 - 숫자야구게임 구현 (0) | 2021.09.17 |
---|---|
간단한 클래스 분리 (0) | 2021.08.21 |
JUnit, AssertJ, 단위테스트 개념 및 다양한 활용법 (0) | 2021.08.04 |
Set Collection에 대한 학습 테스트 (0) | 2021.07.30 |
String 클래스에 대한 학습 테스트 (0) | 2021.07.29 |