From 07ffd9fe0c663706825e438bfbb1c3fe6caf10fe Mon Sep 17 00:00:00 2001 From: Heesoo Date: Wed, 25 Sep 2024 15:01:33 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[feat]=20StringCalculator=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/study/StringCalculator.java | 58 +++++++++++++++++++ .../study/StringCalculatorApplication.java | 8 +++ src/test/java/study/StringCalculatorTest.java | 28 +++++++++ src/test/java/study/StringTest.java | 13 ----- 4 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/main/java/study/StringCalculator.java create mode 100644 src/main/java/study/StringCalculatorApplication.java create mode 100644 src/test/java/study/StringCalculatorTest.java delete mode 100644 src/test/java/study/StringTest.java diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java new file mode 100644 index 0000000..9bcb4af --- /dev/null +++ b/src/main/java/study/StringCalculator.java @@ -0,0 +1,58 @@ +package study; +import java.util.Scanner; + + +public class StringCalculator { + private String[] values; + private int total; + + public StringCalculator(){ + Scanner scanner = new Scanner(System.in); + String value = scanner.nextLine(); + values = value.split(" "); + + total = Integer.parseInt(values[0]); + + for (int i=1; i Date: Thu, 26 Sep 2024 15:36:55 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[update]=20=EC=98=88=EC=99=B8=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/study/StringCalculator.java | 46 +++++++++------- .../study/StringCalculatorApplication.java | 8 ++- .../exception/DivisionZeroException.java | 9 ++++ .../exception/InvalidFormatException.java | 9 ++++ .../exception/InvalidInputException.java | 10 ++++ .../study/exception/enumclass/ErrorCode.java | 25 +++++++++ src/test/java/study/StringCalculatorTest.java | 54 ++++++++++++++----- 7 files changed, 127 insertions(+), 34 deletions(-) create mode 100644 src/main/java/study/exception/DivisionZeroException.java create mode 100644 src/main/java/study/exception/InvalidFormatException.java create mode 100644 src/main/java/study/exception/InvalidInputException.java create mode 100644 src/main/java/study/exception/enumclass/ErrorCode.java diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java index 9bcb4af..4c7b491 100644 --- a/src/main/java/study/StringCalculator.java +++ b/src/main/java/study/StringCalculator.java @@ -1,25 +1,41 @@ package study; +import study.exception.DivisionZeroException; +import study.exception.InvalidFormatException; +import study.exception.enumclass.ErrorCode; +import study.exception.InvalidInputException; + import java.util.Scanner; public class StringCalculator { - private String[] values; private int total; - public StringCalculator(){ - Scanner scanner = new Scanner(System.in); - String value = scanner.nextLine(); - values = value.split(" "); + public StringCalculator(String value){ + String[] values = value.split(" "); - total = Integer.parseInt(values[0]); + try{ + total = Integer.parseInt(values[0]); - for (int i=1; i new StringCalculator(input)); + + assertEquals(exception.getMessage(), ErrorCode.INVALID_INPUT.getMessage()); + } + + @ParameterizedTest + @CsvSource(value = {"3 / 0", "3 + 2 / 0", "4 * 2 / 0 + 7"}) + @DisplayName("0으로 나눌 경우 DivisionZeroException 발생") + void divisionZero_divisionZeroException(String input){ + DivisionZeroException exception = assertThrows(DivisionZeroException.class, + () -> new StringCalculator(input)); - StringCalculator calculator = new StringCalculator(); - assertEquals(calculator.getTotal(), expected); + assertEquals(exception.getMessage(), ErrorCode.DIVISION_ZERO.getMessage()); + } + + @ParameterizedTest + @CsvSource(value = {"3 / ", "65 + 2 *", "2 - 3 + "}) + @DisplayName("완벽하지 않은 수식을 입력할 경우 InvalidFormatException 발생") + void notPerfectFormat_InvalidFormatException(String input){ + InvalidFormatException exception = assertThrows(InvalidFormatException.class, + () -> new StringCalculator(input)); + assertEquals(exception.getMessage(), ErrorCode.INVALID_FORMAT.getMessage()); } } From 0284e55fd1576946d462c61d253714c00523c73b Mon Sep 17 00:00:00 2001 From: Heesoo Date: Thu, 26 Sep 2024 16:57:49 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[update]=20=EC=98=88=EC=99=B8=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ src/main/java/study/exception/DivisionZeroException.java | 5 +++++ src/main/java/study/exception/InvalidFormatException.java | 6 ++++++ src/main/java/study/exception/InvalidInputException.java | 6 +++++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8172fb7..f29dbd9 100644 --- a/build.gradle +++ b/build.gradle @@ -5,11 +5,14 @@ group = 'camp.nextstep' version = '1.0.0' sourceCompatibility = '1.8' + repositories { mavenCentral() } dependencies { + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' + implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' testImplementation "org.junit.jupiter:junit-jupiter:5.7.2" testImplementation "org.assertj:assertj-core:3.19.0" } diff --git a/src/main/java/study/exception/DivisionZeroException.java b/src/main/java/study/exception/DivisionZeroException.java index a0c28c4..f63fc13 100644 --- a/src/main/java/study/exception/DivisionZeroException.java +++ b/src/main/java/study/exception/DivisionZeroException.java @@ -1,9 +1,14 @@ package study.exception; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import study.exception.enumclass.ErrorCode; public class DivisionZeroException extends RuntimeException{ + private static final Logger logger = LoggerFactory.getLogger(DivisionZeroException.class); + public DivisionZeroException(ErrorCode errorCode) { super(errorCode.getMessage()); + logger.error("DivisionZeroException 발생: {}", errorCode.getMessage()); } } diff --git a/src/main/java/study/exception/InvalidFormatException.java b/src/main/java/study/exception/InvalidFormatException.java index bcf17f0..45504c3 100644 --- a/src/main/java/study/exception/InvalidFormatException.java +++ b/src/main/java/study/exception/InvalidFormatException.java @@ -1,9 +1,15 @@ package study.exception; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import study.exception.enumclass.ErrorCode; + public class InvalidFormatException extends RuntimeException{ + private static final Logger logger = LoggerFactory.getLogger(InvalidFormatException.class); + public InvalidFormatException(ErrorCode errorCode) { super(errorCode.getMessage()); + logger.error("InvalidFormatException 발생: {}", errorCode.getMessage()); } } diff --git a/src/main/java/study/exception/InvalidInputException.java b/src/main/java/study/exception/InvalidInputException.java index 66a66bf..9f1d931 100644 --- a/src/main/java/study/exception/InvalidInputException.java +++ b/src/main/java/study/exception/InvalidInputException.java @@ -1,10 +1,14 @@ package study.exception; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import study.exception.enumclass.ErrorCode; public class InvalidInputException extends RuntimeException{ + private static final Logger logger = LoggerFactory.getLogger(InvalidInputException.class); + public InvalidInputException(ErrorCode errorCode) { super(errorCode.getMessage()); + logger.error("InvalidInputException 발생: {}", errorCode.getMessage()); } } From 76f9c1b940ba4cad29d5ba46ff92d994e1fca076 Mon Sep 17 00:00:00 2001 From: Heesoo Date: Thu, 26 Sep 2024 17:00:46 +0900 Subject: [PATCH 4/6] =?UTF-8?q?[refactor]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/study/StringCalculator.java | 6 ------ src/main/java/study/StringCalculatorApplication.java | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java index 4c7b491..c9bc991 100644 --- a/src/main/java/study/StringCalculator.java +++ b/src/main/java/study/StringCalculator.java @@ -32,12 +32,6 @@ public StringCalculator(String value){ } - public String getFormula(){ - Scanner scanner = new Scanner(System.in); - System.out.println("수식을 입력해주세요: "); - return scanner.nextLine(); - } - public void calculator(String nowValue, int nextValue){ switch (nowValue){ case "+": diff --git a/src/main/java/study/StringCalculatorApplication.java b/src/main/java/study/StringCalculatorApplication.java index d763d8a..f8a922d 100644 --- a/src/main/java/study/StringCalculatorApplication.java +++ b/src/main/java/study/StringCalculatorApplication.java @@ -9,6 +9,6 @@ public static void main(String[] args){ String value = scanner.nextLine(); StringCalculator calculator = new StringCalculator(value); - System.out.println(calculator.getTotal()); + System.out.println("계산 결과 : " + calculator.getTotal()); } } From 7ee9d99178101c17c62b9368faf0546050961806 Mon Sep 17 00:00:00 2001 From: Heesoo Date: Tue, 1 Oct 2024 23:18:21 +0900 Subject: [PATCH 5/6] =?UTF-8?q?[refactor]=20=ED=81=B4=EB=9E=98=EC=8A=A4,?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80=EB=A1=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=B6=84=EB=A6=AC,=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/study/StringCalculator.java | 60 ------------------- .../study/StringCalculatorApplication.java | 12 ++-- .../study/exception/enumclass/ErrorCode.java | 6 +- .../java/study/model/CalculatorScanner.java | 28 +++++++++ src/main/java/study/model/Operator.java | 41 +++++++++++++ .../java/study/model/StringCalculator.java | 43 +++++++++++++ 6 files changed, 122 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/study/StringCalculator.java create mode 100644 src/main/java/study/model/CalculatorScanner.java create mode 100644 src/main/java/study/model/Operator.java create mode 100644 src/main/java/study/model/StringCalculator.java diff --git a/src/main/java/study/StringCalculator.java b/src/main/java/study/StringCalculator.java deleted file mode 100644 index c9bc991..0000000 --- a/src/main/java/study/StringCalculator.java +++ /dev/null @@ -1,60 +0,0 @@ -package study; -import study.exception.DivisionZeroException; -import study.exception.InvalidFormatException; -import study.exception.enumclass.ErrorCode; -import study.exception.InvalidInputException; - -import java.util.Scanner; - - -public class StringCalculator { - private int total; - - public StringCalculator(String value){ - String[] values = value.split(" "); - - try{ - total = Integer.parseInt(values[0]); - - for (int i=1; i= values.length){ + throw new InvalidFormatException(ErrorCode.INVALID_FORMAT); + } + return parseInteger(values[index]); + } + + public int parseInteger(String value){ + try{ + return Integer.parseInt(value); + } catch (NumberFormatException e){ + throw new InvalidInputException(ErrorCode.NON_NUMERIC_INPUT); + } + } + + + +} From eb91e54a5b4c6c961a0de168ecd541d9e3b15df6 Mon Sep 17 00:00:00 2001 From: Heesoo Date: Tue, 1 Oct 2024 23:18:39 +0900 Subject: [PATCH 6/6] =?UTF-8?q?[test]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/study/CalculatorScannerTest.java | 53 ++++++++ src/test/java/study/OperatorTest.java | 118 ++++++++++++++++++ src/test/java/study/StringCalculatorTest.java | 114 ++++++++++++++--- 3 files changed, 268 insertions(+), 17 deletions(-) create mode 100644 src/test/java/study/CalculatorScannerTest.java create mode 100644 src/test/java/study/OperatorTest.java diff --git a/src/test/java/study/CalculatorScannerTest.java b/src/test/java/study/CalculatorScannerTest.java new file mode 100644 index 0000000..8dff9e1 --- /dev/null +++ b/src/test/java/study/CalculatorScannerTest.java @@ -0,0 +1,53 @@ +package study; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import study.exception.InvalidInputException; +import study.exception.enumclass.ErrorCode; +import study.model.CalculatorScanner; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CalculatorScannerTest { + + @Test + @DisplayName("사용자 입력 성공") + void getInput_success(){ + // given + String input = "2 + 2"; + InputStream in = new ByteArrayInputStream(input.getBytes()); + System.setIn(in); + + CalculatorScanner scanner = new CalculatorScanner(); + + // when + String result = scanner.getInput(); + + // then + assertEquals(result, input); + } + + + @Test + @DisplayName("사용자 입력 시 공백 입력한 경우") + void getInputEmpty_invalidInputException(){ + // given + String input = ""; + InputStream in = new ByteArrayInputStream(input.getBytes()); + System.setIn(in); + + CalculatorScanner scanner = new CalculatorScanner(); + + // when + InvalidInputException fail = assertThrows(InvalidInputException.class, + () -> scanner.getInput()); + + // then + assertEquals(fail.getMessage(), ErrorCode.EMPTY_INPUT.getMessage()); + } + +} diff --git a/src/test/java/study/OperatorTest.java b/src/test/java/study/OperatorTest.java new file mode 100644 index 0000000..5436e81 --- /dev/null +++ b/src/test/java/study/OperatorTest.java @@ -0,0 +1,118 @@ +package study; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import study.exception.DivisionZeroException; +import study.exception.InvalidFormatException; +import study.exception.enumclass.ErrorCode; +import study.model.Operator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class OperatorTest { + private Operator operator; + + @BeforeEach + void setUp(){ + operator = new Operator(); + } + + @Test + @DisplayName("연산자 구분 함수 성공") + void executeOperator_success(){ + // given + String operators = "+"; + int nowValue = 1; + int nextValue = 2; + + // when + int result = operator.execute(operators, nowValue, nextValue); + + // then + assertEquals(result, 1+2); + } + + @Test + @DisplayName("switch 문에 존재하지 않는 연산자 제공한 경우") + void executeOperator_InvalidFormatException(){ + // given + String operators = " "; + int nowValue = 3; + int nextValue = 2; + + // when + InvalidFormatException fail = assertThrows(InvalidFormatException.class, () -> operator.execute(operators, nowValue, nextValue)); + + // then + assertEquals(fail.getMessage(), ErrorCode.INVALID_FORMAT.getMessage()); + } + + @Test + @DisplayName("더하기 함수 성공") + void add_success(){ + // given + int num1 = 1, num2 = 2; + + // when + int result = operator.add(num1, num2); + + // then + assertEquals(result, 3); + } + + @Test + @DisplayName("빼기 함수 성공") + void minus_success(){ + // given + int num1 = 1, num2 = 2; + + // when + int result = operator.minus(num1, num2); + + // then + assertEquals(result, -1); + } + + @Test + @DisplayName("곱하기 함수 성공") + void multiply_success(){ + // given + int num1 = 5, num2 = 2; + + // when + int result = operator.multiply(num1, num2); + + // then + assertEquals(result, 10); + } + + @Test + @DisplayName("나누기 함수 성공") + void divide_success(){ + // given + int num1 = 5, num2 = 2; + + // when + int result = operator.divide(num1, num2); + + // then + assertEquals(result, 2); + } + + @Test + @DisplayName("0으로 나눈 경우") + void divideZero_divisionZeroException(){ + // given + int num1 = 5, num2 = 0; + + // when + DivisionZeroException fail = assertThrows(DivisionZeroException.class, + () -> operator.divide(num1, num2)); + + // then + assertEquals(fail.getMessage(), ErrorCode.DIVISION_ZERO.getMessage()); + } + +} diff --git a/src/test/java/study/StringCalculatorTest.java b/src/test/java/study/StringCalculatorTest.java index 3893c7e..da79d52 100644 --- a/src/test/java/study/StringCalculatorTest.java +++ b/src/test/java/study/StringCalculatorTest.java @@ -1,6 +1,6 @@ package study; - +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -9,46 +9,126 @@ import study.exception.InvalidFormatException; import study.exception.enumclass.ErrorCode; import study.exception.InvalidInputException; +import study.model.StringCalculator; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; public class StringCalculatorTest { + + private StringCalculator calculator; + + @BeforeEach + void setUp(){ + calculator = new StringCalculator(); + } + @ParameterizedTest @CsvSource(value = {"2 + 3 * 4 / 2, 10", "2 - 3 / 4 + 7, 7", "10 + 3 * 86 - 20, 1098"}) - @DisplayName("올바른 문자열 입력을 통해 올바른 계산 결과가 나온 경우") + @DisplayName("StringCalculator 계산 성공") void stringCalculator_success(String input, int expected){ - StringCalculator calculator = new StringCalculator(input); - assertEquals(calculator.getTotal(), expected); + // given + // when + int result = calculator.calculate(input); + + // then + assertEquals(result, expected); } @ParameterizedTest @CsvSource(value = {"d + 3 * 4 / 2", "2 - ( / 4 + 7", "10 + 3 * 86 - #", "6 + number * 5 / 20"}) - @DisplayName("입력한 문자가 숫자가 아닌 경우 InvalidInputException 발생") + @DisplayName("입력한 문자가 숫자가 아닌 경우") void inputNotNumberAtFirst_invalidInputException(String input){ - InvalidInputException exception = assertThrows(InvalidInputException.class, - () -> new StringCalculator(input)); + // given + // when + InvalidInputException fail = assertThrows(InvalidInputException.class, + () -> calculator.calculate(input)); - assertEquals(exception.getMessage(), ErrorCode.INVALID_INPUT.getMessage()); + // then + assertEquals(fail.getMessage(), ErrorCode.NON_NUMERIC_INPUT.getMessage()); } @ParameterizedTest @CsvSource(value = {"3 / 0", "3 + 2 / 0", "4 * 2 / 0 + 7"}) - @DisplayName("0으로 나눌 경우 DivisionZeroException 발생") + @DisplayName("0으로 나눌 경우") void divisionZero_divisionZeroException(String input){ - DivisionZeroException exception = assertThrows(DivisionZeroException.class, - () -> new StringCalculator(input)); + // given + // when + DivisionZeroException fail = assertThrows(DivisionZeroException.class, + () -> calculator.calculate(input)); - assertEquals(exception.getMessage(), ErrorCode.DIVISION_ZERO.getMessage()); + // then + assertEquals(fail.getMessage(), ErrorCode.DIVISION_ZERO.getMessage()); } @ParameterizedTest @CsvSource(value = {"3 / ", "65 + 2 *", "2 - 3 + "}) - @DisplayName("완벽하지 않은 수식을 입력할 경우 InvalidFormatException 발생") - void notPerfectFormat_InvalidFormatException(String input){ - InvalidFormatException exception = assertThrows(InvalidFormatException.class, - () -> new StringCalculator(input)); + @DisplayName("완벽하지 않은 수식을 입력할 경우") + void notPerfectFormat_invalidFormatException(String input){ + // given + // when + InvalidFormatException fail = assertThrows(InvalidFormatException.class, + () -> calculator.calculate(input)); + + // then + assertEquals(fail.getMessage(), ErrorCode.INVALID_FORMAT.getMessage()); + } + + @Test + @DisplayName("계산에 사용할 다음 숫자 구하는 함수 테스트 성공") + void getNextValue_success(){ + // given + String[] values = {"1", "+", "2"}; + int index = 2; + + // when + int result = calculator.getNextValue(values, index); - assertEquals(exception.getMessage(), ErrorCode.INVALID_FORMAT.getMessage()); + // then + assertEquals(result, 2); } + + @Test + @DisplayName("계산에 사용할 다음 숫자를 구하는 함수 테스트 중 배열의 범위가 넘은 경우") + void getNextValue_invalidFormatException(){ + // given + String[] values = {"1", "+", "2"}; + int index = 10; + + // when + InvalidFormatException fail = assertThrows(InvalidFormatException.class, + () -> calculator.getNextValue(values, index)); + + // then + assertEquals(fail.getMessage(), ErrorCode.INVALID_FORMAT.getMessage()); + } + + @Test + @DisplayName("String 을 Integer 로 변경하는 함수 테스트 성공") + void parseInteger_success(){ + // given + String value = "10"; + + // when + int result = calculator.parseInteger(value); + + // then + assertEquals(result, 10); + } + + @Test + @DisplayName("String 을 Integer 변경 시 실패로 인한 InvalidInputException 발생한 경우") + void parseInteger_invalidInputException(){ + // given + String value = "#"; + + // when + InvalidInputException fail = assertThrows(InvalidInputException.class, + () -> calculator.parseInteger(value)); + + // then + assertEquals(fail.getMessage(), ErrorCode.NON_NUMERIC_INPUT.getMessage()); + } + + }