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단계 과제 제출합니다. #75

Merged
merged 10 commits into from
Feb 13, 2025
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ repositories {

dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation platform('org.assertj:assertj-bom:3.25.1')
seun0123 marked this conversation as resolved.
Show resolved Hide resolved
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
}

test {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/Calculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public int multiply(int num1, int num2) {
}

public int divide(int dividend, int divisor) {
if(divisor == 0){
throw new ArithmeticException("0으로 나눌 수 없습니다.");
if (divisor == 0) {
throw new ArithmeticException("Divide by zero");
}
return dividend / divisor;
}
Expand Down
57 changes: 57 additions & 0 deletions src/main/java/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringCalculator {


private static int[] expressionToTokens(String expression) {
if (expression.isEmpty()) {
return new int[]{0};
}

String tokens = expression;
String delimiters = "[,:]";

if (expression.contains("//") && expression.contains("\n")) {
String customDelimiter = extractCustomDelimiter(expression);
tokens = extractToken(expression);
delimiters = "[,:]" + "|" + customDelimiter;
}

String[] splitTokens = tokens.split(delimiters);
return stringArrayToIntArray(splitTokens);
}

private static String extractCustomDelimiter(String expression) {
Pattern pattern = Pattern.compile("//(.*?)\n");
Matcher matcher = pattern.matcher(expression);
if (matcher.find()) {
return Pattern.quote(matcher.group(1));
}
throw new IllegalArgumentException("Invalid custom delimiter format");
}

private static String extractToken(String expression) {
return expression.replaceFirst("//.*?\n", ",");
}

private static int[] stringArrayToIntArray(String[] expression) {
try{
return Arrays.stream(expression).mapToInt(Integer::parseInt).toArray();
} catch (NumberFormatException e) {
throw new RuntimeException("Contains non-numerical values.");
}
}

public int add(String expression) {
int[] tokens = expressionToTokens(expression);

int answer = tokens[0];
for (int i = 1; i < tokens.length; i++) {
answer += tokens[i];
}
return answer;
}
}

86 changes: 65 additions & 21 deletions src/test/java/CalculatorTest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Nested;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class CalculatorTest {

Expand All @@ -11,14 +13,26 @@ public class CalculatorTest {
@DisplayName("덧셈 테스트")
class addTest {

private final Calculator calculator = new Calculator();

@Test
@DisplayName("정수의 ")
void add_Test() {
@DisplayName("정수의 합을 반환한다.")
void shouldReturnSumOfTwoIntegers() {
final int a = 3;
final int b = 5;
final int actual = a+b;
final int actual = 8;
seun0123 marked this conversation as resolved.
Show resolved Hide resolved

assertThat(actual).isEqualTo(calculator.add(a, b));
}

@Test
@DisplayName("두 음수 정수의 합을 반환한다.")
void shouldReturnSumOfTwoNegativeIntegers() {
final int a = -3;
final int b = -5;
final int actual = -8;

assertEquals(actual, calculator.add(a,b));
assertThat(actual).isEqualTo(calculator.add(a, b));
}
}

Expand All @@ -27,13 +41,23 @@ void add_Test() {
class subtractTest {

@Test
@DisplayName("정수의 ")
void subtract_Test() {
@DisplayName("정수의 차를 반환한다.")
void shouldReturnSubtractOfTwoIntegers() {
final int a = 5;
final int b = 3;
final int actual = a-b;
final int actual = 2;

assertThat(actual).isEqualTo(calculator.subtract(a, b));
}

assertEquals(actual, calculator.subtract(a,b));
@Test
@DisplayName("두 음수 정수의 차를 반환한다.")
void shouldReturnSubtractOfTwoNegativeIntegers() {
final int a = -5;
final int b = -3;
final int actual = -2;

assertThat(actual).isEqualTo(calculator.subtract(a, b));
}
}

Expand All @@ -42,13 +66,23 @@ void subtract_Test() {
class multiplyTest {

@Test
@DisplayName("정수의 곱셈")
void multiply_Test() {
@DisplayName("정수의 곱을 반환한다.")
void shouldReturnMultiplyOfTwoIntegers() {
final int a = 5;
final int b = 3;
final int actual = a*b;
final int actual = 15;

assertThat(actual).isEqualTo(calculator.multiply(a, b));
}

@Test
@DisplayName("두 음수 정수의 곱을 반환한다.")
void shouldReturnMultiplyOfTwoNegativeIntegers() {
final int a = -5;
final int b = -3;
final int actual = 15;

assertEquals(actual, calculator.multiply(a,b));
assertThat(actual).isEqualTo(calculator.multiply(a, b));
}
}

Expand All @@ -57,22 +91,32 @@ void multiply_Test() {
class divideTest {

@Test
@DisplayName("정수의 나눗셈")
void divide_Test() {
@DisplayName("정수의 몫을 반환한다.")
void shouldReturnDivideOfTwoIntegers() {
final int a = 15;
final int b = 3;
final int actual = a/b;
final int actual = 5;

assertThat(actual).isEqualTo(calculator.divide(a, b));
}

@Test
@DisplayName("두 음수 정수의 몫을 반환한다.")
void shouldReturnDivideOfTwoNegativeIntegers() {
final int a = -15;
final int b = -3;
final int actual = 5;

assertEquals(actual, calculator.divide(a,b));
assertThat(actual).isEqualTo(calculator.divide(a, b));
}

@Test
@DisplayName("0으로 나누었을 때 ArithmeticException 예외 발생")
void divideWithZero_Test() {
@DisplayName("정수를 0으로 나누면 ArithmeticException이 발생한다.")
void shouldReturnDivideWithZeroOfTwoIntegers() {
final int a = 15;
final int b = 0;

assertThrows(ArithmeticException.class, () -> calculator.divide(a,b));
assertThatThrownBy(() -> calculator.divide(a, b)).isInstanceOf(ArithmeticException.class);
}
}
}
97 changes: 97 additions & 0 deletions src/test/java/StringCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class StringCalculatorTest {

private final StringCalculator stringCalculator = new StringCalculator();

@Nested
@DisplayName("입력된 문자열 합 계산")
seun0123 marked this conversation as resolved.
Show resolved Hide resolved
class addTest {

@Test
@DisplayName("쉼표와 콜론을 구분자로 가지는 문자열의 합을 반환한다.")
void shouldReturnSumOfString() {
final String expression = "1,2:3";
assertThat(6).isEqualTo(stringCalculator.add(expression));
}

@Test
@DisplayName("숫자 한 개만 입력된 경우 해당 숫자를 반환한다.")
void shouldReturnSumOfChar() {
final String expression = "1";
assertThat(1).isEqualTo(stringCalculator.add(expression));
}
}

@Nested
@DisplayName("커스텀 구분자를 포함한 문자열 합 계산")
class CustomDelimiterTest {

@Test
@DisplayName("커스텀 구분자를 사용한 문자열의 합을 반환한다.")
void shouldReturnSumWithCustomDelimiterOfString() {
final String expression = "1//;\n2,3:4";
assertThat(stringCalculator.add(expression)).isEqualTo(10);
}

@Test
@DisplayName("커스텀 구분자와 기본 구분자를 함께 사용한 문자열의 합을 반환한다.")
void shouldReturnSumWithCustomDelimiterAndDefaultDelimiterOfString() {
final String expression = "1//***\n2,3***4";
assertThat(stringCalculator.add(expression)).isEqualTo(10);
}

@Test
@DisplayName("커스텀 구분자가 여러 개 문자를 포함할 때 문자열의 합을 반환한다.")
void shouldReturnSumWithCustomDelimitersOfString() {
final String expression = "1//**\n2**3**4";
assertThat(stringCalculator.add(expression)).isEqualTo(10);
}
}

@Nested
@DisplayName("예외 발생")
class ExceptionTest {

@Test
@DisplayName("숫자가 아닌 문자열이 입력 되었을 때 RuntimeException이 발생한다.")
void shouldReturnRuntimeExceptionToNumberFormatException() {
final String expression = "example";
assertThatThrownBy(() -> stringCalculator.add(expression)).isInstanceOf(RuntimeException.class);
}

@Test
@DisplayName("빈 문자열이 입력된 경우 0을 반환한다.")
void shouldReturnZeroWhenEmptyStringIsEntered() {
final String expression = "";
assertThat(stringCalculator.add(expression)).isEqualTo(0);
}

@Test
@DisplayName("구분자만 입력된 경우 RuntimeException이 발생한다.")
void shouldThrowRuntimeExceptionWhenOnlyDelimitersAreEntered() {
final String expression = ",,,";
assertThatThrownBy(() -> stringCalculator.add(expression)).isInstanceOf(RuntimeException.class);
}

@Test
@DisplayName("커스텀 구분자 사이에 공백이 포함된 경우 RuntimeException이 발생한다.")
void shouldThrowRuntimeExceptionWhenSpaceExistsBetweenCustomDelimiters() {
final String expression = "1//;\n2; 3;4";
assertThatThrownBy(() -> stringCalculator.add(expression)).isInstanceOf(RuntimeException.class);
}

@Test
@DisplayName("커스텀 구분자를 잘못된 방식으로 입력한 경우 RuntimeException이 발생한다.")
void shouldThrowRuntimeExceptionWhenInvalidCustomDelimiterFormatIsUsed() {
final String expression = "//;\n1;2;3;";
assertThatThrownBy(() -> stringCalculator.add(expression)).isInstanceOf(RuntimeException.class);
}

}
}