diff --git a/build.gradle b/build.gradle index 45d61697f..edc026cd8 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(11) } } diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..524ff36aa --- /dev/null +++ b/docs/README.md @@ -0,0 +1,20 @@ +# 자동차 경주 게임 + +## 기능 목록 + +### 자동차 게임 기능 +- [x] 주어진 횟수를 입력받는 기능 + - [x] 횟수가 숫자가 아닐시 예외 발생 기능 + - [x] 횟수가 음수 또는 너무 큰 수 일시 예외 발생 기능 +- [x] 주어진 횟수 동안 n대의 자동차는 전진 또는 멈춤 기능 + - [x] 움직인 결과 출력 기능 +- [x] 자동차 경주 게임을 완료한 후 누가 우승했는지 출력하는 기능 + - [x] 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분하여 출력하는 기능 + +### 자동차 기능 +- [x] 자동차에 이름을 입력받는 기능 + - [x] 자동차 이름은 쉼표(,)를 기준으로 구분하는 기능 + - [x] 쉼표(,) 여러개를 입력해도 인식 가능한 기능 + - [x] 이름은 5자 초과시 예외 발생 기능 +- [x] 자동차는 전진 또는 멈춤 기능 + - [x] 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 때 전진 기능 \ No newline at end of file diff --git a/src/main/java/racingcar/Application.java b/src/main/java/racingcar/Application.java index b9ed0456a..c862b4f47 100644 --- a/src/main/java/racingcar/Application.java +++ b/src/main/java/racingcar/Application.java @@ -1,7 +1,11 @@ package racingcar; +import racingcar.controller.RacingCarController; + public class Application { + public static void main(String[] args) { - // TODO 구현 진행 + RacingCarController racingCarController = new RacingCarController(); + racingCarController.runGame(); } } diff --git a/src/main/java/racingcar/Car.java b/src/main/java/racingcar/Car.java deleted file mode 100644 index ab3df9492..000000000 --- a/src/main/java/racingcar/Car.java +++ /dev/null @@ -1,12 +0,0 @@ -package racingcar; - -public class Car { - private final String name; - private int position = 0; - - public Car(String name) { - this.name = name; - } - - // 추가 기능 구현 -} diff --git a/src/main/java/racingcar/controller/RacingCarController.java b/src/main/java/racingcar/controller/RacingCarController.java new file mode 100644 index 000000000..acdcc0977 --- /dev/null +++ b/src/main/java/racingcar/controller/RacingCarController.java @@ -0,0 +1,49 @@ +package racingcar.controller; + +import racingcar.domain.CarRandomMoveNumberGenerator; +import racingcar.domain.Cars; +import racingcar.domain.RacingCarGame; +import racingcar.domain.TryCommand; +import racingcar.view.InputView; +import racingcar.view.OutputView; + +public class RacingCarController { + + private final InputView inputView = new InputView(); + private final OutputView outputView = new OutputView(); + private RacingCarGame racingCarGame; + + public void runGame() { + makeRacingCarGame(); + playGame(); + endGame(); + } + + private void endGame() { + outputView.printWinner(racingCarGame.findWinner()); + } + + private void playGame() { + TryCommand tryCommand = askTryCommand(); + while(tryCommand.tryMove()){ + racingCarGame.move(); + outputView.printResult(racingCarGame.getCars()); + } + } + + private void makeRacingCarGame() { + racingCarGame = new RacingCarGame(askCar()); + outputView.printBlank(); + } + + private TryCommand askTryCommand() { + outputView.printInputTry(); + return new ReEnterProcessor<>(inputView::readTryCommand, outputView::printExceptionMessage).process(); + } + + + private Cars askCar() { + outputView.printInputCarName(); + return new ReEnterProcessor<>(inputView::readCarName, outputView::printExceptionMessage).process(); + } +} diff --git a/src/main/java/racingcar/controller/ReEnterProcessor.java b/src/main/java/racingcar/controller/ReEnterProcessor.java new file mode 100644 index 000000000..d06f54816 --- /dev/null +++ b/src/main/java/racingcar/controller/ReEnterProcessor.java @@ -0,0 +1,24 @@ +package racingcar.controller; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ReEnterProcessor { + private final Supplier processor; + private final Consumer consumer; + + public ReEnterProcessor(Supplier processor, Consumer consumer) { + this.processor = processor; + this.consumer = consumer; + } + + public T process() { + while(true){ + try { + return processor.get(); + }catch (IllegalArgumentException exception){ + consumer.accept(exception); + } + } + } +} diff --git a/src/main/java/racingcar/domain/Car.java b/src/main/java/racingcar/domain/Car.java new file mode 100644 index 000000000..494db6685 --- /dev/null +++ b/src/main/java/racingcar/domain/Car.java @@ -0,0 +1,42 @@ +package racingcar.domain; + +import racingcar.exception.CarNameLengthException; + +public class Car { + + private static final int CAR_NAME_LENGTH = 5; + private static final int MOVABLE_MIN_NUMBER = 4; + private final String name; + private int position = 0; + + public Car(String name) { + validate(name); + this.name = name; + } + + private void validate(String name) { + validateLength(name); + } + + private void validateLength(String name) { + if (name.length() > CAR_NAME_LENGTH) { + throw new CarNameLengthException(); + } + } + + public void move(CarMoveNumberGenerator carMoveNumberGenerator) { + final int number = carMoveNumberGenerator.generate(); + + if (number >= MOVABLE_MIN_NUMBER) { + position++; + } + } + + public String getName() { + return name; + } + + public int getPosition() { + return position; + } +} diff --git a/src/main/java/racingcar/domain/CarMoveNumberGenerator.java b/src/main/java/racingcar/domain/CarMoveNumberGenerator.java new file mode 100644 index 000000000..c7be924c9 --- /dev/null +++ b/src/main/java/racingcar/domain/CarMoveNumberGenerator.java @@ -0,0 +1,6 @@ +package racingcar.domain; + +public interface CarMoveNumberGenerator { + + int generate(); +} diff --git a/src/main/java/racingcar/domain/CarRandomMoveNumberGenerator.java b/src/main/java/racingcar/domain/CarRandomMoveNumberGenerator.java new file mode 100644 index 000000000..6646476e8 --- /dev/null +++ b/src/main/java/racingcar/domain/CarRandomMoveNumberGenerator.java @@ -0,0 +1,14 @@ +package racingcar.domain; + +import camp.nextstep.edu.missionutils.Randoms; + +public class CarRandomMoveNumberGenerator implements CarMoveNumberGenerator { + + private static final int RANDOM_LOWER_INCLUSIVE = 0; + private static final int RANDOM_UPPER_INCLUSIVE = 9; + + @Override + public int generate() { + return Randoms.pickNumberInRange(RANDOM_LOWER_INCLUSIVE, RANDOM_UPPER_INCLUSIVE); + } +} diff --git a/src/main/java/racingcar/domain/Cars.java b/src/main/java/racingcar/domain/Cars.java new file mode 100644 index 000000000..8d571a743 --- /dev/null +++ b/src/main/java/racingcar/domain/Cars.java @@ -0,0 +1,71 @@ +package racingcar.domain; + +import racingcar.exception.CarsDuplicatedNameException; +import racingcar.exception.CarsMaxScoreBlankException; + +import java.util.*; +import java.util.stream.Collectors; + +public class Cars { + + private static final String DELIMITER = ","; + private static final String DUPLICATED_DELIMITER_REGEX = ",+"; + private final List cars; + + private Cars(List cars) { + this.cars = Collections.unmodifiableList(cars); + } + + public static Cars createCarNameByWord(String input) { + List cars = new ArrayList<>(); + String[] words = divideWord(input); + validate(words); + + for (String carName : words) { + cars.add(new Car(carName)); + } + return new Cars(cars); + } + + private static void validate(String[] words) { + validateDuplicatedWord(words); + } + + private static void validateDuplicatedWord(String[] words) { + Set uniqueWord = new HashSet<>(); + for (String word : words) { + if (!uniqueWord.add(word)) { + throw new CarsDuplicatedNameException(); + } + } + } + + private static String[] divideWord(String word) { + return word.replaceAll(DUPLICATED_DELIMITER_REGEX, DELIMITER).split(DELIMITER); + } + + public void move(CarMoveNumberGenerator carMoveNumberGenerator) { + for (Car car : cars) { + car.move(carMoveNumberGenerator); + } + } + + public Winner findWinner() { + int maxScore = findMaxScore(); + return new Winner(cars.stream() + .filter(car -> (car.getPosition() == maxScore)) + .map(Car::getName) + .collect(Collectors.toList())); + } + + private int findMaxScore() { + return cars.stream() + .max(Comparator.comparingInt(Car::getPosition)) + .map(Car::getPosition) + .orElseThrow(CarsMaxScoreBlankException::new); + } + + public List getCars() { + return cars; + } +} diff --git a/src/main/java/racingcar/domain/RacingCarGame.java b/src/main/java/racingcar/domain/RacingCarGame.java new file mode 100644 index 000000000..978811609 --- /dev/null +++ b/src/main/java/racingcar/domain/RacingCarGame.java @@ -0,0 +1,22 @@ +package racingcar.domain; + +public class RacingCarGame { + + private final Cars cars; + + public RacingCarGame(Cars cars) { + this.cars = cars; + } + + public void move() { + cars.move(new CarRandomMoveNumberGenerator()); + } + + public Winner findWinner() { + return cars.findWinner(); + } + + public Cars getCars() { + return cars; + } +} diff --git a/src/main/java/racingcar/domain/TryCommand.java b/src/main/java/racingcar/domain/TryCommand.java new file mode 100644 index 000000000..d70c4ec21 --- /dev/null +++ b/src/main/java/racingcar/domain/TryCommand.java @@ -0,0 +1,47 @@ +package racingcar.domain; + +import racingcar.exception.TryCommandNumberException; +import racingcar.exception.TryCommandRangeException; + +public class TryCommand { + + private static final int MIN_TRY = 1; + private static final int MAX_TRY = 100000; + private int tryCount; + + private TryCommand(int tryCount) { + this.tryCount = tryCount; + } + + public static TryCommand createTryCommandByString(String input) { + int number = convertInt(input); + validate(number); + return new TryCommand(number); + } + + private static void validate(int number) { + validateRange(number); + } + + private static void validateRange(int number) { + if(number < MIN_TRY || number > MAX_TRY) { + throw new TryCommandRangeException(MIN_TRY, MAX_TRY); + } + } + + private static int convertInt(String input) { + try{ + return Integer.parseInt(input); + }catch (NumberFormatException exception) { + throw new TryCommandNumberException(); + } + } + + public boolean tryMove() { + if(tryCount > 0) { + tryCount--; + return true; + } + return false; + } +} diff --git a/src/main/java/racingcar/domain/Winner.java b/src/main/java/racingcar/domain/Winner.java new file mode 100644 index 000000000..f3924e04f --- /dev/null +++ b/src/main/java/racingcar/domain/Winner.java @@ -0,0 +1,16 @@ +package racingcar.domain; + +import java.util.List; + +public class Winner { + + private final List winner; + + public Winner(List winner) { + this.winner = winner; + } + + public List getWinner() { + return winner; + } +} diff --git a/src/main/java/racingcar/exception/CarNameLengthException.java b/src/main/java/racingcar/exception/CarNameLengthException.java new file mode 100644 index 000000000..ac0e8b44a --- /dev/null +++ b/src/main/java/racingcar/exception/CarNameLengthException.java @@ -0,0 +1,10 @@ +package racingcar.exception; + +public class CarNameLengthException extends IllegalArgumentException{ + + private static final String EXCEPTION_MESSAGE_CAR_NAME_LENGTH = "[ERROR] 자동차이름은 5글자 이하입니다"; + + public CarNameLengthException() { + super(EXCEPTION_MESSAGE_CAR_NAME_LENGTH); + } +} diff --git a/src/main/java/racingcar/exception/CarsDuplicatedNameException.java b/src/main/java/racingcar/exception/CarsDuplicatedNameException.java new file mode 100644 index 000000000..9c01eb08c --- /dev/null +++ b/src/main/java/racingcar/exception/CarsDuplicatedNameException.java @@ -0,0 +1,10 @@ +package racingcar.exception; + +public class CarsDuplicatedNameException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_CARS_DUPLICATED_NAME = "[ERROR] 자동차 이름은 중복될 수 없습니다"; + + public CarsDuplicatedNameException() { + super(EXCEPTION_MESSAGE_CARS_DUPLICATED_NAME); + } +} \ No newline at end of file diff --git a/src/main/java/racingcar/exception/CarsMaxScoreBlankException.java b/src/main/java/racingcar/exception/CarsMaxScoreBlankException.java new file mode 100644 index 000000000..b98ae8a03 --- /dev/null +++ b/src/main/java/racingcar/exception/CarsMaxScoreBlankException.java @@ -0,0 +1,10 @@ +package racingcar.exception; + +public class CarsMaxScoreBlankException extends IllegalArgumentException{ + + private static final String EXCEPTION_MESSAGE_CARS_MAX_SCORE_BLANK = "[ERROR] 우승자를 찾을 수 없습니다."; + + public CarsMaxScoreBlankException() { + super(EXCEPTION_MESSAGE_CARS_MAX_SCORE_BLANK); + } +} diff --git a/src/main/java/racingcar/exception/TryCommandNumberException.java b/src/main/java/racingcar/exception/TryCommandNumberException.java new file mode 100644 index 000000000..02e755052 --- /dev/null +++ b/src/main/java/racingcar/exception/TryCommandNumberException.java @@ -0,0 +1,10 @@ +package racingcar.exception; + +public class TryCommandNumberException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_TRY_COMMAND_NUMBER = "[ERROR] 시도 횟수는 숫자를 입력해야 합니다."; + + public TryCommandNumberException() { + super(EXCEPTION_MESSAGE_TRY_COMMAND_NUMBER); + } +} diff --git a/src/main/java/racingcar/exception/TryCommandRangeException.java b/src/main/java/racingcar/exception/TryCommandRangeException.java new file mode 100644 index 000000000..3b032b86c --- /dev/null +++ b/src/main/java/racingcar/exception/TryCommandRangeException.java @@ -0,0 +1,10 @@ +package racingcar.exception; + +public class TryCommandRangeException extends IllegalArgumentException { + + private static final String EXCEPTION_MESSAGE_TRY_COMMAND_RANGE = "[ERROR] 시도횟수는 최소 %d, 최대 %d 입니다."; + + public TryCommandRangeException(int minTry, int maxTry) { + super(String.format(EXCEPTION_MESSAGE_TRY_COMMAND_RANGE, minTry, maxTry)); + } +} diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java new file mode 100644 index 000000000..36807ae32 --- /dev/null +++ b/src/main/java/racingcar/view/InputView.java @@ -0,0 +1,17 @@ +package racingcar.view; + +import racingcar.domain.Cars; +import racingcar.domain.TryCommand; + +import static camp.nextstep.edu.missionutils.Console.readLine; + +public class InputView { + + public Cars readCarName() { + return Cars.createCarNameByWord(readLine()); + } + + public TryCommand readTryCommand() { + return TryCommand.createTryCommandByString(readLine()); + } +} diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java new file mode 100644 index 000000000..3c086ba8c --- /dev/null +++ b/src/main/java/racingcar/view/OutputView.java @@ -0,0 +1,54 @@ +package racingcar.view; + +import racingcar.domain.Car; +import racingcar.domain.Cars; +import racingcar.domain.Winner; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class OutputView { + + private static final String MESSAGE_INPUT_CAR_NAME = "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"; + private static final String MESSAGE_INPUT_TRY = "시도할 회수는 몇회인가요?"; + private static final String MESSAGE_RESULT = "실행 결과"; + private static final String MOVE_MARK = "-"; + private static final String JOIN_NAME_AND_POSITION = " : "; + private static final String WINNER_DELIMITER = ","; + private static final String MESSAGE_WINNER_PREFIX = "최종 우승자 : "; + private static final String MESSAGE_WINNER_SUFFIX = ""; + + public void printInputCarName() { + System.out.println(MESSAGE_INPUT_CAR_NAME); + } + + public void printExceptionMessage(IllegalArgumentException exceptionMessage) { + System.out.println(exceptionMessage.getMessage()); + } + + public void printInputTry() { + System.out.println(MESSAGE_INPUT_TRY); + } + + public void printBlank() { + System.out.println(); + } + + public void printResult(Cars cars) { + System.out.println(MESSAGE_RESULT); + for(Car car : cars.getCars()){ + System.out.println(car.getName() + JOIN_NAME_AND_POSITION + convertMoveMark(car.getPosition())); + } + printBlank(); + } + + private String convertMoveMark(int position) { + return Stream.generate(() -> MOVE_MARK).limit(position).collect(Collectors.joining()); + } + + public void printWinner(Winner winner) { + String message = winner.getWinner().stream() + .collect(Collectors.joining(WINNER_DELIMITER, MESSAGE_WINNER_PREFIX, MESSAGE_WINNER_SUFFIX)); + System.out.println(message); + } +} diff --git a/src/test/java/racingcar/CarTest.java b/src/test/java/racingcar/CarTest.java new file mode 100644 index 000000000..e8afd2ae1 --- /dev/null +++ b/src/test/java/racingcar/CarTest.java @@ -0,0 +1,85 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import racingcar.domain.Car; +import racingcar.domain.CarMoveNumberGenerator; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.util.Lists.newArrayList; + +public class CarTest { + + private static final String EXCEPTION_MESSAGE_CAR_NAME_LENGTH = "[ERROR] 자동차이름은 5글자 이하입니다"; + + @DisplayName("Car 객체를 성공적으로 생성한다.") + @ParameterizedTest + @ValueSource(strings = {"pobii", "p", "pob", "3%$^1", "세글자", "k l"}) + void createCarSuccess(String input) { + boolean result = true; + try{ + new Car(input); + }catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("5글자 초과시 Car 생성시 예외를 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"pobiid", "dafasdfasdfasdshgsdfg"}) + void createCarByOverLength(String input) { + assertThatThrownBy(() -> new Car(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_CAR_NAME_LENGTH); + } + + @DisplayName("자동차가 4 이상의 숫자가 들어올시 움직인다.") + @Test + void moveCarSuccess() { + Car car = new Car("pobi"); + CarMoveNumberGenerator carMoveNumberGenerator + = new TestNumberGenerator(newArrayList(4, 5, 6, 7, 8, 9)); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + + assertThat(car).extracting("position").isEqualTo(6); + } + + @DisplayName("자동차가 4 이하의 숫자가 들어올시 움직이지 않는다.") + @Test + void moveCarFail() { + Car car = new Car("pobi"); + CarMoveNumberGenerator carMoveNumberGenerator + = new TestNumberGenerator(newArrayList(0, 1, 2, 3)); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + car.move(carMoveNumberGenerator); + + assertThat(car).extracting("position").isEqualTo(0); + } + + static class TestNumberGenerator implements CarMoveNumberGenerator { + + private final List numbers; + + TestNumberGenerator(List numbers) { + this.numbers = numbers; + } + + @Override + public int generate() { + return numbers.remove(0); + } + } +} diff --git a/src/test/java/racingcar/CarsTest.java b/src/test/java/racingcar/CarsTest.java new file mode 100644 index 000000000..3c7bc8a0c --- /dev/null +++ b/src/test/java/racingcar/CarsTest.java @@ -0,0 +1,73 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import racingcar.domain.Car; +import racingcar.domain.CarMoveNumberGenerator; +import racingcar.domain.Cars; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.util.Lists.newArrayList; + +public class CarsTest { + + private static final String EXCEPTION_MESSAGE_CARS_DUPLICATED_NAME = "[ERROR] 자동차 이름은 중복될 수 없습니다"; + + @DisplayName("Cars 객체를 성공적으로 생성한다.") + @ParameterizedTest + @ValueSource(strings = {"pobii,pop,p", "p", "pob,pb,bb,dcd,wqwqg,xvd,aw,be", "pb,,pob,,,bo"}) + void createCarsSuccess(String input) { + boolean result = true; + try { + Cars.createCarNameByWord(input); + } catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("Cars 객체 생성시 중복되는 자동차 이름이있다") + @ParameterizedTest + @ValueSource(strings = {"d,gme,d", "wwwww,ef,weah,wwwww,wwwww", "d,d,d,d,d,d,d,d,d,d"}) + void createCarsByDuplicatedName(String input) { + assertThatThrownBy(() -> Cars.createCarNameByWord(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_CARS_DUPLICATED_NAME); + } + + @DisplayName("모든 자동차가 정상적으로 움직인다.") + @Test + void moveCarsSuccess() { + Cars cars = Cars.createCarNameByWord("pobi,randi,rudy"); + CarMoveNumberGenerator carMoveNumberGenerator + = new CarTest.TestNumberGenerator(newArrayList(4, 2, 6, 9, 5, 6, 4, 0, 1)); + cars.move(carMoveNumberGenerator); + cars.move(carMoveNumberGenerator); + cars.move(carMoveNumberGenerator); + + assertThat(cars.getCars().get(0)).extracting("position").isEqualTo(3); + assertThat(cars.getCars().get(1)).extracting("position").isEqualTo(1); + assertThat(cars.getCars().get(2)).extracting("position").isEqualTo(2); + } + + @DisplayName("우승자를 찾아서 반환한다") + @Test + void findWinnerSuccess() { + Cars cars = Cars.createCarNameByWord("pobi,randi,rudy"); + CarMoveNumberGenerator carMoveNumberGenerator + = new CarTest.TestNumberGenerator(newArrayList(4, 2, 6, 9, 5, 6, 4, 0, 7)); + cars.move(carMoveNumberGenerator); + cars.move(carMoveNumberGenerator); + cars.move(carMoveNumberGenerator); + + List result = new ArrayList<>(); + result.add("pobi"); + result.add("rudy"); + assertThat(cars.findWinner().getWinner()).isEqualTo(result); + } +} diff --git a/src/test/java/racingcar/TryCommandTest.java b/src/test/java/racingcar/TryCommandTest.java new file mode 100644 index 000000000..814a247e5 --- /dev/null +++ b/src/test/java/racingcar/TryCommandTest.java @@ -0,0 +1,47 @@ +package racingcar; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import racingcar.domain.Car; +import racingcar.domain.TryCommand; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class TryCommandTest { + + private static final String EXCEPTION_MESSAGE_TRY_COMMAND_NUMBER = "[ERROR] 시도 횟수는 숫자를 입력해야 합니다."; + private static final String EXCEPTION_MESSAGE_TRY_COMMAND_RANGE = "[ERROR] 시도횟수는 최소 1, 최대 100000 입니다."; + + @DisplayName("TryCommand 객체를 성공적으로 생성한다.") + @ParameterizedTest + @ValueSource(strings = {"1", "3", "100000"}) + void createTryCommandSuccess(String input) { + boolean result = true; + try{ + TryCommand.createTryCommandByString(input); + }catch (IllegalArgumentException exception) { + result = false; + } + assertThat(result).isEqualTo(true); + } + + @DisplayName("숫자가 아닌 입력시 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"pobi", "d"}) + void createTryCommandByNotNumber(String input) { + assertThatThrownBy(() -> TryCommand.createTryCommandByString(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_TRY_COMMAND_NUMBER); + } + + @DisplayName("값의 범위를 넘어갈시 예외가 발생한다") + @ParameterizedTest + @ValueSource(strings = {"-1", "0", "100001"}) + void createTryCommandByOverRange(String input) { + assertThatThrownBy(() -> TryCommand.createTryCommandByString(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(EXCEPTION_MESSAGE_TRY_COMMAND_RANGE); + } +}