-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add : 요구사항 1 - split 했을 때 contains()를 활용해 변환 값이 맞는지 검증하는 테스트 코드 작성 * add : 요구사항 2 - substring()을 활용해 올바른 문자열이 반환되는지 테스트 * add : 요구사항 3 - charAt() 메소드를 활용해 범위를 넘어가는 예외 테스트 * add : 요구사항 1 - size() 메소드를 활용해 Set의 크기를 확인하는 테스트 * add : 요구사항 2 - JUnit의 ParameterizedTest를 이용해 중복 코드를 제거 * add : 요구사항 3 - @CsvSource를 활용해 입력 값에 따라 결과 값이 다른 경우의 테스트 * add : 문자열 계산기 기능 구현 및 테스트 코드 작성 * add : README 수정 * Update README.md * refact : operator를 enum 클래스로 만들어서 관리 / Validator -> ValidityInspector 이름 변경 * refact : if 문의 나열 -> if ~ else if 문으로 변경 / 조건문의 단계별로 return * refact : 입력 문자열의 공백 또는 null 검사 메소드를 하나로 통일 / 매직넘버 제거 / checkIsDoubleNumber -> checkCorrectDoubleNumber, checkIsOperator -> checkCorrectOperator 로 메소드 이름 변경 * modify : gitignore 수정 * refact : call stack 이 쌓이는 것을 방지하기 위해 잘못된 문자열이 입력될 시 계산기의 기능이 종료되도록 변경 / Validator 에서 is 로 시작하는 메소드 명 변경 / 공백으로만 이루어진 문자열 입력 시 예외 출력 / Input 클래스의 기능을 명확히 설명할 수 있도록 클래스 이름과 메소드 이름을 변경 * refact : 여러 클래스에서 공통적으로 사용하는 0, 공백, 빈 문자열을 상수 클래스로 분리 * refact : 변경한 메소드에 맞게 테스트 코드 수정 / MethodSource -> ValueSource 로 변경 * refact : Operator 를 컨벤션에 맞게 이름 수정 / Operator.find() 와 Operator.calculate() 메소드를 만들어 입력한 연산자와 좌항, 우항을 계산하게 수정
- Loading branch information
Showing
13 changed files
with
352 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,36 @@ | ||
# java-calculator | ||
문자열 계산기 미션 저장소 | ||
|
||
## 우아한테크코스 코드리뷰 | ||
* [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) | ||
## 기능적 요구사항 | ||
- 문자열을 입력 받아 공백 단위로 split 하는 함수를 만든다 | ||
- 입력이 정상적인지 확인 | ||
- 입력이 없는지 | ||
- 숫자와 연산자 외의 다른 문자가 있는지 | ||
- split 된 결과가 정상적인지 확인 | ||
- 숫자와 연산자의 순서가 맞는지 | ||
|
||
- 사칙연산을 하는 함수를 만든다 | ||
- 나눗셈의 경우 0으로 나누는 경우에 대한 예외 처리 | ||
- 입력 값이 자료형의 범위를 넘어 가는 경우에 대한 예외 처리 | ||
|
||
- split 된 결과 값이 순서대로 연산이 되는 함수를 만든다 | ||
|
||
- 연산 결과를 출력하는 함수를 만든다 | ||
|
||
- 단위별로 테스트 하는 함수를 만든다 | ||
- split 테스트를 진행한다 | ||
- 입력으로 null, 공백, 유효하지 않은 double 범위의 수, 숫자와 연산자 외의 문자열 | ||
- split 할 수 없는 문자열, 숫자와 연산자 순서가 바뀐 문자열, 정상 계산식 | ||
- 사칙연산 테스트 | ||
- 사칙연산의 결과 값이 실제 값과 맞는지 테스트 | ||
- 0으로 나누었을 때, double 범위를 넘어가는 결과 값 | ||
|
||
|
||
## 비기능적 요구사항 | ||
- indent 2까지 허용한다. | ||
- 메소드는 15줄 까지 허용한다. | ||
- switch문 사용하지 않는다. | ||
- 하드코딩하지 않는다. | ||
- 변수와 메소드 명명은 컨벤션에 따른다. | ||
- 자바 코드 컨벤션을 지키면서 프로그래밍 한다. | ||
- 함수의 인자 수를 3개까지만 허용한다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package calculator; | ||
|
||
public class Calculator { | ||
public double calculate(String[] splitedInput) { | ||
double left = Double.valueOf(splitedInput[0]); | ||
for (int i = 1; i < splitedInput.length; i = i + 2) { | ||
String operator = splitedInput[i]; | ||
double right = Double.valueOf(splitedInput[i + 1]); | ||
left = Operator.find(operator).calculate(left, right); | ||
} | ||
return left; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package calculator; | ||
|
||
public class Constant { | ||
public final static int ZERO = 0; | ||
|
||
public final static String BLANK = " "; | ||
public final static String EMPTY_STRING = ""; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package calculator; | ||
|
||
public class Main { | ||
public static void main(String[] args) { | ||
UserInputScanner userInputScanner = new UserInputScanner(); | ||
Calculator calculator = new Calculator(); | ||
Output output = new Output(); | ||
|
||
try { | ||
String[] splitString = userInputScanner.splitUserInputString(); | ||
double result = calculator.calculate(splitString); | ||
output.printResult(result); | ||
} catch (Exception e) { | ||
System.out.println(e.getMessage()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package calculator; | ||
|
||
import java.util.Arrays; | ||
import java.util.function.BiFunction; | ||
|
||
public enum Operator { | ||
PLUS("+", | ||
(left, right) -> (left + right)), | ||
MINUS("-", | ||
(left, right) -> (left - right)), | ||
MULTIPLICATION("*", | ||
(left, right) -> (left * right)), | ||
DIVISION("/", | ||
(left, right) -> (left / right)); | ||
|
||
private String symbol; | ||
private BiFunction<Double, Double, Double> expression; | ||
|
||
Operator(String symbol, BiFunction<Double, Double, Double> expression) { | ||
this.symbol = symbol; | ||
this.expression = expression; | ||
} | ||
|
||
private String getSymbol() { | ||
return this.symbol; | ||
} | ||
|
||
public static Operator find(String operator) { | ||
return Arrays.stream(Operator.values()) | ||
.filter(op -> op.getSymbol().equals(operator)) | ||
.findFirst() | ||
.get(); | ||
} | ||
|
||
public double calculate(double left, double right) { | ||
return expression.apply(left, right); | ||
} | ||
|
||
public static boolean isRightOperator(String operator) { | ||
return Arrays.stream(Operator.values()) | ||
.anyMatch(op -> op.getSymbol().equals(operator)); | ||
} | ||
|
||
public static boolean isDivisionOperator(String operator) { | ||
return "/".equals(operator); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package calculator; | ||
|
||
public class Output { | ||
public void printResult(double result) { | ||
System.out.println("결과 값은 : " + result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package calculator; | ||
|
||
import java.util.Scanner; | ||
|
||
public class UserInputScanner { | ||
private ValidityInspector validityInspector = new ValidityInspector(); | ||
private Scanner scanner = new Scanner(System.in); | ||
|
||
private String inputStringToUser() { | ||
System.out.print("계산식을 입력하시오: "); | ||
String inputLine = scanner.nextLine(); | ||
validityInspector.checkUserInputIsBlankOrEmpty(inputLine); | ||
return inputLine; | ||
} | ||
|
||
public String[] splitUserInputString() { | ||
String input = inputStringToUser(); | ||
String[] splitInput = input.split(Constant.BLANK); | ||
validityInspector.checkCanConvertUserInputToNumberAndOperator(splitInput); | ||
return splitInput; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package calculator; | ||
|
||
public class ValidityInspector { | ||
public void checkUserInputIsBlankOrEmpty(String input) { | ||
if (isBlank(input) || isEmpty(input)) { | ||
throw new IllegalArgumentException("공백 또는 빈 문자열을 입력하셨습니다."); | ||
} | ||
} | ||
|
||
private boolean isEmpty(String input) { | ||
return input.equals(Constant.EMPTY_STRING); | ||
} | ||
|
||
private boolean isBlank(String input) { | ||
return input.equals(Constant.BLANK); | ||
} | ||
|
||
public void checkCanConvertUserInputToNumberAndOperator(String[] splitedInput) { | ||
checkSplitedInputEmpty(splitedInput); | ||
String firstClause = splitedInput[0]; | ||
checkCorrectDoubleNumber(firstClause); | ||
try { | ||
for (int i = 1; i < splitedInput.length; i = i + 2) { | ||
String operator = splitedInput[i]; | ||
String secondClause = splitedInput[i + 1]; | ||
checkDivideByZero(operator, secondClause); | ||
checkCorrectOperator(operator); | ||
checkCorrectDoubleNumber(secondClause); | ||
} | ||
} catch (ArrayIndexOutOfBoundsException e) { | ||
throw new ArrayIndexOutOfBoundsException("잘못된 계산식을 입력하였습니다."); | ||
} | ||
} | ||
|
||
private void checkCorrectDoubleNumber(String s) { | ||
try { | ||
Double.valueOf(s); | ||
} catch (Exception e) { | ||
throw new IllegalArgumentException("잘못된 수를 입력하였습니다."); | ||
} | ||
} | ||
|
||
private void checkCorrectOperator(String s) { | ||
if (!Operator.isRightOperator(s)) { | ||
throw new IllegalArgumentException("잘못된 연산자를 입력하였습니다."); | ||
} | ||
} | ||
|
||
private void checkSplitedInputEmpty(String[] splitedInput) { | ||
if (splitedInput.length == 0) { | ||
throw new IllegalArgumentException("공백을 입력하였습니다."); | ||
} | ||
} | ||
|
||
private void checkDivideByZero(String operator, String secondClause) { | ||
if (Operator.isDivisionOperator(operator) && Integer.toString(Constant.ZERO).equals(secondClause)) { | ||
throw new IllegalArgumentException("0으로 나누는 식을 입력하셨습니다."); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package calculator; | ||
|
||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
public class CalculatorTest { | ||
private Calculator calculator; | ||
private ValidityInspector validityInspector; | ||
|
||
@BeforeEach | ||
public void setUp() { | ||
calculator = new Calculator(); | ||
validityInspector = new ValidityInspector(); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {" ", ""}) | ||
public void checkUserInputIsBlankOrEmptyTest(String input) { | ||
Assertions.assertThatThrownBy(() -> { | ||
validityInspector.checkUserInputIsBlankOrEmpty(input); | ||
}).isInstanceOf(IllegalArgumentException.class) | ||
.hasMessageContaining("공백 또는 빈 문자열을 입력하셨습니다."); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {" ", "q + w + e", "1+2+3", "+ + 2", "1 abcd 2", "2 * 65 / 0", "2 + 3/", "/1 + 55", "1 + a3"}) | ||
public void checkCanConvertUserInputToNumberAndOperatorTest(String input) { | ||
String[] splitData = input.split(Constant.BLANK); | ||
Assertions.assertThatThrownBy(() -> { | ||
validityInspector.checkCanConvertUserInputToNumberAndOperator(splitData); | ||
}).isInstanceOf(IllegalArgumentException.class); | ||
} | ||
|
||
@Test | ||
public void addTest() { | ||
String[] numericalExpression = {"1", "+", "2"}; | ||
Double result = calculator.calculate(numericalExpression); | ||
Assertions.assertThat(result).isEqualTo(3); | ||
} | ||
|
||
@Test | ||
public void subtractTest() { | ||
String[] numericalExpression = {"1", "-", "2"}; | ||
Double result = calculator.calculate(numericalExpression); | ||
Assertions.assertThat(result).isEqualTo(-1); | ||
} | ||
|
||
@Test | ||
public void multipleTest() { | ||
String[] numericalExpression = {"1", "*", "2"}; | ||
Double result = calculator.calculate(numericalExpression); | ||
Assertions.assertThat(result).isEqualTo(2); | ||
} | ||
|
||
@Test | ||
public void divideTest() { | ||
String[] numericalExpression = {"1", "/", "2"}; | ||
Double result = calculator.calculate(numericalExpression); | ||
Assertions.assertThat(result).isEqualTo(0.5d); | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package study; | ||
|
||
import org.assertj.core.api.Assertions; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
public class SetTest { | ||
private Set numbers; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
numbers = new HashSet<>(); | ||
numbers.add(1); | ||
numbers.add(1); | ||
numbers.add(2); | ||
numbers.add(3); | ||
} | ||
|
||
@Test | ||
void sizeTest() { | ||
int size = numbers.size(); | ||
Assertions.assertThat(size).isEqualTo(4); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(ints = {1, 1, 2, 3}) | ||
void containTest(int number) { | ||
assertTrue(numbers.contains(number)); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource(value = {"ravie-RAVIE", "Lavine-LAVINE", "orange-ORANKE", "dog-DoG"}, delimiter = '-') | ||
void equalUpperCase(String input, String upperCase){ | ||
Assertions.assertThat(upperCase).isEqualTo(input.toUpperCase()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package study; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.assertj.core.api.Assertions; | ||
|
||
public class StringTest { | ||
@Test | ||
void split() { | ||
String value = "1,2"; | ||
String[] result = value.split(","); | ||
Assertions.assertThat(result).contains("1"); | ||
Assertions.assertThat(result).contains("2"); | ||
String[] temp = {"1", "2"}; | ||
Assertions.assertThat(result).containsExactly(temp); | ||
} | ||
|
||
@Test | ||
void substring() { | ||
String value = "(1,2)"; | ||
String result = value.substring(1, value.length() - 1); | ||
Assertions.assertThat(result).contains("1,2"); | ||
} | ||
|
||
@Test | ||
@DisplayName("charAt method out of bounds test") | ||
void charAtTest() { | ||
String value = "abc"; | ||
Assertions.assertThatThrownBy(() -> { | ||
value.charAt(10); | ||
}).isInstanceOf(StringIndexOutOfBoundsException.class).hasMessageContaining("String index out of range"); | ||
} | ||
} |