Skip to content

[박종범] 1차시 미션 제출입니다. #104

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

Merged
merged 16 commits into from
Aug 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ repositories {
}

dependencies {
implementation("org.apache.commons:commons-lang3:3.18.0")
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
}

test {
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/Calculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
public class Calculator {

public int add(int a, int b) {
return Math.addExact(a, b);
}

public int subtract(int a, int b) {
return Math.subtractExact(a, b);
}

public int multiply(int a, int b) {
return Math.multiplyExact(a, b);
}

public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("0 나누기 오류");
}

return Math.floorDiv(a, b);
}
}
63 changes: 63 additions & 0 deletions src/main/java/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;

public class StringCalculator {

private static final String DEFAULT_DELIMITER = ",|:";
private static final String START_CUSTOM_DELIMITER = "//";
private static final String END_CUSTOM_DELIMITER = "\n";

private String customDelimiter = "";

public int add(String input) {
String delimiter = DEFAULT_DELIMITER;

if (StringUtils.isEmpty(input)) {
return 0;
}

if (hasCustomDelimiter(input)) {
input = extractCustomDelimiter(input);
delimiter += "|" + this.customDelimiter;
}

return getSum(input.split(delimiter));
}

private int getSum(String[] numbers) {
return Arrays.stream(numbers).mapToInt(num -> {
validateIsNumber(num);
int number = Integer.parseInt(num);
validateIsPositive(number);
return number;
}).reduce(0, Math::addExact);
}

private String extractCustomDelimiter(String input) {
int endCustomDelimiterIndex = input.indexOf(END_CUSTOM_DELIMITER);
this.customDelimiter = input.substring(START_CUSTOM_DELIMITER.length(), endCustomDelimiterIndex);
return input.substring(endCustomDelimiterIndex + 1);
}

private void validateIsNumber(String number) {
if (!isNumber(number)) {
throw new RuntimeException("숫자가 아닌 값이 포함되어 있습니다");
}
}

private void validateIsPositive(Integer number) {
if (number < 0) {
throw new RuntimeException("음수는 허용되지 않습니다");
}
}

private boolean hasCustomDelimiter(String input) {
return input.startsWith(START_CUSTOM_DELIMITER);
}

private boolean isNumber(String number) {
return number.matches("-?\\d+");
}

}
116 changes: 116 additions & 0 deletions src/test/java/CalculatorAssertJTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import static org.assertj.core.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class CalculatorAssertJTest {

private final Calculator calculator = new Calculator();

@Nested
@DisplayName("덧셈 테스트")
public class AddTest {

@Test
public void 정수_더하기() {
Comment on lines +7 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 부분은 클래스 시작할때 들여쓰기가 있는데, 다른 부분에는 없네요.
추후 협업을 하는데 코드 컨벤션은 매우 중요한 요소이기에 기준을 잘 정하셨으면 좋겠습니다
(참고로 코인은 클래스 시작은 들여쓰기O, 메서드 시작은 들여쓰기X입니다)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

감사합니다! 해당 부분은 코인 방식으로 리팩토링 해보겠습니다.

인텔리제이에 해당 bcsd 컨벤션 포매팅 파일 을 적용해서 사용하였는데, 해당 포매팅파일 말고도 별도로 더 강하게 컨벤션을 잡기 위해 사용하고 계신 툴이 혹시 있으신지 궁금합니다.

// Given
int a = 2;
int b = 3;

// When
int actual = calculator.add(a, b);

// Then
int expected = 5;
assertThat(actual).isEqualTo(expected);
}
}

@Nested
@DisplayName("뺄셈 테스트")
public class SubtractTest {

@Test
public void 정수_빼기() {
// Given
int a = 3;
int b = 2;

// When
int actual = calculator.subtract(a, b);

// Then
int expected = 1;
assertThat(actual).isEqualTo(expected);
}
}

@Nested
@DisplayName("곱셈 테스트")
public class MultiplyTest {

@Test
public void 정수_곱하기() {
// Given
int a = 2;
int b = 3;

// When
int actual = calculator.multiply(a, b);

// Then
int expected = 6;
assertThat(actual).isEqualTo(expected);
}
}

@Nested
@DisplayName("나눗셈 테스트")
public class DivideTest {

@Test
public void 정수_나누기() {
// Given
int a = 6;
int b = 3;

// When
int actual = calculator.divide(a, b);

// Then
int expected = 2;
assertThat(actual).isEqualTo(expected);
}

@Test
public void 예외_0_나누기() {
// Given
int a = 1;
int b = 0;

// When & Then
assertThatThrownBy(() -> calculator.divide(a, b))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("0 나누기 오류");

assertThatCode(() -> calculator.divide(b, a))
.doesNotThrowAnyException();
}

@Test
public void 나누기_결과가_정수가_아닐때() {
// Given
int a = 5;
int b = 2;

// When
int actual = calculator.divide(a, b);

// Then
int expected = 2; // 결과값은 정수로 나옴
assertThat(actual).isEqualTo(expected);
}
}

}
70 changes: 70 additions & 0 deletions src/test/java/CalculatorJunit5Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class CalculatorJunit5Test {

private final Calculator calculator = new Calculator();

@Nested
@DisplayName("덧셈 테스트")
public class AddTest {

@Test
public void 정수_더하기() {
assertEquals(5, calculator.add(2, 3));
assertEquals(0, calculator.add(-1, 1));
assertEquals(-5, calculator.add(-2, -3));
}
}

@Nested
@DisplayName("뺄셈 테스트")
public class SubtractTest {

@Test
public void 정수_빼기() {
assertEquals(1, calculator.subtract(3, 2));
assertEquals(-2, calculator.subtract(-1, 1));
assertEquals(1, calculator.subtract(-2, -3));
}
}

@Nested
@DisplayName("곱셈 테스트")
public class MultiplyTest {

@Test
public void 정수_곱하기() {
assertEquals(6, calculator.multiply(2, 3));
assertEquals(-1, calculator.multiply(-1, 1));
assertEquals(6, calculator.multiply(-2, -3));
}
}

@Nested
@DisplayName("나눗셈 테스트")
public class DivideTest {

@Test
public void 정수_나누기() {
assertEquals(2, calculator.divide(6, 3));
assertEquals(-1, calculator.divide(-3, 3));
assertEquals(1, calculator.divide(-3, -3));
}

@Test
public void 예외_0_나누기() {
assertThrows(IllegalArgumentException.class, () -> calculator.divide(1, 0));
assertDoesNotThrow(() -> calculator.divide(0, 1));
}

@Test
public void 나누기_결과가_정수가_아닐때() {
assertEquals(2, calculator.divide(5, 2));
assertEquals(0, calculator.divide(1, 2));
}
}
}
99 changes: 99 additions & 0 deletions src/test/java/StringCalculatorAssertJTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

public class StringCalculatorAssertJTest {

private final StringCalculator stringCalculator = new StringCalculator();

@Nested
@DisplayName("덧셈 테스트")
class AddTest {

@Test
void 빈_문자열() {
// Given
String input = "";

// When
int result = stringCalculator.add(input);

// Then
assertThat(result).isEqualTo(0);
}

@Test
void 하나의_숫자() {
// Given
String input = "1";

// When
int result = stringCalculator.add(input);

// Then
assertThat(result).isEqualTo(1);
}

@Test
void 두_숫자_더하기() {
// Given
String input = "1,2";

// When
int result = stringCalculator.add(input);

// Then
assertThat(result).isEqualTo(3);
}

@Test
void 여러_숫자_더하기() {
// Given
String input = "1,2,3";

// When
int result = stringCalculator.add(input);

// Then
assertThat(result).isEqualTo(6);
}

@Test
void 커스텀_구분자() {
// Given
String input = "//;\n4;5,1:2";

// When
int result = stringCalculator.add(input);

// Then
assertThat(result).isEqualTo(12);
}

@Test
void 음수_예외() {
// Given
String input = "-1";

// When & Then
assertThatThrownBy(() -> stringCalculator.add(input))
.isInstanceOf(RuntimeException.class)
.hasMessageContaining("음수는 허용되지 않습니다");

}

@Test
void 숫자가_아닌_예외() {
// Given
String input = "1,a";

// When & Then
assertThatThrownBy(() -> stringCalculator.add(input))
.isInstanceOf(RuntimeException.class)
.hasMessageContaining("숫자가 아닌 값이 포함되어 있습니다");
}
}
}
Loading