Skip to content
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단계 과제 제출합니다. #74

Merged
merged 11 commits into from
Feb 13, 2025
Merged
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ repositories {
dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.assertj:assertj-core')
}

test {
Expand Down
62 changes: 62 additions & 0 deletions src/main/java/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import java.util.regex.Pattern;

public class StringCalculator {

// 기본 구분자
private static final String DEFAULT_DELIMITER = "[,|:]";
private static final String CUSTOM_DELIMITER_PREFIX = "//";
private static final String NEW_LINE = "\n";
private static final int CUSTOM_DELIMITER_PREFIX_LENGTH = 2;

public static int add(String input) {
if (input.isEmpty()) {
return 0;
}

String delimiter = DEFAULT_DELIMITER; // 기본 구분자 정의

if (input.startsWith(CUSTOM_DELIMITER_PREFIX)) { // 커스텀 구분자 처리 (여러 글자 지원)
int delimiterEnd = input.indexOf(NEW_LINE);
String customDelimiter = input.substring(CUSTOM_DELIMITER_PREFIX_LENGTH, delimiterEnd);
delimiter = DEFAULT_DELIMITER + "|" + Pattern.quote(customDelimiter);
input = input.substring(delimiterEnd + 1);
}

Pattern pattern = Pattern.compile(delimiter);
String[] numbers = pattern.split(input);
return sum(numbers);
}

private static int sum(String[] numbers) { // 문자열을 숫자로 변환하여 합을 계산
int sum = 0;
StringBuilder negativeNumbers = new StringBuilder(); // 음수값을 저장

for (String num : numbers) {
int value = parseAndValidateNumber(num, negativeNumbers); // 숫자 변환 및 검증
sum += value;
}

// 음수값이 존재하면 예외 발생
if (!negativeNumbers.isEmpty()) {
throw new RuntimeException("입력한 값 중 음수 값이 존재합니다: " + negativeNumbers.toString().trim());
}

return sum;
}

private static int parseAndValidateNumber(String num, StringBuilder negativeNumbers) {
int value;

try {
value = Integer.parseInt(num);
} catch (NumberFormatException e) {
throw new RuntimeException("Invalid input: 숫자가 아닌 값이 포함되었습니다.");
}

if (value < 0) {
negativeNumbers.append(value).append(" ");
}

return value;
}
}
81 changes: 81 additions & 0 deletions src/test/java/StringCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import org.junit.jupiter.api.DisplayName;
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;

public class StringCalculatorTest {

@Test
@DisplayName("입력값이 비어있는 경우 테스트")
void testEmptyStringReturnsZero() {
assertThat(StringCalculator.add(""))
.isEqualTo(0);
}

@ParameterizedTest
@DisplayName("단일 숫자 입력 테스트")
@CsvSource({
"1, 1",
"5, 5",
"10, 10"
})
void testSingleNumber(String input, int expected) {
assertThat(StringCalculator.add(input)).isEqualTo(expected);
}

@Test
@DisplayName("콤마로 구분한 숫자 합산 기능")
void testTwoNumbersWithComma() {
assertThat(StringCalculator.add("1,2")).isEqualTo(3);
}

@Test
@DisplayName("콤마와 콜론으로 구분한 숫자 합산 기능")
void testMultipleNumbersWithCommaAndColon() {
assertThat(StringCalculator.add("1,2:3")).isEqualTo(6);
}

@Test
@DisplayName("커스텀 구분자를 사용한 숫자 합산 기능")
void testCustomDelimiter() {
assertThat(StringCalculator.add("//;\n1;2;3")).isEqualTo(6);
assertThat(StringCalculator.add("//|\n2|3|5")).isEqualTo(10);
assertThat(StringCalculator.add("//|\n2,3|50")).isEqualTo(55);
}

@ParameterizedTest
@DisplayName("특수문자가 포함된 커스텀 구분자를 사용한 숫자 합산 기능")
@CsvSource({
"'//.\n2.3.5', 10",
"'//$\n1$2$3', 6"
})
void testCustomDelimiterWithSpecialCharacters(String input, int expected) {
assertThat(StringCalculator.add(input)).isEqualTo(expected);
}

@Test
@DisplayName("입력값 중 음수가 존재하는 경우 예외 발생")
void testNegativeNumbersThrowException() {
String input = "1,-2,3";
String expectedMessage = "입력한 값 중 음수 값이 존재합니다: -2";

assertThatThrownBy(() -> StringCalculator.add(input))
.isInstanceOf(RuntimeException.class)
.hasMessage(expectedMessage); // 예외 메시지가 정확히 일치하는지 검증
}

@Test
@DisplayName("입력값이 숫자가 아닌 값이 존재하는 경우 예외 발생")
void testNonNumericValuesThrowException() {
assertThatThrownBy(() -> StringCalculator.add("1,a,3"))
.isInstanceOf(RuntimeException.class)
.hasMessage("Invalid input: 숫자가 아닌 값이 포함되었습니다.");

assertThatThrownBy(() -> StringCalculator.add("//;\n1;B;3"))
.isInstanceOf(RuntimeException.class)
.hasMessage("Invalid input: 숫자가 아닌 값이 포함되었습니다.");
}
}