diff --git a/src/main/java/Formula.java b/src/main/java/Formula.java new file mode 100644 index 000000000..eeaa5476d --- /dev/null +++ b/src/main/java/Formula.java @@ -0,0 +1,14 @@ +public class Formula { + private static final String FORMULA_DELIMITER = " "; + private final String[] formula; + + public Formula(String formula) { + this.formula = formula.split(FORMULA_DELIMITER); + } + + public String[] getFormula() { + return formula; + } +} + + diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 000000000..db45f966d --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,15 @@ +import java.util.Scanner; + +public class Main { + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + + System.out.println("정수를 입력해주세요: "); + StringCalc stringCalc = new StringCalc(new Formula(scanner.nextLine())); + + int calcNumber = stringCalc.calc(); + + System.out.println(String.format("연산된 값은 %d입니다.", calcNumber)); + } +} diff --git a/src/main/java/Operator.java b/src/main/java/Operator.java new file mode 100644 index 000000000..ea21a1f03 --- /dev/null +++ b/src/main/java/Operator.java @@ -0,0 +1,46 @@ +import java.util.Collections; +import java.util.Map; +import java.util.function.BiFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public enum Operator { + PLUS("+", (first, second) -> first + second), + MINUS("-", (first, second) -> first - second), + MULTIPLY("*", (first, second) -> first * second), + DIVIDE("/", (first, second) -> { + if (second == 0) { + throw new IllegalArgumentException(); + } + return first / second; + }); + + private static final Map OPERATOR_MAP = + Collections.unmodifiableMap(Stream.of(values()) + .collect(Collectors.toMap(operator -> operator.getSymbol(), operator -> operator))); + private final String symbol; + private final BiFunction operation; + + Operator(String symbol, BiFunction operation) { + this.symbol = symbol; + this.operation = operation; + } + + public static Operator findOperator(String symbol) { + Operator operator = OPERATOR_MAP.get(symbol); + + if (operator == null) { + throw new IllegalArgumentException(); + } + + return operator; + } + + public String getSymbol() { + return symbol; + } + + public int operate(int first, int second) { + return operation.apply(first, second); + } +} diff --git a/src/main/java/StringCalc.java b/src/main/java/StringCalc.java new file mode 100644 index 000000000..0abd8f925 --- /dev/null +++ b/src/main/java/StringCalc.java @@ -0,0 +1,27 @@ +import java.util.regex.Pattern; + +public class StringCalc { + private static final Pattern NUMBER_REGEXP = Pattern.compile("^[0-9]*$"); + private Formula formula; + + public StringCalc(Formula formula) { + this.formula = formula; + } + + public int calc() { + + int sum = 0; + Operator currentOperator = Operator.PLUS; + + for (String input : formula.getFormula()) { + if (NUMBER_REGEXP.matcher(input).find()) { + sum = currentOperator.operate(sum, Integer.valueOf(input)); + continue; + } + + currentOperator = Operator.findOperator(input); + } + + return sum; + } +} diff --git a/src/test/java/CalculatorTest.java b/src/test/java/CalculatorTest.java new file mode 100644 index 000000000..a715dbd38 --- /dev/null +++ b/src/test/java/CalculatorTest.java @@ -0,0 +1,42 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.*; + +public class CalculatorTest { + + @DisplayName("정상 입력시 의도대로 계산된 값이 나오는지 테스트") + @Test + void calculateTest(){ + StringCalc calculator = new StringCalc(new Formula("5 + 5 * 5 / 25")); + int result = calculator.calc(); + assertThat(2).isEqualTo(result); + } + + @DisplayName("0 으로 나눌 시 IllegalArgumentException 발생 하는지 테스트") + @Test + void divideZeroTest(){ + assertThatIllegalArgumentException().isThrownBy(() -> { + StringCalc calculator = new StringCalc(new Formula("2 + 2 * 10 / 0")); + int result = calculator.calc(); + assertThat(2).isEqualTo(result); + }); + } + + @DisplayName("입력 값이 null 이거나 빈 공백 문자일 경우 IllegalArgumentException 발생 하는지 테스트") + @Test + void inputNullOrEmptyTest(){ + assertThatIllegalArgumentException().isThrownBy(() -> { + StringCalc calculator = new StringCalc(new Formula("2 + * 2 / 2")); + int result = calculator.calc(); + }); + } + + @DisplayName("사칙연산 기호가 아닌 경우 IllegalArgumentException throw") + @Test + void checkPermittedOperator(){ + assertThatIllegalArgumentException().isThrownBy(() -> { + StringCalc calculator = new StringCalc(new Formula("2 $ 6 * 5 / 4")); + int result = calculator.calc(); + }); + } +} diff --git a/src/test/java/OperatorTest.java b/src/test/java/OperatorTest.java new file mode 100644 index 000000000..849b99731 --- /dev/null +++ b/src/test/java/OperatorTest.java @@ -0,0 +1,43 @@ +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.assertj.core.api.Assertions.*; + + +public class OperatorTest { + + @DisplayName("plus, minus, multiply, divide 테스트") + @ParameterizedTest + @CsvSource(value = {"+, 12", "-, 8", "*, 20", "/,5"}, delimiter = ',') + void operatorTest(String value, String result){ + + assertThat(Operator.findOperator(value).operate(10, 2)).isEqualTo(Integer.parseInt(result)); + + } + @Test + void operatorPlusTest(){ + int result = Operator.PLUS.operate(1,5); + assertThat(result).isEqualTo(6); + } + + @Test + void operatorMinusTest(){ + int result = Operator.MINUS.operate(5, 3); + assertThat(result).isEqualTo(2); + } + + @Test + void operatorMultiplyTest(){ + int result = Operator.MULTIPLY.operate(10, 2); + assertThat(result).isEqualTo(20); + } + + @Test + void operatorDivideTest(){ + int result = Operator.DIVIDE.operate(100, 10); + assertThat(result).isEqualTo(10); + } + +} \ No newline at end of file diff --git a/src/test/java/StringCalcTest.java b/src/test/java/StringCalcTest.java new file mode 100644 index 000000000..313e29411 --- /dev/null +++ b/src/test/java/StringCalcTest.java @@ -0,0 +1,5 @@ +import static org.junit.jupiter.api.Assertions.*; + +class StringCalcTest { + +} \ No newline at end of file diff --git a/src/test/java/study/SetTest.java b/src/test/java/study/SetTest.java new file mode 100644 index 000000000..a0d70e2da --- /dev/null +++ b/src/test/java/study/SetTest.java @@ -0,0 +1,62 @@ +package study; + +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.assertj.core.api.Assertions.assertThat; + +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 Case 구현 + /** + * 요구사항 1 : size() + */ + @Test + void size_test() { + // given + + // when + int result = numbers.size(); + + // then + assertThat(result).isEqualTo(3); + } + /** + * 요구사항 2 : contains() + */ + @ParameterizedTest + @ValueSource(ints = {1, 2, 3}) + void contains_test(int input) { + // given + // when + // then + assertThat(numbers.contains(input)).isTrue(); + } + /** + * 요구사항 3 : contains() + */ + @ParameterizedTest + @CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':') + void contains_test(int input, boolean result) { + // given + // when + // then + assertThat(numbers.contains(input)).isEqualTo(result); + } +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java index 43e47d90b..62de6f26f 100644 --- a/src/test/java/study/StringTest.java +++ b/src/test/java/study/StringTest.java @@ -1,8 +1,10 @@ package study; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class StringTest { @Test @@ -10,4 +12,75 @@ void replace() { String actual = "abc".replace("b", "d"); assertThat(actual).isEqualTo("adc"); } + + /** + * 학습테스트 - 요구사항 1 : split() + */ + @Test + void split_test1() { + // given + String givenStr = "1,2"; + + // when + String[] splitResult = givenStr.split(","); + + // then + assertThat(splitResult).containsExactly("1", "2"); + } + + @Test + void split_test2() { + // given + String givenStr = "1"; + + // when + String[] splitResult = givenStr.split(","); + + // then + assertThat(splitResult).containsExactly("1"); + } + /** + * 학습테스트 - 요구사항 2 : subString() + */ + @Test + void subString_test() { + // given + String givenStr = "(1,2)"; + + // when + String result = givenStr.substring(1, 4); + + // then + assertThat(result).isEqualTo("1,2"); + } + + /** + * 학습테스트 - 요구사항 3 : charAt() + */ + @Test + @DisplayName("Stirng클래스의 charAt() 메소드로 특정 위치의 문자를 가져온다.") + void charAt_success_test() { + // given + String givenStr = "abc"; + + // when + char result = givenStr.charAt(1); + + // then + assertThat(result).isEqualTo("b"); + } + @Test + @DisplayName("Stirng클래스의 charAt() 메소드로 특정 위치의 문자를 가져오다가, 위치 값을 벗어나면 StringIndexOutOfBoundsException이 발생한다.") + void charAt_fail_test() { + // given + String givenStr = "abc"; + + // when + // then + assertThatThrownBy(() -> { + givenStr.charAt(5); + }).isInstanceOf(IndexOutOfBoundsException.class) + .hasMessageContaining("String index out of range: 5"); + + } }