diff --git a/README.md b/README.md
index bd90ef0247..386df9fc42 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,152 @@
-# java-calculator-precourse
\ No newline at end of file
+# 기능목록
+
+## 도메인
+
+입력받은 문자열을 구분자를 이용해 나눈다.
+ - 구분자는 기본적으로 쉼표(,)와 콜론(:)이 포함되어야 한다.
+ - 문자열 앞부분의 //와 \n사이에 위치하는 문자를 커스텀 구분자로 추가해야한다.
+ - 커스텀 구분자는 숫자의 특성상 부호를 표기하는 +, -와 소숫점을 표현하는 .은 잘못된 것으로 처리하여 예외를 던진다.
+ - 구분자라는 특성상 커스텀 구분자의 속하는 문자열의 길이가 2이상일 경우 각각 하나의 문자를 커스텀 구분자로 사용한다.
+ - (예시) "//;^$\n1;2^3" 의 경우 ;^$라는 길이 3짜리 구분자를 사용하는 것이 아닌 ; ^ $ 이 셋을 각각 하나의 구분자로 사용한다.
+ - 기본 구분자 쉼표(,)와 콜론(:) 그리고 추가된 커스텀 문자를 제외한 문자열이 나타난 경우 잘못된 것으로 처리하여 예외를 던진다.
+ - 커스텀 구분자를 등록한 이후 숫자와 구분자가 있어야할 부분에서 숫자와 구분자가 번갈아 등장하지 않고 연속으로 등장한 경우 예외를 던진다.
+ - 이는 공백문자열로 나타날 것이므로, 나눠진 문자열의 목록을 숫자로 변환하는 부분에서 예외를 던진다.
+
+
+
+ 숫자의 제한조건은 양수라는 것 외에는 없다. 따라서 확장성을 위하여 문자를 숫자로 변환하는 객체를 따로 관리한다.
+ - 나눠진 문자열을 숫자로 변환한다.
+ - 변환한 숫자들을 더하여 문자로 반환한다.
+
+## 출력
+ - 프로그램 실행시 안내메시지를 출력한다.
+ - 결과를 출력한다.
+
+## 테스트
+ - 기본 구분자를 통해 문자열이 잘 나누어지는지 확인한다.
+ - 커스텀 구분자가 추가된 경우 문자열이 잘 나누어지는지 확인한다.
+ - 여러개의 커스텀 구분자가 추가된 경우도 확인한다.
+ - +, -, .이 커스텀 구분자로 포함될 경우 예외를 던진다.
+ - 구분자가 연속으로 등장한 경우 예외를 던진다.
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+
+## 학습 목표
+- Git, GitHub, IDE 등 실제 개발을 위한 환경에 익숙해진다.
+- 교육 분야에 맞는 프로그래밍 언어를 사용하여 간단한 문제를 해결한다.
+
+
+# 프리코스 진행 방식
+
+## 진행 방식
+
+- 미션은 **과제 진행 요구 사항, 기능 요구 사항, 프로그래밍 요구 사항** 세 가지로 구성되어 있다.
+- 세 개의 요구 사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다.
+- 기능 요구 사항에 기재되지 않은 내용은 스스로 판단하여 구현한다.
+- 매주 진행할 미션은 화요일 오후 3시부터 확인할 수 있으며, 다음 주 월요일까지 구현을 완료하여 제출해야 한다. 제출은 일요일 오후 3시부터 가능하다.
+ - 정해진 시간을 지키지 않을 경우 미션을 제출하지 않은 것으로 간주한다.
+ - 종료 일시 이후에는 추가 푸시를 허용하지 않는다.
+
+---
+
+
+
+## 미션 제출 방법
+
+- 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다.
+ - GitHub을 활용한 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고해 제출한다.
+- GitHub에 미션을 제출한 후 [우아한테크코스 지원 플랫폼](https://apply.techcourse.co.kr) 에 접속하여 프리코스 과제를 제출한다.
+ - 자세한 방법은 [링크](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#제출-가이드) 를 참고한다.
+ - 과제를 수행하면서 느낀 점, 배운 점, 많은 시간을 투자한 부분 등 자유롭게 작성한다.
+
+## 과제 제출 전 체크리스트
+
+- 기능을 올바르게 구현했더라도 **요구 사항에 명시된 출력 형식**을 따르지 않으면 0점을 받게 된다.
+- 기능 구현을 완료한 후 아래 가이드에 따라 모든 테스트가 성공적으로 실행되는지 확인한다.
+- **테스트가 실패하면 점수가 0점**이 되므로 제출하기 전에 반드시 확인한다.
+
+## 테스트 실행 가이드
+- 터미널에서 `java -version`을 실행하여 Java 버전이 21인지 확인한다. Eclipse 또는 IntelliJ IDEA와 같은 IDE에서 Java 21로 실행되는지 확인한다.
+- 터미널에서 Mac 또는 Linux 사용자의 경우 `./gradlew clean test` 명령을 실행하고, Windows 사용자의 경우 `gradlew.bat clean test`
+또는 .\gradlew.bat clean test 명령을 실행할 때 모든 테스트가 아래와 같이 통과하는지 확인한다.
+
+```
+BUILD SUCCESSFUL in 0s
+```
+
+
+
+
+
+# 문자열 덧셈 계산기
+
+---
+
+## 과제 진행 요구 사항
+
+---
+- 미션은 [문자열 덧셈 계산기 저장소](https://github.com/woowacourse-precourse/java-calculator-7)를 포크하고 클론하는 것으로 시작한다.
+- **기능을 구현하기 전 `README.md`에 구현할 기능 목록을 정리**해 추가한다.
+ - Git의 커밋 단위는 앞 단계에서 `README.md`에 정리한 기능 목록 단위로 추가한다.
+ - [AngularJS Git Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153)을 참고해 커밋 메시지를 작성한다.
+- 자세한 과제 진행 방법은 프리코스 진행 가이드 문서를 참고한다.
+
+
+
+## 기능 요구 사항
+입력한 문자열에서 숫자를 추출하여 더하는 계산기를 구현한다.
+- 쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환한다.
+ - 예: "" => 0, "1,2" => 3, "1,2,3" => 6, "1,2:3" => 6
+- 앞의 기본 구분자(쉼표, 콜론) 외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 "//"와 "\n" 사이에 위치하는 문자를 커스텀 구분자로 사용한다.
+ - 예를 들어 "//;\n1;2;3"과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.
+- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다.
+
+### 입출력 요구 사항
+#### 입력
+- 구분자와 양수로 구성된 문자열
+
+#### 출력
+- 덧셈 결과
+```
+결과 : 6
+```
+#### 실행 결과 예시
+```
+덧셈할 문자열을 입력해 주세요.
+1,2:3
+결과 : 6
+```
+
+
+## 프로그래밍 요구 사항
+
+---
+
+- JDK 21 버전에서 실행 가능해야 한다.
+- 프로그램을 실행하는 시작점은 `Application`의 `main()`이다.
+- build.gradle 파일은 변경할 수 없으며, **제공된 라이브러리 이외의 외부 라이브러리는 사용하지 않는다.**
+- 프로그램 종료 시 System.exit()를 호출하지 않는다.
+- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 등의 이름을 바꾸거나 이동하지 않는다.
+- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
+ - 기본적으로 Java Style Guide를 원칙으로 한다.
+
+### 라이브러리
+
+- `camp.nextstep.edu.missionutils`에서 제공하는 Console API를 사용하여 구현해야 한다.
+ - 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다.
+
+
+
diff --git a/src/main/java/calculator/Application.java b/src/main/java/calculator/Application.java
index 573580fb40..5b3517e5a0 100644
--- a/src/main/java/calculator/Application.java
+++ b/src/main/java/calculator/Application.java
@@ -2,6 +2,7 @@
public class Application {
public static void main(String[] args) {
- // TODO: 프로그램 구현
+ Calculator calculator = new Calculator();
+ calculator.run();
}
}
diff --git a/src/main/java/calculator/Calculator.java b/src/main/java/calculator/Calculator.java
new file mode 100644
index 0000000000..1dbe896c70
--- /dev/null
+++ b/src/main/java/calculator/Calculator.java
@@ -0,0 +1,32 @@
+package calculator;
+
+import calculator.domain.SumCalculator;
+import calculator.domain.stringsplitter.CustomStringSplitter;
+import calculator.domain.stringsplitter.DefaultStringSplitter;
+import calculator.domain.StringSplitterManager;
+import camp.nextstep.edu.missionutils.Console;
+
+import java.util.List;
+
+public class Calculator {
+
+ private final CalculatorView view = new CalculatorView();
+ private final StringSplitterManager splitterManager = new StringSplitterManager(
+ List.of(
+ new DefaultStringSplitter(),
+ new CustomStringSplitter()
+ )
+ );
+
+ public void run() {
+ String input = view.readInput();
+
+ List splitStrings = splitterManager.getSplitStrings(input);
+ SumCalculator sumCalculator = new SumCalculator(splitStrings);
+ String result = sumCalculator.calculateSum();
+
+ view.printOutput(result);
+
+ Console.close();
+ }
+}
diff --git a/src/main/java/calculator/CalculatorView.java b/src/main/java/calculator/CalculatorView.java
new file mode 100644
index 0000000000..cbde401d5c
--- /dev/null
+++ b/src/main/java/calculator/CalculatorView.java
@@ -0,0 +1,15 @@
+package calculator;
+
+import camp.nextstep.edu.missionutils.Console;
+
+public class CalculatorView {
+
+ public String readInput() {
+ System.out.println("덧셈할 문자열을 입력해 주세요.");
+ return Console.readLine();
+ }
+
+ public void printOutput(String str) {
+ System.out.println("결과 : " + str);
+ }
+}
diff --git a/src/main/java/calculator/domain/StringSplitterManager.java b/src/main/java/calculator/domain/StringSplitterManager.java
new file mode 100644
index 0000000000..838047ac87
--- /dev/null
+++ b/src/main/java/calculator/domain/StringSplitterManager.java
@@ -0,0 +1,23 @@
+package calculator.domain;
+
+import calculator.domain.stringsplitter.StringSplitter;
+
+import java.util.List;
+
+public class StringSplitterManager {
+
+ private final List stringSplitters;
+
+ public StringSplitterManager(List stringSplitters) {
+ this.stringSplitters = stringSplitters;
+ }
+
+ public List getSplitStrings(String str) {
+ StringSplitter stringSplitter = stringSplitters.stream()
+ .filter(splitter -> splitter.canSupport(str))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(str));
+
+ return stringSplitter.splitString(str);
+ }
+}
diff --git a/src/main/java/calculator/domain/SumCalculator.java b/src/main/java/calculator/domain/SumCalculator.java
new file mode 100644
index 0000000000..a81f8bc34e
--- /dev/null
+++ b/src/main/java/calculator/domain/SumCalculator.java
@@ -0,0 +1,34 @@
+package calculator.domain;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+public class SumCalculator {
+
+ private final List strings;
+
+ public SumCalculator(List strings) {
+ this.strings = strings;
+ }
+
+ public String calculateSum() {
+ BigDecimal sum = strings.stream()
+ .map(str -> convertToBigDecimal(str))
+ .reduce(new BigDecimal("0"), (o1, o2) -> o1.add(o2));
+
+ return sum.toString();
+ }
+
+ private BigDecimal convertToBigDecimal(String str) {
+ if (str.equals("0")) {
+ throw new IllegalArgumentException(strings.toString());
+ }
+
+ String positiveNumberPattern = "^[+]?[0-9]+([.][0-9]+)?";
+ if (!str.matches(positiveNumberPattern)) {
+ throw new IllegalArgumentException(strings.toString());
+ }
+
+ return new BigDecimal(str);
+ }
+}
diff --git a/src/main/java/calculator/domain/stringsplitter/CustomStringSplitter.java b/src/main/java/calculator/domain/stringsplitter/CustomStringSplitter.java
new file mode 100644
index 0000000000..efb3718212
--- /dev/null
+++ b/src/main/java/calculator/domain/stringsplitter/CustomStringSplitter.java
@@ -0,0 +1,93 @@
+package calculator.domain.stringsplitter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CustomStringSplitter implements StringSplitter {
+
+ private static final String CUSTOM_DELIMITER_HEADER = "\\/\\/";
+ private static final String CUSTOM_DELIMITER_FOOTER = "[(\n)(\\\\n)]";
+
+ @Override
+ public boolean canSupport(String str) {
+ String patternRegex = generatePatternRegex();
+ Pattern pattern = Pattern.compile(patternRegex);
+ Matcher matcher = pattern.matcher(str);
+ boolean isFound = matcher.matches();
+
+ if (isFound) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List splitString(String str) {
+ String patternRegex = generatePatternRegex();
+ Pattern pattern = Pattern.compile(patternRegex);
+ Matcher matcher = pattern.matcher(str);
+ matcher.matches();
+
+ String customDelimiter = matcher.group(1);
+ validateCustomDelimiter(customDelimiter, str);
+ String conjoinedDelimiter = DEFAULT_DELIMITER + customDelimiter;
+
+ String numbersAndDelimiter = matcher.group(2);
+ numbersAndDelimiter = replaceBackSlash(customDelimiter, numbersAndDelimiter);
+ List result = splitSubstring(conjoinedDelimiter, numbersAndDelimiter);
+ validateContinuousDelimiter(result, str);
+
+ return result;
+ }
+
+ private String replaceBackSlash(String customDelimiter, String numbersAndDelimiter) {
+ if (customDelimiter.contains("\\")) {
+ numbersAndDelimiter = numbersAndDelimiter.replace("\\", String.valueOf(DEFAULT_DELIMITER.charAt(0)));
+ }
+ return numbersAndDelimiter;
+ }
+
+ private String generatePatternRegex() {
+ StringBuilder delimiterBuilder = new StringBuilder();
+
+ delimiterBuilder.append("^")
+ .append(CUSTOM_DELIMITER_HEADER)
+ .append("([^0-9]+)")
+ .append(CUSTOM_DELIMITER_FOOTER)
+ .append("(.+)");
+
+ return delimiterBuilder.toString();
+ }
+
+ private void validateCustomDelimiter(String customDelimiter, String str) {
+ boolean hasInvalidDelimiter = Arrays.stream(customDelimiter.split(""))
+ .anyMatch(s -> INVALID_DELIMITER.contains(s));
+
+ if (hasInvalidDelimiter) {
+ throw new IllegalArgumentException(str);
+ }
+ }
+
+ private List splitSubstring(String conjoinedDelimiter, String numbersAndDelimiter) {
+ StringTokenizer stringTokenizer = new StringTokenizer(numbersAndDelimiter, conjoinedDelimiter);
+
+ List strings = new ArrayList<>();
+ while (stringTokenizer.hasMoreTokens()) {
+ strings.add(stringTokenizer.nextToken());
+ }
+ return strings;
+ }
+
+ private void validateContinuousDelimiter(List split, String str) {
+ boolean hasContinuousDelimiter = split.stream()
+ .anyMatch(s -> s.isEmpty());
+
+ if (hasContinuousDelimiter) {
+ throw new IllegalArgumentException(str);
+ }
+ }
+}
diff --git a/src/main/java/calculator/domain/stringsplitter/DefaultStringSplitter.java b/src/main/java/calculator/domain/stringsplitter/DefaultStringSplitter.java
new file mode 100644
index 0000000000..2fb6d1cfd8
--- /dev/null
+++ b/src/main/java/calculator/domain/stringsplitter/DefaultStringSplitter.java
@@ -0,0 +1,27 @@
+package calculator.domain.stringsplitter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DefaultStringSplitter implements StringSplitter {
+
+ @Override
+ public boolean canSupport(String str) {
+ Pattern pattern = Pattern.compile("^[0-9]+([" + DEFAULT_DELIMITER + "][0-9]+)*$");
+ Matcher matcher = pattern.matcher(str);
+ return matcher.find();
+ }
+
+ @Override
+ public List splitString(String str) {
+ StringTokenizer stringTokenizer = new StringTokenizer(str, DEFAULT_DELIMITER);
+ List strings = new ArrayList<>();
+ while (stringTokenizer.hasMoreTokens()) {
+ strings.add(stringTokenizer.nextToken());
+ }
+ return strings;
+ }
+}
diff --git a/src/main/java/calculator/domain/stringsplitter/StringSplitter.java b/src/main/java/calculator/domain/stringsplitter/StringSplitter.java
new file mode 100644
index 0000000000..e765c87605
--- /dev/null
+++ b/src/main/java/calculator/domain/stringsplitter/StringSplitter.java
@@ -0,0 +1,14 @@
+package calculator.domain.stringsplitter;
+
+import java.util.List;
+
+public interface StringSplitter {
+
+ static final String DEFAULT_DELIMITER = ":,";
+ static final String INVALID_DELIMITER = "+-.";
+
+ boolean canSupport(String str);
+
+ List splitString(String str);
+
+}
diff --git a/src/test/java/calculator/domain/CustomStringSplitterTest.java b/src/test/java/calculator/domain/CustomStringSplitterTest.java
new file mode 100644
index 0000000000..904f50d68d
--- /dev/null
+++ b/src/test/java/calculator/domain/CustomStringSplitterTest.java
@@ -0,0 +1,98 @@
+package calculator.domain;
+
+import calculator.domain.stringsplitter.CustomStringSplitter;
+import calculator.domain.stringsplitter.StringSplitter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.List;
+
+class CustomStringSplitterTest {
+
+ StringSplitter stringSplitter = new CustomStringSplitter();
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//;\\\n1'",
+ "'//;\\n1'",
+ "'//;\n1'",
+ "'///;*?!@#$\n1'"
+ })
+ void 커스텀_문자열_지원_TRUE(String input) {
+ Assertions.assertTrue(stringSplitter.canSupport(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//0\n3:4'",
+ "'3:4//i\n'"
+ })
+ void 커스텀_문자열_지원_FALSE(String input) {
+ Assertions.assertFalse(stringSplitter.canSupport(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//i\\n2\\23i4', '2', '23', '4'",
+ "'///i\n2/23i4', '2', '23', '4'"
+ })
+ void 커스텀_문자열_나누기(String input, String expected1, String expected2, String expected3) {
+ List strings = stringSplitter.splitString(input);
+
+ Assertions.assertTrue(strings.contains(expected1));
+ Assertions.assertTrue(strings.contains(expected2));
+ Assertions.assertTrue(strings.contains(expected3));
+ Assertions.assertTrue(strings.size() == 3);
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//*\n0*123,456:7890', '0', '123', '456', '7890'",
+ "'//**&^%\n0*123&456^7890', '0', '123', '456', '7890'"
+ })
+ void 커스텀_문자열_나누기_기본_구분자_혼합(String input, String expected1, String expected2, String expected3, String expected4) {
+ List strings = stringSplitter.splitString(input);
+
+ Assertions.assertTrue(strings.contains(expected1));
+ Assertions.assertTrue(strings.contains(expected2));
+ Assertions.assertTrue(strings.contains(expected3));
+ Assertions.assertTrue(strings.contains(expected4));
+ Assertions.assertTrue(strings.size() == 4);
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//*\n1', '1'",
+ "'//i\n2345678590', '2345678590'"
+ })
+ void 나누어진_크기가_1인_문자열(String input, String expected1) {
+ System.out.println(input);
+ List strings = stringSplitter.splitString(input);
+
+ Assertions.assertTrue(strings.contains(expected1));
+ Assertions.assertTrue(strings.size() == 1);
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//-\n12:34'",
+ "'//.\n12:34'",
+ "'//*-\n12:34'",
+ "'//+\n1245'"
+ })
+ void 허용되지_않는_커스텀_구분자_canSupport_메소드_통과(String input) {
+ Assertions.assertTrue(stringSplitter.canSupport(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'//-\n12:34'",
+ "'//.\n12:34'",
+ "'//*-\n12:34'",
+ "'//+\n1245'"
+ })
+ void 허용되지_않는_커스텀_구분자_예외_발생(String input) {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> stringSplitter.splitString(input));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/calculator/domain/DefaultStringSplitterTest.java b/src/test/java/calculator/domain/DefaultStringSplitterTest.java
new file mode 100644
index 0000000000..0647f64ecb
--- /dev/null
+++ b/src/test/java/calculator/domain/DefaultStringSplitterTest.java
@@ -0,0 +1,52 @@
+package calculator.domain;
+
+
+import calculator.domain.stringsplitter.DefaultStringSplitter;
+import calculator.domain.stringsplitter.StringSplitter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.util.List;
+
+public class DefaultStringSplitterTest {
+
+ StringSplitter stringSplitter = new DefaultStringSplitter();
+
+ @ParameterizedTest
+ @CsvSource({
+ "'1,2'",
+ "'1:2:3'",
+ "'45,67:89'"
+ })
+ void 기본_문자열_지원_TRUE(String input) {
+ Assertions.assertTrue(stringSplitter.canSupport(input));
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "6:3:2, '6', '3', '2'",
+ "'12,34,56', '12', '34', '56'",
+ "'100:200,300', '100', '200', '300'",
+ })
+ void 기본_문자열_나누기(String input, String expected1, String expected2, String expected3) {
+ List strings = stringSplitter.splitString(input);
+
+ Assertions.assertTrue(strings.contains(expected1));
+ Assertions.assertTrue(strings.contains(expected2));
+ Assertions.assertTrue(strings.contains(expected3));
+ Assertions.assertTrue(strings.size() == 3);
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "'1', '1'",
+ "'234567890', '234567890'"
+ })
+ void 나누어진_크기가_1인_문자열(String input, String expected1) {
+ List strings = stringSplitter.splitString(input);
+
+ Assertions.assertTrue(strings.contains(expected1));
+ Assertions.assertTrue(strings.size() == 1);
+ }
+}
diff --git a/src/test/java/calculator/domain/SumCalculatorTest.java b/src/test/java/calculator/domain/SumCalculatorTest.java
new file mode 100644
index 0000000000..28a0544411
--- /dev/null
+++ b/src/test/java/calculator/domain/SumCalculatorTest.java
@@ -0,0 +1,59 @@
+package calculator.domain;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SumCalculatorTest {
+
+ List list = new ArrayList<>();
+ SumCalculator sumCalculator = new SumCalculator(list);
+
+ @BeforeEach
+ void init() {
+ list.clear();
+ }
+
+ @Test
+ void 계산_테스트() {
+ list.add("1");
+ list.add("3.0123456789");
+
+ String result = sumCalculator.calculateSum();
+
+ Assertions.assertTrue(result.equals("4.0123456789"));
+ }
+
+ @Test
+ void 계산_테스트_2() {
+ list.add("0123");
+ list.add("0456");
+
+ String result = sumCalculator.calculateSum();
+
+ Assertions.assertTrue(result.equals("579"));
+ }
+
+ @Test
+ void 계산_테스트_음수() {
+ list.add("-1");
+ list.add("1234567890");
+
+ Assertions.assertThrows(IllegalArgumentException.class, () -> sumCalculator.calculateSum());
+
+ }
+
+ @Test
+ void 계산_테스트_0() {
+ list.add("1");
+ list.add("0");
+
+ Assertions.assertThrows(IllegalArgumentException.class, () -> sumCalculator.calculateSum());
+
+ }
+}
\ No newline at end of file