-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LBP] 송하은 미션 3,4단계 제출합니다. #72
base: haeunsong
Are you sure you want to change the base?
Changes from all commits
eb6bedd
035d8ad
0afd62f
972b88c
ce29ca1
15dad54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
public class Calculator { | ||
|
||
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) { | ||
if (b == 0) { | ||
throw new ArithmeticException("Divide by zero"); | ||
} | ||
return a / b; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import java.util.regex.Pattern; | ||
|
||
public class StringCalculator { | ||
|
||
/* | ||
1. 입력값 검증 | ||
2. 구분자 추출 | ||
3. 문자열을 구분자 기준으로 분리 | ||
4. 분리된 숫자 문자열 배열을 합산 | ||
*/ | ||
|
||
public int splitStrBySeparaterAndGetSum(String str) { | ||
// 1. 입력값 검증 | ||
if(str.length() == 0) { | ||
return 0; | ||
} | ||
|
||
// 2. 구분자, 커스텀 구분자일 경우 구분자 제외 검사해야할 문자열 추출 | ||
String separater = extractSeparater(str); | ||
String numbers = extractNumbers(str); | ||
|
||
// 3. 문자열을 구분자 기준으로 분리 | ||
String [] tokens = numbers.split(separater); | ||
validateTokens(tokens); | ||
|
||
// 4. 분리된 숫자 문자열 배열 합산 | ||
return calculateSum(tokens); | ||
} | ||
|
||
private String extractSeparater(String str) { | ||
// 기본 구분자는 , 또는 : 이다. | ||
String separater = "[,|:]"; | ||
|
||
// 커스텀 구분자가 존재하는 경우 | ||
if (str.startsWith("//") && str.contains("\n")) { | ||
int newLineIdx = str.indexOf("\n"); | ||
// /n 을 찾을 수 없는 경우 | ||
if (newLineIdx == -1) { | ||
throw new RuntimeException("커스텀 구분자를 '//' 와 '\\n' 문자 사이에 정확하게 입력해주세요."); | ||
} | ||
separater = Pattern.quote(str.substring(2, newLineIdx)); | ||
} | ||
return separater; | ||
} | ||
|
||
private String extractNumbers(String str) { | ||
String numbers = ""; | ||
|
||
// 커스텀 구분자일 경우 | ||
if(str.startsWith("//")) { | ||
numbers = str.substring(str.indexOf("\n") + 1); | ||
return numbers; | ||
} | ||
|
||
// 기본 구분자이면 그대로 str 반환 | ||
return str; | ||
} | ||
|
||
private void validateTokens(String[] tokens) { | ||
for(String token : tokens) { | ||
if (token.isEmpty()) { | ||
throw new RuntimeException("잘못된 입력 형식입니다."); | ||
} | ||
|
||
if(parseNumber(token) < 0) { | ||
throw new RuntimeException("음수는 사용할 수 없습니다."); | ||
} | ||
} | ||
} | ||
|
||
private int calculateSum(String[] tokens) { | ||
int sum = 0; | ||
for(String token : tokens) { | ||
sum += Integer.parseInt(token); | ||
} | ||
return sum; | ||
} | ||
|
||
private int parseNumber(String number) { | ||
// 숫자가 아니라면 예외 발생 | ||
try { | ||
return Integer.parseInt(number); | ||
} catch (NumberFormatException e) { | ||
throw new RuntimeException("숫자가 아닌 값이 포함되어 있습니다."); | ||
} | ||
} | ||
|
||
private boolean isNumeric(String str) { | ||
return str.matches("-?\\d+"); // 정수 여부를 확인하는 정규식 (-는 음수 허용) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
@DisplayName("초간단 계산기 테스트") | ||
class CalculatorTest { | ||
private final Calculator calculator = new Calculator(); | ||
|
||
@Nested | ||
class Add { | ||
@Test | ||
void add() { | ||
assertEquals(5, calculator.add(2, 3)); | ||
} | ||
} | ||
|
||
@Nested | ||
class Subtract { | ||
@Test | ||
void subtract() { | ||
assertEquals(-3, calculator.subtract(3, 6)); | ||
} | ||
} | ||
|
||
@Nested | ||
class Multiply { | ||
@Test | ||
void multiply() { | ||
assertEquals(6, calculator.multiply(2, 3)); | ||
} | ||
} | ||
|
||
@Nested | ||
class Divide{ | ||
@Test | ||
@DisplayName("0으로 나누면 ArithmeticException 예외가 발생한다.") | ||
void should_throw_exception_when_divide_by_zero() { | ||
assertThrows(ArithmeticException.class, () -> calculator.divide(3,0)); | ||
} | ||
|
||
@Test | ||
void divideByNotZero() { | ||
assertEquals(2, calculator.divide(6, 3)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
|
||
@DisplayName("문자열 계산기 테스트") | ||
class StringCalculatorTest { | ||
|
||
private StringCalculator stringCalculator = new StringCalculator(); | ||
|
||
@Nested | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
@DisplayName("기본 구분자 테스트") | ||
class basicSeparaterTest { | ||
|
||
@ParameterizedTest(name = "입력값 \"{0}\"은 결과값 {1}을 반환해야 한다.") | ||
@CsvSource({ | ||
"'', 0", | ||
"'123', 123", | ||
"'1,2:3', 6" | ||
}) | ||
void should_return_correct_sum(String input, int expected) { | ||
assertThat(stringCalculator.splitStrBySeparaterAndGetSum(input)).isEqualTo(expected); | ||
} | ||
} | ||
|
||
@Nested | ||
@DisplayName("커스텀 구분자 테스트") | ||
class customSeparaterTest { | ||
@Test | ||
@DisplayName("커스텀 구분자로 분리한 숫자들의 합을 반환해야 한다") | ||
void should_sum_numbers_separated_by_custom_separator() { | ||
assertThat(6).isEqualTo(stringCalculator.splitStrBySeparaterAndGetSum("//;\n1;2;3")); | ||
assertThat(2).isEqualTo(stringCalculator.splitStrBySeparaterAndGetSum("//;\n2")); | ||
} | ||
} | ||
|
||
@Nested | ||
@DisplayName("Runtime Exception 테스트") | ||
class runtimeExceptionTest { | ||
@Test | ||
@DisplayName("숫자가 아닌 값이 포함되면 예외를 발생해야 한다.") | ||
void should_throw_exception_when_contains_non_number() { | ||
|
||
// 특수문자가 포함된 경우 | ||
assertThatThrownBy(() -> stringCalculator.splitStrBySeparaterAndGetSum("//;\n1;*;3")) | ||
.isInstanceOf(RuntimeException.class) | ||
.hasMessageContaining("숫자가 아닌 값이 포함되어 있습니다."); | ||
|
||
assertThatThrownBy(() -> stringCalculator.splitStrBySeparaterAndGetSum("//;\n1456;-;3")) | ||
.isInstanceOf(RuntimeException.class) | ||
.hasMessageContaining("숫자가 아닌 값이 포함되어 있습니다."); | ||
|
||
// 글자가 포함된 경우 | ||
assertThatThrownBy(() -> stringCalculator.splitStrBySeparaterAndGetSum("//;\nddd;ad;3")) | ||
.isInstanceOf(RuntimeException.class) | ||
.hasMessageContaining("숫자가 아닌 값이 포함되어 있습니다."); | ||
} | ||
|
||
@Test | ||
@DisplayName("음수가 포함되면 예외를 발생해야 한다.") | ||
void should_throw_exception_when_contains_minus() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른 메서드들과 컨벤션이 맞춰지지 않은 것 같아요 |
||
|
||
assertThatThrownBy(() -> stringCalculator.splitStrBySeparaterAndGetSum("-4,2:-9")) | ||
.isInstanceOf(RuntimeException.class) | ||
.hasMessageContaining("음수는 사용할 수 없습니다."); | ||
} | ||
|
||
@Test | ||
@DisplayName("또 다른 잘못된 입력 형식의 경우 예외를 발생해야 한다.") | ||
void should_throw_exception_when_another_wrong_input() { | ||
|
||
assertThatThrownBy(() -> stringCalculator.splitStrBySeparaterAndGetSum("//;1;2;\n;")) | ||
.isInstanceOf(RuntimeException.class) | ||
.hasMessageContaining("잘못된 입력 형식입니다."); | ||
|
||
} | ||
} | ||
|
||
Comment on lines
+79
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 불필요한 개행들이 보입니다 제거해볼까요? |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정규식 특수문자를 안전하게 처리하셨네요! 👍