Skip to content

Commit ea5bc6d

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

File tree

7 files changed

+431
-0
lines changed

7 files changed

+431
-0
lines changed

build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ repositories {
1010
}
1111

1212
dependencies {
13+
implementation("org.apache.commons:commons-lang3:3.18.0")
1314
testImplementation platform('org.junit:junit-bom:5.9.1')
15+
testImplementation platform('org.assertj:assertj-bom:3.25.1')
1416
testImplementation('org.junit.jupiter:junit-jupiter')
17+
testImplementation('org.assertj:assertj-core')
1518
}
1619

1720
test {

src/main/java/Calculator.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
public class Calculator {
2+
3+
public int add(int a, int b) {
4+
return Math.addExact(a, b);
5+
}
6+
7+
public int subtract(int a, int b) {
8+
return Math.subtractExact(a, b);
9+
}
10+
11+
public int multiply(int a, int b) {
12+
return Math.multiplyExact(a, b);
13+
}
14+
15+
public int divide(int a, int b) {
16+
if (b == 0) {
17+
throw new IllegalArgumentException("0 나누기 오류");
18+
}
19+
20+
return Math.floorDiv(a, b);
21+
}
22+
}

src/main/java/StringCalculator.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import java.util.Arrays;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
5+
public class StringCalculator {
6+
7+
private static final String DEFAULT_DELIMITER = ",|:";
8+
private static final String START_CUSTOM_DELIMITER = "//";
9+
private static final String END_CUSTOM_DELIMITER = "\n";
10+
11+
private String customDelimiter = "";
12+
13+
public int add(String input) {
14+
String delimiter = DEFAULT_DELIMITER;
15+
16+
if (StringUtils.isEmpty(input)) {
17+
return 0;
18+
}
19+
20+
if (hasCustomDelimiter(input)) {
21+
input = extractCustomDelimiter(input);
22+
delimiter += "|" + this.customDelimiter;
23+
}
24+
25+
return getSum(input.split(delimiter));
26+
}
27+
28+
private int getSum(String[] numbers) {
29+
return Arrays.stream(numbers).mapToInt(num -> {
30+
validateIsNumber(num);
31+
int number = Integer.parseInt(num);
32+
validateIsPositive(number);
33+
return number;
34+
}).reduce(0, Math::addExact);
35+
}
36+
37+
private String extractCustomDelimiter(String input) {
38+
int endCustomDelimiterIndex = input.indexOf(END_CUSTOM_DELIMITER);
39+
this.customDelimiter = input.substring(START_CUSTOM_DELIMITER.length(), endCustomDelimiterIndex);
40+
return input.substring(endCustomDelimiterIndex + 1);
41+
}
42+
43+
private void validateIsNumber(String number) {
44+
if (!isNumber(number)) {
45+
throw new RuntimeException("숫자가 아닌 값이 포함되어 있습니다");
46+
}
47+
}
48+
49+
private void validateIsPositive(Integer number) {
50+
if (number < 0) {
51+
throw new RuntimeException("음수는 허용되지 않습니다");
52+
}
53+
}
54+
55+
private boolean hasCustomDelimiter(String input) {
56+
return input.startsWith(START_CUSTOM_DELIMITER);
57+
}
58+
59+
private boolean isNumber(String number) {
60+
return number.matches("-?\\d+");
61+
}
62+
63+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import static org.assertj.core.api.Assertions.*;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Nested;
5+
import org.junit.jupiter.api.Test;
6+
7+
public class CalculatorAssertJTest {
8+
9+
private final Calculator calculator = new Calculator();
10+
11+
@Nested
12+
@DisplayName("덧셈 테스트")
13+
public class AddTest {
14+
15+
@Test
16+
public void 정수_더하기() {
17+
// Given
18+
int a = 2;
19+
int b = 3;
20+
21+
// When
22+
int actual = calculator.add(a, b);
23+
24+
// Then
25+
int expected = 5;
26+
assertThat(actual).isEqualTo(expected);
27+
}
28+
}
29+
30+
@Nested
31+
@DisplayName("뺄셈 테스트")
32+
public class SubtractTest {
33+
34+
@Test
35+
public void 정수_빼기() {
36+
// Given
37+
int a = 3;
38+
int b = 2;
39+
40+
// When
41+
int actual = calculator.subtract(a, b);
42+
43+
// Then
44+
int expected = 1;
45+
assertThat(actual).isEqualTo(expected);
46+
}
47+
}
48+
49+
@Nested
50+
@DisplayName("곱셈 테스트")
51+
public class MultiplyTest {
52+
53+
@Test
54+
public void 정수_곱하기() {
55+
// Given
56+
int a = 2;
57+
int b = 3;
58+
59+
// When
60+
int actual = calculator.multiply(a, b);
61+
62+
// Then
63+
int expected = 6;
64+
assertThat(actual).isEqualTo(expected);
65+
}
66+
}
67+
68+
@Nested
69+
@DisplayName("나눗셈 테스트")
70+
public class DivideTest {
71+
72+
@Test
73+
public void 정수_나누기() {
74+
// Given
75+
int a = 6;
76+
int b = 3;
77+
78+
// When
79+
int actual = calculator.divide(a, b);
80+
81+
// Then
82+
int expected = 2;
83+
assertThat(actual).isEqualTo(expected);
84+
}
85+
86+
@Test
87+
public void 예외_0_나누기() {
88+
// Given
89+
int a = 1;
90+
int b = 0;
91+
92+
// When & Then
93+
assertThatThrownBy(() -> calculator.divide(a, b))
94+
.isInstanceOf(IllegalArgumentException.class)
95+
.hasMessage("0 나누기 오류");
96+
97+
assertThatCode(() -> calculator.divide(b, a))
98+
.doesNotThrowAnyException();
99+
}
100+
101+
@Test
102+
public void 나누기_결과가_정수가_아닐때() {
103+
// Given
104+
int a = 5;
105+
int b = 2;
106+
107+
// When
108+
int actual = calculator.divide(a, b);
109+
110+
// Then
111+
int expected = 2; // 결과값은 정수로 나옴
112+
assertThat(actual).isEqualTo(expected);
113+
}
114+
}
115+
116+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import static org.junit.jupiter.api.Assertions.*;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Nested;
5+
import org.junit.jupiter.api.Test;
6+
7+
public class CalculatorJunit5Test {
8+
9+
private final Calculator calculator = new Calculator();
10+
11+
@Nested
12+
@DisplayName("덧셈 테스트")
13+
public class AddTest {
14+
15+
@Test
16+
public void 정수_더하기() {
17+
assertEquals(5, calculator.add(2, 3));
18+
assertEquals(0, calculator.add(-1, 1));
19+
assertEquals(-5, calculator.add(-2, -3));
20+
}
21+
}
22+
23+
@Nested
24+
@DisplayName("뺄셈 테스트")
25+
public class SubtractTest {
26+
27+
@Test
28+
public void 정수_빼기() {
29+
assertEquals(1, calculator.subtract(3, 2));
30+
assertEquals(-2, calculator.subtract(-1, 1));
31+
assertEquals(1, calculator.subtract(-2, -3));
32+
}
33+
}
34+
35+
@Nested
36+
@DisplayName("곱셈 테스트")
37+
public class MultiplyTest {
38+
39+
@Test
40+
public void 정수_곱하기() {
41+
assertEquals(6, calculator.multiply(2, 3));
42+
assertEquals(-1, calculator.multiply(-1, 1));
43+
assertEquals(6, calculator.multiply(-2, -3));
44+
}
45+
}
46+
47+
@Nested
48+
@DisplayName("나눗셈 테스트")
49+
public class DivideTest {
50+
51+
@Test
52+
public void 정수_나누기() {
53+
assertEquals(2, calculator.divide(6, 3));
54+
assertEquals(-1, calculator.divide(-3, 3));
55+
assertEquals(1, calculator.divide(-3, -3));
56+
}
57+
58+
@Test
59+
public void 예외_0_나누기() {
60+
assertThrows(IllegalArgumentException.class, () -> calculator.divide(1, 0));
61+
assertDoesNotThrow(() -> calculator.divide(0, 1));
62+
}
63+
64+
@Test
65+
public void 나누기_결과가_정수가_아닐때() {
66+
assertEquals(2, calculator.divide(5, 2));
67+
assertEquals(0, calculator.divide(1, 2));
68+
}
69+
}
70+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2+
import static org.assertj.core.api.Assertions.*;
3+
4+
import org.junit.jupiter.api.DisplayName;
5+
import org.junit.jupiter.api.Nested;
6+
import org.junit.jupiter.api.Test;
7+
8+
public class StringCalculatorAssertJTest {
9+
10+
private final StringCalculator stringCalculator = new StringCalculator();
11+
12+
@Nested
13+
@DisplayName("덧셈 테스트")
14+
class AddTest {
15+
16+
@Test
17+
void 빈_문자열() {
18+
// Given
19+
String input = "";
20+
21+
// When
22+
int result = stringCalculator.add(input);
23+
24+
// Then
25+
assertThat(result).isEqualTo(0);
26+
}
27+
28+
@Test
29+
void 하나의_숫자() {
30+
// Given
31+
String input = "1";
32+
33+
// When
34+
int result = stringCalculator.add(input);
35+
36+
// Then
37+
assertThat(result).isEqualTo(1);
38+
}
39+
40+
@Test
41+
void 두_숫자_더하기() {
42+
// Given
43+
String input = "1,2";
44+
45+
// When
46+
int result = stringCalculator.add(input);
47+
48+
// Then
49+
assertThat(result).isEqualTo(3);
50+
}
51+
52+
@Test
53+
void 여러_숫자_더하기() {
54+
// Given
55+
String input = "1,2,3";
56+
57+
// When
58+
int result = stringCalculator.add(input);
59+
60+
// Then
61+
assertThat(result).isEqualTo(6);
62+
}
63+
64+
@Test
65+
void 커스텀_구분자() {
66+
// Given
67+
String input = "//;\n4;5,1:2";
68+
69+
// When
70+
int result = stringCalculator.add(input);
71+
72+
// Then
73+
assertThat(result).isEqualTo(12);
74+
}
75+
76+
@Test
77+
void 음수_예외() {
78+
// Given
79+
String input = "-1";
80+
81+
// When & Then
82+
assertThatThrownBy(() -> stringCalculator.add(input))
83+
.isInstanceOf(RuntimeException.class)
84+
.hasMessageContaining("음수는 허용되지 않습니다");
85+
86+
}
87+
88+
@Test
89+
void 숫자가_아닌_예외() {
90+
// Given
91+
String input = "1,a";
92+
93+
// When & Then
94+
assertThatThrownBy(() -> stringCalculator.add(input))
95+
.isInstanceOf(RuntimeException.class)
96+
.hasMessageContaining("숫자가 아닌 값이 포함되어 있습니다");
97+
}
98+
}
99+
}

0 commit comments

Comments
 (0)