Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

임아리 1주차 미션 제출합니다. #46

Merged
merged 16 commits into from
Jan 30, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@ repositories {
dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.assertj:assertj-core')
}

test {
15 changes: 15 additions & 0 deletions src/main/java/SimpleCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
public class SimpleCalculator {
public int add(int firstNum, int secondNum){
return firstNum + secondNum;
}
public int multiply(int firstNum, int secondNum){
return firstNum * secondNum;
}
public int divide(int firstNum, int secondNum){
return firstNum / secondNum;
}
public int minus(int firstNum, int secondNum){
return firstNum - secondNum;
}

}
83 changes: 83 additions & 0 deletions src/main/java/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
input을 받고 빈문자열인지 null인지 체크
구분자 체크 -> 구분자 예외 체크
구분자 대로 문자열 계산기 구현
*/

import java.util.regex.Pattern;

public class StringCalculator {

//입력 문자열이 null인지 확인
public String checkInput(String input){
if(input == null) throw new RuntimeException("null은 허용되지 않습니다.");
return input;
}
Comment on lines +12 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkInput메소드에서 결과를 반환하지 않아도 될 것 같습니다!

Suggested change
public String checkInput(String input){
if(input == null) throw new RuntimeException("null은 허용되지 않습니다.");
return input;
}
public void validateInput(String input){
if(input == null) {
throw new RuntimeException("null은 허용되지 않습니다.");
}
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇네요... 확실히 input을 반환하지 않고 잘못된 입력이면 예외를 발생하면 될 것 같습니다!


//커스텀 구분자가 있는지 확인
public int checkDelimiter(String checkedInput) {
if(checkedInput.isEmpty()) return -2; //문자열이 빈 경우


if (checkedInput.startsWith("//")) { //커스텀 구분자를 설정하는가?
int idx = checkedInput.indexOf("\n"); //제대로된 형식인가?
if (idx == -1) throw new RuntimeException("잘못된 커스텀 구분자 형식입니다.");
return idx; //구분자 위치 전달
}

return -1; //기본 구분자대로 문자열을 나눔
}
Comment on lines +18 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

커스텀 구분자가 있는지 확인하기 보단, 커스텀 구분자가 를 추출해서 반환해주면 좋을 것 같아요!
커스텀 구분자가 있으면 커스텀 구분자를 추출하고 아니면 빈 문자열 반환

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extractDelimiter과 같은 함수를 만들어서 입력 문자열에서 구분자를 추출하는 함수를 만들어도 좋을 것 같아요.

Suggested change
public int checkDelimiter(String checkedInput) {
if(checkedInput.isEmpty()) return -2; //문자열이 빈 경우
if (checkedInput.startsWith("//")) { //커스텀 구분자를 설정하는가?
int idx = checkedInput.indexOf("\n"); //제대로된 형식인가?
if (idx == -1) throw new RuntimeException("잘못된 커스텀 구분자 형식입니다.");
return idx; //구분자 위치 전달
}
return -1; //기본 구분자대로 문자열을 나눔
}
public String extractDelimiter(String input) {
String delimiter = ",:";
if (checkedInput.startsWith("//")) { //커스텀 구분자를 설정하는가?
int index = checkedInput.indexOf("\n"); //제대로된 형식인가?
if (index == -1) throw new RuntimeException("잘못된 커스텀 구분자 형식입니다.");
delimiter += input.subString(커스텀구분자 시작index, 커스텀구분자 종료index);
}
return delimiter;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkDelimiter에 맞는 내용만 생각해서 구분자가 있는지 확인하는 함수로만 만들려고 생각한것 같습니다. 알려주셔서 감사합니다!


private String[] splitInput(String checkedInput, int idx){
if(idx == -1){
String delimiter = "[,:]";
return checkedInput.split(delimiter); //기본 구분자대로 나누기
}
else if(idx == -2){
return new String[0]; //빈 문자열인 경우
}
else{
String delimiter = checkedInput.substring(2, idx); //구분자 나누기
String regex = Pattern.quote(delimiter); //정규표현식에 사용되는 문자가 커스텀 구분자일 경우를 위해 설정
return checkedInput.substring(idx + 1).split(regex); //커스텀 구분자대로 문자열을 나눔
}
}

//문자열 덧셈 실행
public int sum(String[] strings){

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sum의 인자가 문자열의 배열보단 정수의 배열로 받는게 자연스러운 흐름인 것 같습니다!
두 문자열을 더한다 보단 두 정수를 더한다가 더 자연스러움

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가로 인자로 주어진 수를 더하는 sum에서는 수를 더하는 역할만 하는게 바람직해 보이는데 지금의 경우 문자열에 대한 검증과 변환까지 하고 있어서 함수의 역할이 흐려지는것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확실히 sum에서는 덧셈만 하는게 맞을거 같습니다! 피드백 감사합니다!

if(strings.length == 0) return 0;

int sum = 0;

for(var n : strings){
if(n.isEmpty()) throw new RuntimeException("빈 문자열입니다.");

int num = checkException(n);

//예외 처리
if(sum > Integer.MAX_VALUE - num || sum < Integer.MIN_VALUE + num) throw new RuntimeException("int 범위를 벗어났습니다.");

sum += num;
}
return sum;
}

private int checkException(String n){
int num;
try{
num = Integer.parseInt(n);
if(num < 0) throw new RuntimeException("음수는 입력이 불가합니다.");
}
catch(NumberFormatException msg){
throw new RuntimeException("int 값을 벗어났거나 잘못된 숫자 형식입니다.");
}
return num;
}

public int calculate(String input){
String checkedInput = checkInput(input);
int idx = checkDelimiter(checkedInput);
String[] strings = splitInput(checkedInput, idx);
return sum(strings);
}
}
37 changes: 37 additions & 0 deletions src/test/java/SimpleCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class SimpleCalculatorTest {
@Nested
class SimpleTest {

@Test
void addTest(){
SimpleCalculator calc = new SimpleCalculator();
assertEquals(3, calc.add(1, 2));
assertEquals(5, calc.add(3, 2));
}

@Test
void minusTest(){
SimpleCalculator calc = new SimpleCalculator();
assertEquals(3, calc.minus(5, 2));
assertEquals(-2, calc.minus(3, 5));
}

@Test
void multiply(){
SimpleCalculator calc = new SimpleCalculator();
assertEquals(10, calc.multiply(5, 2));
assertEquals(15, calc.multiply(3, 5));
}

@Test
void divide(){
SimpleCalculator calc = new SimpleCalculator();
assertEquals(5, calc.divide(10, 2));
assertEquals(30, calc.divide(180, 6));
}
}
}
47 changes: 47 additions & 0 deletions src/test/java/StringCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class StringCalculatorTest {
@Nested
class StringTest{
@Test
void default_delimiter_Test(){
StringCalculator calc = new StringCalculator();
assertEquals(3, calc.calculate("1,2"));
assertEquals(6, calc.calculate("1,2,3"));
assertEquals(3, calc.calculate("1:2"));
assertEquals(38, calc.calculate("1:2,3:4,5:6:7:10"));
assertEquals(0, calc.calculate(""));
}

@Test
void custom_delimiter_Test(){
StringCalculator calc = new StringCalculator();
assertEquals(6, calc.calculate("//;\n1;2;3"));
assertEquals(5, calc.calculate("//;;\n1;;1;;2;;1"));
assertEquals(6, calc.calculate("//.\n1.2.3"));
assertEquals(3, calc.calculate("//|\n1|2"));
assertEquals(101, calc.calculate("//?\n10?11?12?13?14?20?21"));
}

@Test
void exceptionTest(){
StringCalculator calc = new StringCalculator();

RuntimeException exception = assertThrows(RuntimeException.class, () ->
calc.calculate("-1,2")
);

assertEquals("음수는 입력이 불가합니다.", exception.getMessage());

RuntimeException exception2 = assertThrows(RuntimeException.class, () ->
calc.calculate("2147483647,10")
);

assertEquals("int 범위를 벗어났습니다.", exception2.getMessage());
}
}
}
36 changes: 36 additions & 0 deletions src/test/java/TestWithAssertJ.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestWithAssertJ {
@Nested
class CalculatorTest{
@Test
void simpleCalcTest(){
SimpleCalculator calc = new SimpleCalculator();
assertThat(calc.add(1, 2)).isEqualTo(3);
assertThat(calc.minus(1,2)).isEqualTo(-1);
assertThat(calc.divide(4, 2)).isEqualTo(2);
assertThat(calc.multiply(3,2)).isEqualTo(6);
}

@Test
void stringCalcTest(){
StringCalculator calc = new StringCalculator();
assertThat(calc.calculate("//;\n1;2;3")).isEqualTo(6);
assertThat(calc.calculate("//?\n10?11?12?13?14?20?21")).isEqualTo(101);
}

@Test
void exceptionTest(){
StringCalculator calc = new StringCalculator();
assertThatThrownBy(() ->
calc.calculate("-1,2")).isInstanceOf(RuntimeException.class);

assertThatThrownBy(() -> calc.calculate("//:123")).isInstanceOf(RuntimeException.class);
}
}
}