Skip to content

Commit 4a1534b

Browse files
authored
고생하셨습니다.
🎉 PR 머지 완료! 🎉
1 parent 3aa0cd2 commit 4a1534b

File tree

5 files changed

+255
-0
lines changed

5 files changed

+255
-0
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ repositories {
1212
dependencies {
1313
testImplementation platform('org.junit:junit-bom:5.9.1')
1414
testImplementation('org.junit.jupiter:junit-jupiter')
15+
testImplementation('org.assertj:assertj-core:3.24.2')
1516
}
1617

1718
test {

src/main/java/Calc.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
public class Calc {
2+
public int add(int a, int b) {
3+
int res = a + b;
4+
return res;
5+
}
6+
7+
public int minus(int a, int b) {
8+
int res = a - b;
9+
return res;
10+
}
11+
12+
public int times(int a, int b) {
13+
int res = a * b;
14+
return res;
15+
}
16+
17+
public int divide(int a, int b) {
18+
if (b == 0) {
19+
throw new IllegalArgumentException("0 으로 나눌 수 없습니다.");
20+
}
21+
int res = a / b;
22+
return res;
23+
}
24+
}

src/main/java/StringCalc.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import java.util.regex.Matcher;
2+
import java.util.regex.Pattern;
3+
4+
public class StringCalc {
5+
6+
private static final String DEFAULT_DELIMITERS = "[,:]";
7+
8+
public int add(String text) {
9+
if (isNullOrEmpty(text)) {
10+
return 0;
11+
}
12+
13+
DelimiterInfo delimiterInfo = parseDelimiterInfo(text);
14+
String[] numbersAsString = splitByDelimiter(delimiterInfo.textToParse, delimiterInfo.delimiter);
15+
16+
return calculateSum(numbersAsString);
17+
}
18+
19+
private boolean isNullOrEmpty(String text) {
20+
return text == null || text.isEmpty();
21+
}
22+
23+
private DelimiterInfo parseDelimiterInfo(String text) {
24+
Pattern customDelimiterPattern = Pattern.compile("//(.)\n(.*)");
25+
Matcher matcher = customDelimiterPattern.matcher(text);
26+
27+
if (matcher.find()) {
28+
String customDelimiter = Pattern.quote(matcher.group(1));
29+
String actualTextToParse = matcher.group(2);
30+
// 커스텀 구분자와 기본 구분자를 모두 포함
31+
String combinedDelimiters = DEFAULT_DELIMITERS + "|" + customDelimiter;
32+
return new DelimiterInfo(combinedDelimiters, actualTextToParse);
33+
}
34+
35+
return new DelimiterInfo(DEFAULT_DELIMITERS, text);
36+
}
37+
38+
private String[] splitByDelimiter(String text, String delimiter) {
39+
return text.split(delimiter);
40+
}
41+
42+
private int calculateSum(String[] numbersAsString) {
43+
int sum = 0;
44+
for (String numStr : numbersAsString) {
45+
if (numStr.isEmpty()) {
46+
continue;
47+
}
48+
sum += parseAndValidateNumber(numStr);
49+
}
50+
return sum;
51+
}
52+
53+
private int parseAndValidateNumber(String numStr) {
54+
try {
55+
int number = Integer.parseInt(numStr);
56+
validateNumber(number);
57+
return number;
58+
} catch (NumberFormatException e) {
59+
throw new RuntimeException("숫자 이외의 값이 포함되어 있습니다.");
60+
}
61+
}
62+
63+
private void validateNumber(int number) {
64+
if (number < 0) {
65+
throw new RuntimeException("음수는 입력할 수 없습니다.");
66+
}
67+
}
68+
69+
private static class DelimiterInfo {
70+
final String delimiter;
71+
final String textToParse;
72+
73+
DelimiterInfo(String delimiter, String textToParse) {
74+
this.delimiter = delimiter;
75+
this.textToParse = textToParse;
76+
}
77+
}
78+
}

src/test/java/CalcTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
import org.junit.jupiter.api.DisplayName;
3+
import org.junit.jupiter.api.Test;
4+
import static org.assertj.core.api.Assertions.*;
5+
6+
@DisplayName("계산기 작동 테스트")
7+
public class CalcTest {
8+
private final Calc calc = new Calc();
9+
10+
@Test
11+
@DisplayName("더하기 테스트")
12+
void add() {
13+
final var a = 1;
14+
final var b = 2;
15+
final var actual = calc.add(a, b);
16+
17+
assertThat(actual).isEqualTo(3);
18+
}
19+
20+
@Test
21+
@DisplayName("빼기 테스트")
22+
void minus() {
23+
final var a = 3;
24+
final var b = 1;
25+
final var actual = calc.minus(a, b);
26+
27+
assertThat(actual).isEqualTo(2);
28+
}
29+
30+
@Test
31+
@DisplayName("곱하기 테스트")
32+
void times() {
33+
final var a = 2;
34+
final var b = 3;
35+
final var actual = calc.times(a, b);
36+
37+
assertThat(actual).isEqualTo(6);
38+
}
39+
40+
@Test
41+
@DisplayName("나누기 테스트")
42+
void divide() {
43+
final var a = 10;
44+
final var b = 5;
45+
final var actual = calc.divide(a, b);
46+
47+
assertThat(actual).isEqualTo(2);
48+
}
49+
50+
@Test
51+
@DisplayName("0으로 나누기 예외 테스트")
52+
void divideByZeroThrowsException() {
53+
final var a = 10;
54+
final var b = 0;
55+
56+
assertThatThrownBy(() -> calc.divide(a, b))
57+
.isInstanceOf(IllegalArgumentException.class)
58+
.hasMessage("0 으로 나눌 수 없습니다.");
59+
}
60+
}

src/test/java/StringCalcTest.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
2+
import org.junit.jupiter.api.DisplayName;
3+
import org.junit.jupiter.api.Test;
4+
import static org.assertj.core.api.Assertions.*;
5+
6+
@DisplayName("문자열 계산기 테스트")
7+
class StringCalcTest {
8+
private final StringCalc stringCalc = new StringCalc();
9+
10+
@Test
11+
@DisplayName("쉼표 구분자 문자열 계산 테스트")
12+
void addWithComma() {
13+
final var input = "1,2,3";
14+
final var actual = stringCalc.add(input);
15+
16+
assertThat(actual).isEqualTo(6);
17+
}
18+
19+
@Test
20+
@DisplayName("콜론 구분자 문자열 계산 테스트")
21+
void addWithColon() {
22+
final var input = "1:2:3";
23+
final var actual = stringCalc.add(input);
24+
25+
assertThat(actual).isEqualTo(6);
26+
}
27+
28+
@Test
29+
@DisplayName("쉼표와 콜론 혼합 구분자 테스트")
30+
void addWithMixedDelimiters() {
31+
final var input = "1,2:3";
32+
final var actual = stringCalc.add(input);
33+
34+
assertThat(actual).isEqualTo(6);
35+
}
36+
37+
@Test
38+
@DisplayName("빈 문자열 테스트")
39+
void addEmptyString() {
40+
final var input = "";
41+
final var actual = stringCalc.add(input);
42+
43+
assertThat(actual).isEqualTo(0);
44+
}
45+
46+
@Test
47+
@DisplayName("null 입력 테스트")
48+
void addNullInput() {
49+
final String input = null;
50+
final var actual = stringCalc.add(input);
51+
52+
assertThat(actual).isEqualTo(0);
53+
}
54+
55+
@Test
56+
@DisplayName("커스텀 구분자 테스트")
57+
void addWithCustomDelimiter() {
58+
final var input = "//;\n1;2;3";
59+
final var actual = stringCalc.add(input);
60+
61+
assertThat(actual).isEqualTo(6);
62+
}
63+
64+
@Test
65+
@DisplayName("음수 입력 예외 테스트")
66+
void addNegativeNumberThrowsException() {
67+
final var input = "1,-2,3";
68+
69+
assertThatThrownBy(() -> stringCalc.add(input))
70+
.isInstanceOf(RuntimeException.class)
71+
.hasMessage("음수는 입력할 수 없습니다.");
72+
}
73+
74+
@Test
75+
@DisplayName("숫자가 아닌 값 입력 예외 테스트")
76+
void addNonNumericValueThrowsException() {
77+
final var input = "1,a,3";
78+
79+
assertThatThrownBy(() -> stringCalc.add(input))
80+
.isInstanceOf(RuntimeException.class)
81+
.hasMessage("숫자 이외의 값이 포함되어 있습니다.");
82+
}
83+
84+
@Test
85+
@DisplayName("커스텀 구분자와 기본 구분자 혼합 테스트")
86+
void addWithCustomAndDefaultDelimiters() {
87+
final var input = "//@\n1@2,3:4";
88+
final var actual = stringCalc.add(input);
89+
90+
assertThat(actual).isEqualTo(10);
91+
}
92+
}

0 commit comments

Comments
 (0)