From 035d68e6f61edd8831fc791744e0f4991e0d21f2 Mon Sep 17 00:00:00 2001 From: ichangyu Date: Fri, 26 Feb 2021 02:37:52 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EA=B3=84=EC=82=B0=EA=B8=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 19 ++++++++++ src/main/java/Calculator.java | 58 +++++++++++++++++++++++++++++ src/main/java/Output.java | 7 ++++ src/main/java/StringCalculator.java | 29 +++++++++++++++ src/test/java/CalculatorTest.java | 42 +++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 src/main/java/Calculator.java create mode 100644 src/main/java/Output.java create mode 100644 src/main/java/StringCalculator.java create mode 100644 src/test/java/CalculatorTest.java diff --git a/README.md b/README.md index e79684b..040aadb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,25 @@ # java-calculator 문자열 계산기 미션 저장소 +## 구현 기능 +- 사용자에게 입력을 받는다. + - 숫자와 기호 사이를 공백으로 분리하여 입력 + - [예외] 입력값이 없는 경우 + +- 공백을 기준으로 문자열을 분리 + +- 숫자인지 아닌지 판별 + - [예외] 숫자가 아닌 경우 + - [예외] 연산 기호로 시작할 경 + +- 연산 기호별 계산 진행 + - [에외] 연산 기호가 아닌 다른 기호 입력한 경우 + - [예외] 0으로 나눌 경우 + +- 결과 출력 + + + ## 단위 테스트 실습 - 문자열 계산기 - 다음 요구사항을 junit을 활용해 단위 테스트 코드를 추가해 구현한다. ## 요구사항 diff --git a/src/main/java/Calculator.java b/src/main/java/Calculator.java new file mode 100644 index 0000000..2430619 --- /dev/null +++ b/src/main/java/Calculator.java @@ -0,0 +1,58 @@ +import java.util.Scanner; + +public class Calculator { + static double calculate(double num1, String operator, double num2) { + double result = 0; + + if (operator.equals("+")) { + result = num1 + num2; + } else if (operator.equals("-")) { + result = num1 - num2; + } else if (operator.equals("*")) { + result = num1 * num2; + } else if (operator.equals("/")) { + result = num1 / num2; + } else { + System.out.println("잘못된 기호입니다."); + } + return result; + } + + // main 이름 변경 + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + double num1 = getFirstNum(scanner); + + double result = num1; + while(true) { + String operator = getOperator(scanner); + + if (operator.equals("quit")) { + Output.printResult(result); + break; + } + + double second = getSecondNum(scanner); + + result = calculate(result, operator, second); + } + } + + + // 여기서 부터는 + static double getFirstNum(Scanner scanner) { + double num1 = scanner.nextDouble(); + return num1; + } + + static String getOperator(Scanner scanner) { + String operator = scanner.next(); + return operator; + } + + static double getSecondNum(Scanner scanner) { + double num2 = scanner.nextDouble(); + return num2; + } +} \ No newline at end of file diff --git a/src/main/java/Output.java b/src/main/java/Output.java new file mode 100644 index 0000000..1b9fe54 --- /dev/null +++ b/src/main/java/Output.java @@ -0,0 +1,7 @@ +public class Output { + private static String OUTPUT_MESSAGE ="연산결과: "; + + static void printResult(double result) { + System.out.println(OUTPUT_MESSAGE + result); + } +} \ No newline at end of file diff --git a/src/main/java/StringCalculator.java b/src/main/java/StringCalculator.java new file mode 100644 index 0000000..875eb7a --- /dev/null +++ b/src/main/java/StringCalculator.java @@ -0,0 +1,29 @@ +import java.util.Scanner; + +public class StringCalculator { + public static Scanner scanner = new Scanner(System.in); + private static final String INPUT_MESSAGE ="문자열을 입력해주세요: "; + + public static void main(String[] args) { + System.out.print(INPUT_MESSAGE); + + String value = scanner.nextLine(); + String[] values = value.split(" "); + + double num1 = Double.parseDouble(values[0]); + + double result = num1; + + // 문자열 배열 안에서 + for (int i = 1; i < values.length; i += 2) { + String operator = values[i]; + + double num2 = Double.parseDouble(values[i + 1]); + + result = Calculator.calculate(result, operator, num2); + } + + // 최종 결과 출력 + Output.printResult(result); + } +} \ No newline at end of file diff --git a/src/test/java/CalculatorTest.java b/src/test/java/CalculatorTest.java new file mode 100644 index 0000000..b638f57 --- /dev/null +++ b/src/test/java/CalculatorTest.java @@ -0,0 +1,42 @@ +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + + +public class CalculatorTest { + double num1 = 3; + double num2 = 2; + + Calculator calculator = new Calculator(); + + @Test + void addTest() { + String operator = "+"; + double result; + result = calculator.calculate(num1, operator, num2); + assertThat(result).isEqualTo(5); + } + + @Test + void subtractTest() { + String operator = "-"; + double result; + result = Calculator.calculate(num1, operator, num2); + assertThat(result).isEqualTo(-1); + } + + @Test + void multiplyTest() { + String operator = "*"; + double result; + result = calculator.calculate(num1, operator, num2); + assertThat(result).isEqualTo(6); + } + + @Test + void divideTest() { + String operator = "/"; + double result; + result = calculator.calculate(num1, operator, num2); + assertThat(result).isEqualTo(1.5); + } +} From b435316162987ae7893636ca1c2eea1a5e27a5ed Mon Sep 17 00:00:00 2001 From: ichangyu Date: Sat, 27 Feb 2021 16:48:43 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=BD=94=EB=93=9C=20=EC=9D=BC?= =?UTF-8?q?=EC=B9=98=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++--- build.gradle | 2 +- src/main/java/Calculator.java | 58 --------- src/main/java/CalculatorApplication.java | 64 +++++++++ src/main/java/Output.java | 7 - src/main/java/StringCalculator.java | 29 ----- .../java/domain/calculator/Calculator.java | 21 +++ .../calculator/ExpressionValidator.java | 55 ++++++++ src/main/java/domain/calculator/Parser.java | 37 ++++++ .../exception/InvalidInputException.java | 15 +++ .../java/domain/expression/Expression.java | 32 +++++ .../domain/expression/operator/Addition.java | 8 ++ .../domain/expression/operator/Division.java | 13 ++ .../expression/operator/Multiplication.java | 8 ++ .../domain/expression/operator/Operator.java | 17 +++ .../expression/operator/Subtraction.java | 8 ++ .../exception/DivideByZeroException.java | 15 +++ src/main/java/ui/printer/ConsolePrinter.java | 32 +++++ src/main/java/ui/printer/Printer.java | 12 ++ .../java/ui/receiver/ConsoleReceiver.java | 17 +++ src/main/java/ui/receiver/Receiver.java | 6 + src/test/java/CalculatorTest.java | 123 ++++++++++++++---- 22 files changed, 477 insertions(+), 136 deletions(-) delete mode 100644 src/main/java/Calculator.java create mode 100644 src/main/java/CalculatorApplication.java delete mode 100644 src/main/java/Output.java delete mode 100644 src/main/java/StringCalculator.java create mode 100644 src/main/java/domain/calculator/Calculator.java create mode 100644 src/main/java/domain/calculator/ExpressionValidator.java create mode 100644 src/main/java/domain/calculator/Parser.java create mode 100644 src/main/java/domain/calculator/exception/InvalidInputException.java create mode 100644 src/main/java/domain/expression/Expression.java create mode 100644 src/main/java/domain/expression/operator/Addition.java create mode 100644 src/main/java/domain/expression/operator/Division.java create mode 100644 src/main/java/domain/expression/operator/Multiplication.java create mode 100644 src/main/java/domain/expression/operator/Operator.java create mode 100644 src/main/java/domain/expression/operator/Subtraction.java create mode 100644 src/main/java/domain/expression/operator/exception/DivideByZeroException.java create mode 100644 src/main/java/ui/printer/ConsolePrinter.java create mode 100644 src/main/java/ui/printer/Printer.java create mode 100644 src/main/java/ui/receiver/ConsoleReceiver.java create mode 100644 src/main/java/ui/receiver/Receiver.java diff --git a/README.md b/README.md index 040aadb..1248de2 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,26 @@ # java-calculator 문자열 계산기 미션 저장소 -## 구현 기능 -- 사용자에게 입력을 받는다. - - 숫자와 기호 사이를 공백으로 분리하여 입력 - - [예외] 입력값이 없는 경우 - -- 공백을 기준으로 문자열을 분리 +## 짝 프로그래밍 진행 절차 +1. 네비게이터, 드라이버 결정 + - 1st: 네비게이터 이동민, 드라이버 이찬규 + - 2nd: 네비게이터 이찬규, 드라이버 이동민 -- 숫자인지 아닌지 판별 - - [예외] 숫자가 아닌 경우 - - [예외] 연산 기호로 시작할 경 +2. 기능 분석 + - 입력기: 사용자 입력을 받는다. + - 출력기: 프로그램 메시지를 출력한다. + - 계산기: 식을 계산한다. + - 파서: 문자열 식을 의미 단위로 나눈다. -- 연산 기호별 계산 진행 - - [에외] 연산 기호가 아닌 다른 기호 입력한 경우 - - [예외] 0으로 나눌 경우 - -- 결과 출력 +3. 테스트 케이스 작성 +4. 구현 +5. 다른 테스트 케이스 작성 + +6. 구현 + +7. 3~6 반복 ## 단위 테스트 실습 - 문자열 계산기 - 다음 요구사항을 junit을 활용해 단위 테스트 코드를 추가해 구현한다. @@ -33,8 +35,8 @@ - 문자열을 입력 받은 후(scanner의 nextLine() 메소드 활용) 빈 공백 문자열을 기준으로 문자들을 분리해야 한다. ```java String value = scanner.nextLine(); -String[] values = value.split(" "); + String[] values = value.split(" "); ``` - 문자열을 숫자로 변경하는 방법 -`int number = Integer.parseInt("문자열");` +`int number = Integer.parseInt("문자열");` \ No newline at end of file diff --git a/build.gradle b/build.gradle index db8d2fd..b7e31be 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' apply plugin: 'eclipse' version = '1.0.0' -sourceCompatibility = 1.8 +sourceCompatibility = 11 repositories { mavenCentral() diff --git a/src/main/java/Calculator.java b/src/main/java/Calculator.java deleted file mode 100644 index 2430619..0000000 --- a/src/main/java/Calculator.java +++ /dev/null @@ -1,58 +0,0 @@ -import java.util.Scanner; - -public class Calculator { - static double calculate(double num1, String operator, double num2) { - double result = 0; - - if (operator.equals("+")) { - result = num1 + num2; - } else if (operator.equals("-")) { - result = num1 - num2; - } else if (operator.equals("*")) { - result = num1 * num2; - } else if (operator.equals("/")) { - result = num1 / num2; - } else { - System.out.println("잘못된 기호입니다."); - } - return result; - } - - // main 이름 변경 - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - - double num1 = getFirstNum(scanner); - - double result = num1; - while(true) { - String operator = getOperator(scanner); - - if (operator.equals("quit")) { - Output.printResult(result); - break; - } - - double second = getSecondNum(scanner); - - result = calculate(result, operator, second); - } - } - - - // 여기서 부터는 - static double getFirstNum(Scanner scanner) { - double num1 = scanner.nextDouble(); - return num1; - } - - static String getOperator(Scanner scanner) { - String operator = scanner.next(); - return operator; - } - - static double getSecondNum(Scanner scanner) { - double num2 = scanner.nextDouble(); - return num2; - } -} \ No newline at end of file diff --git a/src/main/java/CalculatorApplication.java b/src/main/java/CalculatorApplication.java new file mode 100644 index 0000000..b52c67f --- /dev/null +++ b/src/main/java/CalculatorApplication.java @@ -0,0 +1,64 @@ +import domain.calculator.Calculator; +import domain.calculator.exception.InvalidInputException; +import domain.expression.operator.exception.DivideByZeroException; +import ui.printer.ConsolePrinter; +import ui.printer.Printer; +import ui.receiver.ConsoleReceiver; +import ui.receiver.Receiver; + +import java.util.Optional; + +public class CalculatorApplication { + private static final boolean CONTINUE_PROGRAM = true; + private static final String EXIT_REQUEST = "exit"; + + private Printer printer; + private Receiver receiver; + private Calculator calculator; + + public CalculatorApplication() { + printer = new ConsolePrinter(); + receiver = new ConsoleReceiver(); + calculator = new Calculator(); + } + + public void run() { + printer.greet(); + + while (CONTINUE_PROGRAM) { + printer.printWaitingForInputText(); + String expression = receiver.receiveExpression(); + if (expression.equalsIgnoreCase(EXIT_REQUEST)) { + break ; + } + + Optional optionalResult = calculateExpression(expression); + if (optionalResult.isEmpty()) { + continue ; + } + + int result = optionalResult.get(); + printer.printResult(result); + } + } + + private Optional calculateExpression(String expression) { + Integer result; + try { + result = calculator.calculate(expression); + } catch (DivideByZeroException e) { + System.out.println(e.getMessage()); + return Optional.empty(); + } catch (InvalidInputException e) { + System.out.println(e.getMessage()); + return Optional.empty(); + } + + return Optional.of(result); + } + + public static void main(String[] args) { + CalculatorApplication app = new CalculatorApplication(); + app.run(); + } +} \ No newline at end of file diff --git a/src/main/java/Output.java b/src/main/java/Output.java deleted file mode 100644 index 1b9fe54..0000000 --- a/src/main/java/Output.java +++ /dev/null @@ -1,7 +0,0 @@ -public class Output { - private static String OUTPUT_MESSAGE ="연산결과: "; - - static void printResult(double result) { - System.out.println(OUTPUT_MESSAGE + result); - } -} \ No newline at end of file diff --git a/src/main/java/StringCalculator.java b/src/main/java/StringCalculator.java deleted file mode 100644 index 875eb7a..0000000 --- a/src/main/java/StringCalculator.java +++ /dev/null @@ -1,29 +0,0 @@ -import java.util.Scanner; - -public class StringCalculator { - public static Scanner scanner = new Scanner(System.in); - private static final String INPUT_MESSAGE ="문자열을 입력해주세요: "; - - public static void main(String[] args) { - System.out.print(INPUT_MESSAGE); - - String value = scanner.nextLine(); - String[] values = value.split(" "); - - double num1 = Double.parseDouble(values[0]); - - double result = num1; - - // 문자열 배열 안에서 - for (int i = 1; i < values.length; i += 2) { - String operator = values[i]; - - double num2 = Double.parseDouble(values[i + 1]); - - result = Calculator.calculate(result, operator, num2); - } - - // 최종 결과 출력 - Output.printResult(result); - } -} \ No newline at end of file diff --git a/src/main/java/domain/calculator/Calculator.java b/src/main/java/domain/calculator/Calculator.java new file mode 100644 index 0000000..22d1ec6 --- /dev/null +++ b/src/main/java/domain/calculator/Calculator.java @@ -0,0 +1,21 @@ +package domain.calculator; + +import domain.expression.Expression; + +public class Calculator { + + public int calculate(String strExpression) { + Parser parser = new Parser(strExpression); + + int left = Integer.parseInt(parser.nextToken()); + Expression expression = Expression.from(left); + + while (parser.hasNext()) { + String operator = parser.nextToken(); + int right = Integer.parseInt(parser.nextToken()); + expression = Expression.of(expression, right, operator); + } + + return expression.evaluate(); + } +} \ No newline at end of file diff --git a/src/main/java/domain/calculator/ExpressionValidator.java b/src/main/java/domain/calculator/ExpressionValidator.java new file mode 100644 index 0000000..92f8703 --- /dev/null +++ b/src/main/java/domain/calculator/ExpressionValidator.java @@ -0,0 +1,55 @@ +package domain.calculator; + +import domain.calculator.exception.InvalidInputException; + +import java.util.List; +import java.util.regex.Pattern; + +public class ExpressionValidator { + + public void validateTokenList(List tokenList) { + long invalidTokenCount = tokenList.stream() + .filter(token -> !isNumber(token) && !isOperator(token)) + .count(); + + if (invalidTokenCount > 0) { + throw new InvalidInputException("올바르지 않은 입력입니다."); + } + } + + public void validateTokenSequence(List tokenList) { + throwIfConditionIsTrue(hasNotAnyToken(tokenList)); + + String firstToken = tokenList.get(0); + throwIfConditionIsTrue(!isNumber(firstToken)); + + for (int i = 1; i < tokenList.size(); i += 2) { + String operatorToken = tokenList.get(i); + throwIfConditionIsTrue(!isOperator(operatorToken)); + + if (isNotLastOperation(i, tokenList.size())) { + String rightOperandToken = tokenList.get(i + 1); + throwIfConditionIsTrue(!isNumber(rightOperandToken)); + } + } + } + + private void throwIfConditionIsTrue(boolean isConditionTrue) { + if (isConditionTrue) { + throw new InvalidInputException("올바르지 않은 입력입니다."); + } + } + + private boolean hasNotAnyToken(List tokenList) { + return (tokenList.size() == 0); + } + private boolean isNumber(String token) { + return Pattern.matches("^[0-9]+$", token); + } + private boolean isOperator(String token) { + return Pattern.matches("\\+|-|\\*|/", token); + } + private boolean isNotLastOperation(int index, int tokenListSize) { + return (index + 1 < tokenListSize); + } +} \ No newline at end of file diff --git a/src/main/java/domain/calculator/Parser.java b/src/main/java/domain/calculator/Parser.java new file mode 100644 index 0000000..63c2a37 --- /dev/null +++ b/src/main/java/domain/calculator/Parser.java @@ -0,0 +1,37 @@ +package domain.calculator; + +import java.util.*; +import java.util.stream.Collectors; + +public class Parser { + + private final Queue tokenQueue; + + public Parser(String expression) { + tokenQueue = new LinkedList<>(); + ExpressionValidator validator = new ExpressionValidator(); + + List tokenList = splitExpressionToList(expression); + validator.validateTokenList(tokenList); + validator.validateTokenSequence(tokenList); + tokenQueue.addAll(tokenList); + } + + private List splitExpressionToList(String expression) { + String[] tokens = expression.split(" +"); + return filterMeaningfulToken(tokens); + } + + private List filterMeaningfulToken(String[] tokens) { + return Arrays.stream(tokens) + .filter(token -> !token.equals("")) + .collect(Collectors.toList()); + } + + public String nextToken() { + return tokenQueue.poll(); + } + public boolean hasNext() { + return !tokenQueue.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/domain/calculator/exception/InvalidInputException.java b/src/main/java/domain/calculator/exception/InvalidInputException.java new file mode 100644 index 0000000..6385bf0 --- /dev/null +++ b/src/main/java/domain/calculator/exception/InvalidInputException.java @@ -0,0 +1,15 @@ +package domain.calculator.exception; + +public class InvalidInputException extends RuntimeException { + + private String message; + + public InvalidInputException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/Expression.java b/src/main/java/domain/expression/Expression.java new file mode 100644 index 0000000..4121916 --- /dev/null +++ b/src/main/java/domain/expression/Expression.java @@ -0,0 +1,32 @@ + +package domain.expression; + +import domain.expression.operator.Operator; + +public class Expression { + + private int left; + private int right; + private Operator operator; + + private Expression(int left, int right, Operator operator) { + this.left = left; + this.right = right; + this.operator = operator; + } + + public static Expression of(int left, int right, String operator) { + return new Expression(left, right, Operator.from(operator)); + } + public static Expression of(Expression left, int right, String operator) { + int leftResult = left.evaluate(); + return new Expression(leftResult, right, Operator.from(operator)); + } + public static Expression from(int left) { + return of(left, 0, "+"); + } + + public int evaluate() { + return operator.operate(left, right); + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/Addition.java b/src/main/java/domain/expression/operator/Addition.java new file mode 100644 index 0000000..2f8bc7b --- /dev/null +++ b/src/main/java/domain/expression/operator/Addition.java @@ -0,0 +1,8 @@ +package domain.expression.operator; + +public class Addition extends Operator { + + public int operate(int left, int right) { + return left + right; + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/Division.java b/src/main/java/domain/expression/operator/Division.java new file mode 100644 index 0000000..becd121 --- /dev/null +++ b/src/main/java/domain/expression/operator/Division.java @@ -0,0 +1,13 @@ +package domain.expression.operator; + +import domain.expression.operator.exception.DivideByZeroException; + +public class Division extends Operator { + + public int operate(int left, int right) { + if (right == 0) { + throw new DivideByZeroException("0으로 나눌 수 없습니다."); + } + return left / right; + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/Multiplication.java b/src/main/java/domain/expression/operator/Multiplication.java new file mode 100644 index 0000000..997f3fe --- /dev/null +++ b/src/main/java/domain/expression/operator/Multiplication.java @@ -0,0 +1,8 @@ +package domain.expression.operator; + +public class Multiplication extends Operator { + + public int operate(int left, int right) { + return left * right; + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/Operator.java b/src/main/java/domain/expression/operator/Operator.java new file mode 100644 index 0000000..edcaa63 --- /dev/null +++ b/src/main/java/domain/expression/operator/Operator.java @@ -0,0 +1,17 @@ +package domain.expression.operator; + +public abstract class Operator { + + public static Operator from(String operator) { + if (operator.equals("+")) { + return new Addition(); + } else if (operator.equals("-")) { + return new Subtraction(); + } else if (operator.equals("*")) { + return new Multiplication(); + } + return new Division(); + } + + public abstract int operate(int left, int right); +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/Subtraction.java b/src/main/java/domain/expression/operator/Subtraction.java new file mode 100644 index 0000000..2730357 --- /dev/null +++ b/src/main/java/domain/expression/operator/Subtraction.java @@ -0,0 +1,8 @@ +package domain.expression.operator; + +public class Subtraction extends Operator { + + public int operate(int left, int right) { + return left - right; + } +} \ No newline at end of file diff --git a/src/main/java/domain/expression/operator/exception/DivideByZeroException.java b/src/main/java/domain/expression/operator/exception/DivideByZeroException.java new file mode 100644 index 0000000..a2fd3ba --- /dev/null +++ b/src/main/java/domain/expression/operator/exception/DivideByZeroException.java @@ -0,0 +1,15 @@ +package domain.expression.operator.exception; + +public class DivideByZeroException extends RuntimeException { + + private String message; + + public DivideByZeroException(String message) { + this.message = message; + } + + @Override + public String getMessage() { + return message; + } +} \ No newline at end of file diff --git a/src/main/java/ui/printer/ConsolePrinter.java b/src/main/java/ui/printer/ConsolePrinter.java new file mode 100644 index 0000000..bf5e783 --- /dev/null +++ b/src/main/java/ui/printer/ConsolePrinter.java @@ -0,0 +1,32 @@ +package ui.printer; + +public class ConsolePrinter implements Printer { + private final String GREET_MESSAGE = "계산기 프로그램입니다.\n" + + "숫자와 사칙연산 기호를 공백으로 구분하여 입력해주세요.\n" + + "프로그램을 종료하시려면 exit을 입력해주세요."; + + private final String INPUT_REQUEST_MESSAGE = "식 입력: "; + + private final String OUTPUT_MESSAGE = "answer: %d\n"; + private final String EXIT_MESSAGE = "프로그램을 종료합니다."; + + @Override + public void greet() { + System.out.println(GREET_MESSAGE); + } + + @Override + public void printWaitingForInputText() { + System.out.print(INPUT_REQUEST_MESSAGE); + } + + @Override + public void printResult(int result) { + System.out.printf(OUTPUT_MESSAGE, result); + } + + @Override + public void printExitMessage() { + System.out.println(EXIT_MESSAGE); + } +} \ No newline at end of file diff --git a/src/main/java/ui/printer/Printer.java b/src/main/java/ui/printer/Printer.java new file mode 100644 index 0000000..18494e2 --- /dev/null +++ b/src/main/java/ui/printer/Printer.java @@ -0,0 +1,12 @@ +package ui.printer; + +public interface Printer { + + void greet(); + + void printWaitingForInputText(); + + void printResult(int result); + + void printExitMessage(); +} \ No newline at end of file diff --git a/src/main/java/ui/receiver/ConsoleReceiver.java b/src/main/java/ui/receiver/ConsoleReceiver.java new file mode 100644 index 0000000..e87d170 --- /dev/null +++ b/src/main/java/ui/receiver/ConsoleReceiver.java @@ -0,0 +1,17 @@ +package ui.receiver; + +import java.util.Scanner; + +public class ConsoleReceiver implements Receiver { + + private final Scanner scanner; + + public ConsoleReceiver() { + scanner = new Scanner(System.in); + } + + @Override + public String receiveExpression() { + return scanner.nextLine(); + } +} \ No newline at end of file diff --git a/src/main/java/ui/receiver/Receiver.java b/src/main/java/ui/receiver/Receiver.java new file mode 100644 index 0000000..f7106a4 --- /dev/null +++ b/src/main/java/ui/receiver/Receiver.java @@ -0,0 +1,6 @@ +package ui.receiver; + +public interface Receiver { + + String receiveExpression(); +} \ No newline at end of file diff --git a/src/test/java/CalculatorTest.java b/src/test/java/CalculatorTest.java index b638f57..df8780e 100644 --- a/src/test/java/CalculatorTest.java +++ b/src/test/java/CalculatorTest.java @@ -1,42 +1,115 @@ +import domain.calculator.Calculator; +import domain.calculator.exception.InvalidInputException; +import domain.expression.operator.exception.DivideByZeroException; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class CalculatorTest { - double num1 = 3; - double num2 = 2; - Calculator calculator = new Calculator(); + private Calculator calculator = new Calculator(); @Test - void addTest() { - String operator = "+"; - double result; - result = calculator.calculate(num1, operator, num2); - assertThat(result).isEqualTo(5); + void 더하기_테스트() { + int test1Result = calculator.calculate("1 + 1"); + assertThat(test1Result).isEqualTo(2); + + int test2Result = calculator.calculate("3 + 7"); + assertThat(test2Result).isEqualTo(10); + + int test3Result = calculator.calculate("10 + 234"); + assertThat(test3Result).isEqualTo(244); } @Test - void subtractTest() { - String operator = "-"; - double result; - result = Calculator.calculate(num1, operator, num2); - assertThat(result).isEqualTo(-1); + void 빼기_테스트() { + int test1Result = calculator.calculate("1 - 1"); + assertThat(test1Result).isEqualTo(0); + + int test2Result = calculator.calculate("998 - 234"); + assertThat(test2Result).isEqualTo(764); + + int test3Result = calculator.calculate("10003 - 234"); + assertThat(test3Result).isEqualTo(9769); } @Test - void multiplyTest() { - String operator = "*"; - double result; - result = calculator.calculate(num1, operator, num2); - assertThat(result).isEqualTo(6); + void 곱하기_테스트() { + int test1Result = calculator.calculate("2 * 34"); + assertThat(test1Result).isEqualTo(68); + + int test2Result = calculator.calculate("60 * 61"); + assertThat(test2Result).isEqualTo(3660); + + int test3Result = calculator.calculate("430 * 289"); + assertThat(test3Result).isEqualTo(124270); } @Test - void divideTest() { - String operator = "/"; - double result; - result = calculator.calculate(num1, operator, num2); - assertThat(result).isEqualTo(1.5); + void 나누기_테스트() { + int test1Result = calculator.calculate("42 / 2"); + assertThat(test1Result).isEqualTo(21); + + int test2Result = calculator.calculate("60 / 5"); + assertThat(test2Result).isEqualTo(12); + + int test3Result = calculator.calculate("22 / 6"); + assertThat(test3Result).isEqualTo(3); + } + + @Test + void 나누기는_0으로_나눌때_DivideByZeroException_발생() { + assertThatExceptionOfType(DivideByZeroException.class) + .isThrownBy(() -> calculator.calculate("2 / 0")) + .as("0으로 나눌 수 없습니다."); + } + + @Test + void 두개의_연산자가_존재하는_식을_계산할_수_있다() { + int test1Result = calculator.calculate("44 + 23 - 3"); + assertThat(test1Result).isEqualTo(64); + + int test2Result = calculator.calculate("4 / 2 - 10"); + assertThat(test2Result).isEqualTo(-8); + + int test3Result = calculator.calculate("54 * 20 / 3"); + assertThat(test3Result).isEqualTo(360); + } + + @Test + void 두개_이상의_연산자가_존재하는_식을_계산할_수_있다() { + int test1Result = calculator.calculate("44 + 23 - 3 * 5"); + assertThat(test1Result).isEqualTo(320); + + int test2Result = calculator.calculate("4 / 2 - 10 * 10 / 4"); + assertThat(test2Result).isEqualTo(-20); + + int test3Result = calculator.calculate("54 * 20 / 3 / 120 + 2 - 5"); + assertThat(test3Result).isEqualTo(0); + } + + @Test + void 정상적이지_않은_공백_입력에_대해서도_올바른_답을_낼_수_있다() { + int test1Result = calculator.calculate(" 21 + 2 "); + assertThat(test1Result).isEqualTo(23); + + int test2Result = calculator.calculate("23 - 2 / 3"); + assertThat(test2Result).isEqualTo(7); + } + + @Test + void 정상적이지_않은_입력에_대해_InvalidInputException을_던진다() { + assertThatExceptionOfType(InvalidInputException.class) + .isThrownBy(() -> calculator.calculate("2 + // 3")); + + assertThatExceptionOfType(InvalidInputException.class) + .isThrownBy(() -> calculator.calculate("abc efij 2 + 3")); + + assertThatExceptionOfType(InvalidInputException.class) + .isThrownBy(() -> calculator.calculate("3 + 3 - 3 ###")); + + assertThatExceptionOfType(InvalidInputException.class) + .isThrownBy(() -> calculator.calculate("3 + 3 3 2 - 2")); } -} +} \ No newline at end of file