diff --git a/docs/README.md b/docs/README.md index e69de29bb2..e39cb3e1c4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -0,0 +1,94 @@ +## 기능 명세 +1. 랜덤 정답 생성 기능 + - 정답 저장 기능 +2. 사용자 정답 입력 기능 + - input 숫자 여부 검증 및 예외처리 + - input 숫자의 길이 검증 및 예외처리 +3. Strike와 Ball 개수 판단 기능 + - 3 Strike인 경우 게임 종료 기능 + - 3 Strike가 아닌 경우 결과 출력 기능 +4. 정답인 경우 새 게임 진행 여부 입력 기능 + - input 1 or 2 검증 및 예외처리 + - input 1인 경우 새 게임 시작 기능 + - input 0인 경우 종료 기능 + +## 구현 클래스 명세 + +### Application - 실행을 담당 +- main() 어플리케이션의 실행 + +### BaseballController - 정답 관련 요청과 입력 검증을 담당 +- startGame() 하나의 게임 실행 +- askIsContinue() 게임 종료시 이어서 할 지에 대한 여부 검증 +- playGame() 게임 메인 로직 실행 +- getUserAttempt() 유저의 정답 시도 입력 +- getResult() 결과 계산 로직 실행 + +### BaseballService - 정답 관련 서비스 로직 담당 +- saveAnswer() 정답을 생성하여 저장 +- calculateResult() 결과를 계산 +- findCurrentAnswer() 현재 정답 정보를 조회 + +### BaseballRepository - 정답 정보 저장, 조회를 담당 +- saveAnswer() 정답 저장 +- findCurrentAnswer() 현재 정답 정보를 조회 + +### Answer - 정답 정보를 가진 불변클래스 +- generateRandomNumbers() 랜덤한 숫자를 생성 +- createAnswer() 불변클래스의 팩토리 메서드 +- hasNum() 매개변수로 받는 숫자가 정답에 포함됐는지 확인 + +### ComponentFactory - 컴포넌트들의 생성을 담당 +- 각 컴포넌트들을 생성 + +### InputValidator - 유저의 시도에 대한 입력값 검증 +- validateUserAttempt() 유저의 시도에 대한 입력값 검증 +- notValidAttemptString() 입력 String 이 유효한지 검증 +- hasDuplicate() 중복된 숫자가 입력되었는지 검증 +- validateIsContinue() 계속 진행할지 여부에 대한 입력 검증 +- notValidContinueString() 계속 진행할지 여부에 대한 입력값 검증 + +### InputReader - 사용자의 입력값 받아와 검증 +- readUserAttempt() 유저의 시도 입력 받기 및 입력값 검증 +- readIsContinue() 게임 이어서 하기 여부 입력 받기 및 입력값 검증 + +### OutputWriter - 문자열 출력 +- write() 문자열을 그대로 출력 +- writeWithLine() 맨 끝에 개행문자와 함께 출력 + +### ResultProvider - Answer 객체와 유저의 입력을 받아 결과를 반환 +- calculateResult() 최종 출력할 결과를 반환 +- mapToStrikeBalls() StrikeBall의 리스트로 변환 +- checkStrikeBall() 계산을 통해 StrikeBall 하나로 변환 및 반환 +- checkBallOrNone() 같은 인덱스에 같은 값이 없는 경우 ball 인지 판단 +- findAnswerNumByIndex() 정답 숫자에서 인덱스에 해당하는 숫자 반환 +- convertToIntWithIndex() String 에서 인덱스에 해당하는 숫자를 int 로 변환 + +### ResultOutputFormatter - 출력할 결과 포맷을 만듦 +- writeWithLine() 개행문자화 함께 출력 +- write() 문자열 그대로 출력 +- writeWithFormat() 결과 형태로 변환하여 출력 + +### Result - strike 개수롸 ball 개수를 갖는 dto +- getStrikeNum() strike 개수 반환 +- getBallNum() ball 개수 반환 + +### ResultOutputFormatter - Result를 결과 문자열로 변환 +- format() 결과 문자열로 변환 +- getFormattedOutput() format 진행 +- toCountResult() strike 혹은 ball 이 있을 경우 변환 진행 +- appendStrikeIfExists() strike의 개수에 따라 분기하여 변환 + +## 구현 열거형 명세 + +### GameMessage +- 게임의 메시지들을 나타낸다. + +### RandomNumberRange +- 랜덤한 숫자의 범위, 자릿수를 나타낸다. + +### StrikeBall +- 스트라이크, 볼을 나타낸다. + +### ResultMessage +- 결과 메시지를 나타낸다. diff --git a/src/main/java/baseball/Answer.java b/src/main/java/baseball/Answer.java new file mode 100644 index 0000000000..4328a272d9 --- /dev/null +++ b/src/main/java/baseball/Answer.java @@ -0,0 +1,38 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Randoms; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class Answer { + private final List currentAnswer; + + private Answer() { + this.currentAnswer = Collections.unmodifiableList(generateRandomNumbers()); + } + + public static Answer createAnswer() { + return new Answer(); + } + + private List generateRandomNumbers() { + List randomNumbers = new ArrayList<>(); + while (randomNumbers.size() < 3) { + int randomNumber = Randoms.pickNumberInRange(1, 9); + if (!randomNumbers.contains(randomNumber)) { + randomNumbers.add(randomNumber); + } + } + return randomNumbers; + } + + public Integer findByIndex(final Integer index) { + return currentAnswer.get(index); + } + + public boolean hasNum(final int attemptNum) { + return currentAnswer.contains(attemptNum); + } +} diff --git a/src/main/java/baseball/Application.java b/src/main/java/baseball/Application.java index dd95a34214..75c1ab3827 100644 --- a/src/main/java/baseball/Application.java +++ b/src/main/java/baseball/Application.java @@ -2,6 +2,8 @@ public class Application { public static void main(String[] args) { - // TODO: 프로그램 구현 + final ComponentFactory componentFactory = new ComponentFactory(); + final BaseballController baseballController = componentFactory.baseballController(); + baseballController.startGame(); } } diff --git a/src/main/java/baseball/BaseballController.java b/src/main/java/baseball/BaseballController.java new file mode 100644 index 0000000000..9e9e49a4dc --- /dev/null +++ b/src/main/java/baseball/BaseballController.java @@ -0,0 +1,59 @@ +package baseball; + +public class BaseballController { + private static final int CONTINUE_COMMAND = 1; + private static final int ATTEMPT_SUCCESS = 3; + private final BaseballService baseballService; + private final OutputWriter outputWriter; + private final InputReader inputReader; + + public BaseballController( + final BaseballService baseballService, + final OutputWriter outputWriter, + final InputReader inputReader) { + + this.baseballService = baseballService; + this.outputWriter = outputWriter; + this.inputReader = inputReader; + } + + public void startGame() { + boolean isContinue = true; + while (isContinue) { + outputWriter.writeWithLine(GameMessage.GAME_START); + baseballService.saveAnswer(); + playGame(); + isContinue = askIsContinue(); + } + } + + private boolean askIsContinue() { + outputWriter.writeWithLine(GameMessage.CREATE_NEW_GAME_OR_NOT); + final String input = inputReader.readIsContinue(); + return Integer.parseInt(input) == CONTINUE_COMMAND; + } + + private void playGame() { + boolean isContinue = true; + while (isContinue) { + final String userAttempt = getUserAttempt(); + final Result result = getResult(userAttempt); + + if (result.getStrikeNum() == ATTEMPT_SUCCESS) { + outputWriter.writeWithLine(GameMessage.GAME_FINISH); + isContinue = false; + } + } + } + + private String getUserAttempt() { + outputWriter.write(GameMessage.INPUT_NEXT_NUMBER); + return inputReader.readUserAttempt(); + } + + private Result getResult(final String userAttempt) { + final Result result = baseballService.calculateResult(userAttempt); + outputWriter.writeWithFormat(result); + return result; + } +} diff --git a/src/main/java/baseball/BaseballRepository.java b/src/main/java/baseball/BaseballRepository.java new file mode 100644 index 0000000000..efad2ae4ed --- /dev/null +++ b/src/main/java/baseball/BaseballRepository.java @@ -0,0 +1,13 @@ +package baseball; + +public class BaseballRepository { + private Answer answer; + + public void saveAnswer(final Answer answer) { + this.answer = answer; + } + + public Answer findCurrentAnswer() { + return this.answer; + } +} diff --git a/src/main/java/baseball/BaseballService.java b/src/main/java/baseball/BaseballService.java new file mode 100644 index 0000000000..e0dbf36b5c --- /dev/null +++ b/src/main/java/baseball/BaseballService.java @@ -0,0 +1,24 @@ +package baseball; + +public class BaseballService { + private final BaseballRepository baseballRepository; + + public BaseballService(final BaseballRepository baseballRepository) { + this.baseballRepository = baseballRepository; + } + + public void saveAnswer() { + final Answer answer = Answer.createAnswer(); + baseballRepository.saveAnswer(answer); + } + + public Result calculateResult(final String attempt) { + final Answer currentAnswer = findCurrentAnswer(); + final ResultProvider resultProvider = new ResultProvider(currentAnswer, attempt); + return resultProvider.calculateResult(); + } + + private Answer findCurrentAnswer() { + return baseballRepository.findCurrentAnswer(); + } +} diff --git a/src/main/java/baseball/ComponentFactory.java b/src/main/java/baseball/ComponentFactory.java new file mode 100644 index 0000000000..e2760e2ed0 --- /dev/null +++ b/src/main/java/baseball/ComponentFactory.java @@ -0,0 +1,35 @@ +package baseball; + +public class ComponentFactory { + + public BaseballController baseballController() { + return new BaseballController( + baseballService(), + outputWriter(), + inputReader()); + } + + private ResultOutputFormatter resultOutputFormatter() { + return new ResultOutputFormatter(); + } + + private InputReader inputReader() { + return new InputReader(inputValidator()); + } + + private OutputWriter outputWriter() { + return new OutputWriter(resultOutputFormatter()); + } + + private BaseballService baseballService() { + return new BaseballService(baseballRepository()); + } + + private BaseballRepository baseballRepository() { + return new BaseballRepository(); + } + + private InputValidator inputValidator() { + return new InputValidator(); + } +} diff --git a/src/main/java/baseball/GameMessage.java b/src/main/java/baseball/GameMessage.java new file mode 100644 index 0000000000..7d257525c6 --- /dev/null +++ b/src/main/java/baseball/GameMessage.java @@ -0,0 +1,18 @@ +package baseball; + +public enum GameMessage { + GAME_START("숫자 야구 게임을 시작합니다."), + INPUT_NEXT_NUMBER("숫자를 입력해주세요 : "), + GAME_FINISH("3개의 숫자를 모두 맞히셨습니다! 게임 종료"), + CREATE_NEW_GAME_OR_NOT("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + private final String message; + + GameMessage(final String message) { + this.message = message; + } + + @Override + public String toString() { + return this.message; + } +} diff --git a/src/main/java/baseball/InputReader.java b/src/main/java/baseball/InputReader.java new file mode 100644 index 0000000000..b18103ca85 --- /dev/null +++ b/src/main/java/baseball/InputReader.java @@ -0,0 +1,23 @@ +package baseball; + +import camp.nextstep.edu.missionutils.Console; + +public class InputReader { + private final InputValidator inputValidator; + + public InputReader(final InputValidator inputValidator) { + this.inputValidator = inputValidator; + } + + public String readUserAttempt() { + final String input = Console.readLine(); + inputValidator.validateUserAttempt(input); + return input; + } + + public String readIsContinue() { + final String input = Console.readLine(); + inputValidator.validateIsContinue(input); + return input; + } +} diff --git a/src/main/java/baseball/InputValidator.java b/src/main/java/baseball/InputValidator.java new file mode 100644 index 0000000000..3e8364aa52 --- /dev/null +++ b/src/main/java/baseball/InputValidator.java @@ -0,0 +1,43 @@ +package baseball; + +public class InputValidator { + private static final String NUMERIC_MATCHER = "-?\\d+"; + private static final Integer IS_CONTINUE_LENGTH = 1; + private static final Integer CONTINUE = 1; + private static final Integer NOT_CONTINUE = 2; + + + public void validateUserAttempt(final String userAttempt) { + if (notValidAttemptString(userAttempt) || hasDuplicate(userAttempt)) { + throw new IllegalArgumentException(); + } + } + + private boolean notValidAttemptString(final String userAttempt) { + return userAttempt.isBlank() + || !userAttempt.matches(NUMERIC_MATCHER) + || userAttempt.length() != RandomNumberRange.CIPHER.getNum(); + } + + private boolean hasDuplicate(final String userAttempt) { + final long count = userAttempt.chars().distinct().count(); + return count != 3; + } + + public void validateIsContinue(final String isContinueInput) { + if (notValidIsContinueString(isContinueInput) || isOutOfRange(isContinueInput)) { + throw new IllegalArgumentException(); + } + } + + private boolean notValidIsContinueString(final String isContinueInput) { + return isContinueInput.isBlank() + || !isContinueInput.matches(NUMERIC_MATCHER) + || isContinueInput.length() != IS_CONTINUE_LENGTH; + } + + private boolean isOutOfRange(final String isContinueInput) { + final int input = Integer.parseInt(isContinueInput); + return input != CONTINUE && input != NOT_CONTINUE; + } +} diff --git a/src/main/java/baseball/OutputWriter.java b/src/main/java/baseball/OutputWriter.java new file mode 100644 index 0000000000..ecf75ca105 --- /dev/null +++ b/src/main/java/baseball/OutputWriter.java @@ -0,0 +1,21 @@ +package baseball; + +public class OutputWriter { + private final ResultOutputFormatter resultOutputFormatter; + + public OutputWriter(final ResultOutputFormatter resultOutputFormatter) { + this.resultOutputFormatter = resultOutputFormatter; + } + + public void writeWithLine(final GameMessage gameMessage) { + System.out.println(gameMessage); + } + + public void write(final GameMessage gameMessage) { + System.out.print(gameMessage); + } + + public void writeWithFormat(final Result result) { + System.out.println(resultOutputFormatter.format(result)); + } +} diff --git a/src/main/java/baseball/RandomNumberRange.java b/src/main/java/baseball/RandomNumberRange.java new file mode 100644 index 0000000000..c910ef4b65 --- /dev/null +++ b/src/main/java/baseball/RandomNumberRange.java @@ -0,0 +1,17 @@ +package baseball; + +public enum RandomNumberRange { + MIN(1), + MAX(9), + CIPHER(3); + + private final Integer num; + + RandomNumberRange(final Integer num) { + this.num = num; + } + + public Integer getNum() { + return num; + } +} diff --git a/src/main/java/baseball/Result.java b/src/main/java/baseball/Result.java new file mode 100644 index 0000000000..3e1562fc37 --- /dev/null +++ b/src/main/java/baseball/Result.java @@ -0,0 +1,19 @@ +package baseball; + +public class Result { + private final int strikeNum; + private final int ballNum; + + public Result(final int strikeNum, final int ballNum) { + this.strikeNum = strikeNum; + this.ballNum = ballNum; + } + + public int getStrikeNum() { + return this.strikeNum; + } + + public int getBallNum() { + return this.ballNum; + } +} diff --git a/src/main/java/baseball/ResultMessage.java b/src/main/java/baseball/ResultMessage.java new file mode 100644 index 0000000000..63e55e3c76 --- /dev/null +++ b/src/main/java/baseball/ResultMessage.java @@ -0,0 +1,18 @@ +package baseball; + +public enum ResultMessage { + BALL("%d볼"), + STRIKE("%d스트라이크"), + NOTHING("낫싱"); + + private final String message; + + ResultMessage(final String message) { + this.message = message; + } + + @Override + public String toString() { + return this.message; + } +} diff --git a/src/main/java/baseball/ResultOutputFormatter.java b/src/main/java/baseball/ResultOutputFormatter.java new file mode 100644 index 0000000000..b004e5f893 --- /dev/null +++ b/src/main/java/baseball/ResultOutputFormatter.java @@ -0,0 +1,38 @@ +package baseball; + +public class ResultOutputFormatter { + private static final int NONE = 0; + private static final String BLANK = " "; + + public String format(final Result result) { + final int ballNum = result.getBallNum(); + final int strikeNum = result.getStrikeNum(); + + return getFormattedOutput(ballNum, strikeNum); + } + + private String getFormattedOutput(final int ballNum, final int strikeNum) { + if (ballNum == NONE && strikeNum == NONE) { + return ResultMessage.NOTHING.toString(); + } + return toCountResult(ballNum, strikeNum); + } + + private String toCountResult(final int ballNum, final int strikeNum) { + final StringBuilder stringBuilder = new StringBuilder(); + if (ballNum != NONE) { + stringBuilder + .append(String.format(ResultMessage.BALL.toString(), ballNum)) + .append(BLANK); + } + return appendStrikeIfExists(stringBuilder, strikeNum); + } + + private String appendStrikeIfExists(final StringBuilder stringBuilder, final int strikeNum) { + if (strikeNum != NONE) { + stringBuilder + .append(String.format(ResultMessage.STRIKE.toString(), strikeNum)); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/baseball/ResultProvider.java b/src/main/java/baseball/ResultProvider.java new file mode 100644 index 0000000000..a0ae747caf --- /dev/null +++ b/src/main/java/baseball/ResultProvider.java @@ -0,0 +1,53 @@ +package baseball; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class ResultProvider { + private final Answer answer; + private final String attempt; + + public ResultProvider(final Answer answer, final String attempt) { + this.answer = answer; + this.attempt = attempt; + } + + public Result calculateResult() { + final List strikeBalls = mapToStrikeBalls(); + final int strikeCount = Collections.frequency(strikeBalls, StrikeBall.STRIKE); + final int ballCount = Collections.frequency(strikeBalls, StrikeBall.BALL); + return new Result(strikeCount, ballCount); + } + + private List mapToStrikeBalls() { + return IntStream.range(0, 3).mapToObj(i -> { + final int attemptNum = convertToIntWithIndex(i); + final int answerNum = findAnswerNumByIndex(i); + return checkStrikeBall(answerNum, attemptNum, i); + }).collect(Collectors.toUnmodifiableList()); + } + + private StrikeBall checkStrikeBall(final int answerNum, final int attemptNum, final int index) { + if (answerNum == attemptNum && attemptNum == findAnswerNumByIndex(index)) { + return StrikeBall.STRIKE; + } + return checkBallOrNone(attemptNum); + } + + private StrikeBall checkBallOrNone(final int attemptNum) { + if (answer.hasNum(attemptNum)) { + return StrikeBall.BALL; + } + return StrikeBall.NONE; + } + + private int findAnswerNumByIndex(final int index) { + return answer.findByIndex(index); + } + + private int convertToIntWithIndex(final int stringIndex) { + return Integer.parseInt(String.valueOf(attempt.charAt(stringIndex))); + } +} diff --git a/src/main/java/baseball/StrikeBall.java b/src/main/java/baseball/StrikeBall.java new file mode 100644 index 0000000000..636b569d4b --- /dev/null +++ b/src/main/java/baseball/StrikeBall.java @@ -0,0 +1,5 @@ +package baseball; + +public enum StrikeBall { + STRIKE, BALL, NONE +} diff --git a/src/test/java/baseball/BaseballRepositoryTest.java b/src/test/java/baseball/BaseballRepositoryTest.java new file mode 100644 index 0000000000..38611c3bd4 --- /dev/null +++ b/src/test/java/baseball/BaseballRepositoryTest.java @@ -0,0 +1,25 @@ +package baseball; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("BaseRepository의") +class BaseballRepositoryTest { + private final BaseballRepository baseballRepository = new BaseballRepository(); + + @Test + @DisplayName("저장후 조회 로직이 수행되는가") + void saveAnswerAndGet() { + //given + final Answer answer = Answer.createAnswer(); + + //when + baseballRepository.saveAnswer(answer); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + + //then + assertThat(answer).isEqualTo(currentAnswer); + } +} diff --git a/src/test/java/baseball/BaseballServiceTest.java b/src/test/java/baseball/BaseballServiceTest.java new file mode 100644 index 0000000000..4233fcb6d7 --- /dev/null +++ b/src/test/java/baseball/BaseballServiceTest.java @@ -0,0 +1,82 @@ +package baseball; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("BaseballService 의") +class BaseballServiceTest { + private final BaseballRepository baseballRepository = new BaseballRepository(); + private final BaseballService baseballService = new BaseballService(baseballRepository); + + + @Test + @DisplayName("정답 저장 로직이 수행되는가") + void saveAnswer() { + //given + + //when + baseballService.saveAnswer(); + + //then + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + assertThat(currentAnswer).isNotNull(); + } + + @Nested + @DisplayName("결과 계산 로직 중") + class CalculateResult { + @Test + @DisplayName("3스트라이크 결과 반환이 수행되는가") + void threeStrike() { + //given + baseballService.saveAnswer(); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + final Integer first = currentAnswer.findByIndex(0); + final Integer second = currentAnswer.findByIndex(1); + final Integer third = currentAnswer.findByIndex(2); + + //when +// final BallCount ballCount = baseballService.calculateResult(Integer.toString(first) + Integer.toString(second) + Integer.toString(third)); + + //then +// assertThat(ballCount).isEqualTo(BallCount.THREE_STRIKE); + } + + @Test + @DisplayName("3볼 결과 반환이 수행되는가") + void threeBall() { + //given + baseballService.saveAnswer(); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + final Integer first = currentAnswer.findByIndex(0); + final Integer second = currentAnswer.findByIndex(1); + final Integer third = currentAnswer.findByIndex(2); + + //when +// final BallCount ballCount = baseballService.calculateResult(Integer.toString(third) + Integer.toString(first) + Integer.toString(second)); + + //then +// assertThat(ballCount).isEqualTo(BallCount.THREE_BALL); + } + + @Test + @DisplayName("2볼 1스트라이크 결과 반환이 수행되는가") + void oneStrikeTwoBall() { + //given + baseballService.saveAnswer(); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + final Integer first = currentAnswer.findByIndex(0); + final Integer second = currentAnswer.findByIndex(1); + final Integer third = currentAnswer.findByIndex(2); + + //when +// final BallCount ballCount = baseballService.calculateResult(Integer.toString(first) + Integer.toString(third) + Integer.toString(second)); + + //then +// assertThat(ballCount).isEqualTo(BallCount.TWO_BALL_ONE_STRIKE); + } + } +} diff --git a/src/test/java/baseball/InputValidatorTest.java b/src/test/java/baseball/InputValidatorTest.java new file mode 100644 index 0000000000..07c9b52ae6 --- /dev/null +++ b/src/test/java/baseball/InputValidatorTest.java @@ -0,0 +1,72 @@ +package baseball; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("InputValidator의") +class InputValidatorTest { + private final InputValidator inputValidator = new InputValidator(); + + @Nested + @DisplayName("유저의 시도 검증 중") + class ValidateUserAttempt { + @Test + @DisplayName("입력값 길이 검증이 수행되는가") + void validateLength() { + assertThatThrownBy(() -> inputValidator.validateUserAttempt("1234")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("중복 값 검증이 수행되는가") + void validateDuplicate() { + assertThatThrownBy(() -> inputValidator.validateUserAttempt("122")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("빈 값 검증이 수행되는가") + void validateBlank() { + assertThatThrownBy(() -> inputValidator.validateUserAttempt("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("정상 입력값 검증이 수행되는가") + void validate() { + inputValidator.validateUserAttempt("123"); + inputValidator.validateUserAttempt("275"); + } + } + + @Nested + @DisplayName("게임 이어서 하기 여부 검증 중") + class ValidateIsContinue { + @Test + @DisplayName("입력값 길이 검증이 수행되는가") + void validateLength() { + assertThatThrownBy(() -> inputValidator.validateIsContinue("1234")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("입력값 범위 검증이 수행되는가") + void validateRange() { + assertThatThrownBy(() -> inputValidator.validateIsContinue("3")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + @DisplayName("정상 입력값 검증이 수행되는가") + void validate() { + inputValidator.validateIsContinue("1"); + inputValidator.validateIsContinue("2"); + } + } +} diff --git a/src/test/java/baseball/ResultProviderTest.java b/src/test/java/baseball/ResultProviderTest.java new file mode 100644 index 0000000000..816009699c --- /dev/null +++ b/src/test/java/baseball/ResultProviderTest.java @@ -0,0 +1,82 @@ +package baseball; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("ResultProvider의") +class ResultProviderTest { + private final BaseballRepository baseballRepository = new BaseballRepository(); + + @Nested + @DisplayName("결과 계산 로직 중") + class GetResult { + @Test + @DisplayName("3스트라이크가 반환되는가") + void threeStrikeResult() { + //given + final Answer answer = Answer.createAnswer(); + baseballRepository.saveAnswer(answer); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + + final ResultProvider resultProvider = + new ResultProvider( + answer, + Integer.toString(currentAnswer.findByIndex(0)) + + Integer.toString(currentAnswer.findByIndex(1)) + + Integer.toString(currentAnswer.findByIndex(2))); + + //when +// final BallCount result = resultProvider.calculateResult(); + + //then +// assertThat(result).isEqualTo(BallCount.THREE_STRIKE); + } + + @Test + @DisplayName("3볼이 반환되는가") + void threeBallResult() { + //given + final Answer answer = Answer.createAnswer(); + baseballRepository.saveAnswer(answer); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + + final ResultProvider resultProvider = + new ResultProvider( + answer, + Integer.toString(currentAnswer.findByIndex(2)) + + Integer.toString(currentAnswer.findByIndex(0)) + + Integer.toString(currentAnswer.findByIndex(1))); + + //when +// final BallCount result = resultProvider.calculateResult(); + + //then +// assertThat(result).isEqualTo(BallCount.THREE_BALL); + } + + @Test + @DisplayName("2볼 1스트라이크가 반환되는가") + void twoBallOneStrikeResult() { + //given + final Answer answer = Answer.createAnswer(); + baseballRepository.saveAnswer(answer); + final Answer currentAnswer = baseballRepository.findCurrentAnswer(); + + final ResultProvider resultProvider = + new ResultProvider( + answer, + Integer.toString(currentAnswer.findByIndex(0)) + + Integer.toString(currentAnswer.findByIndex(2)) + + Integer.toString(currentAnswer.findByIndex(1))); + + //when +// final BallCount result = resultProvider.calculateResult(); + + //then +// assertThat(result).isEqualTo(BallCount.TWO_BALL_ONE_STRIKE); + } + } +}