diff --git a/README.md b/README.md index f498458691d..2570bc2cae6 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,26 @@ - [x] 입력 횟수가 숫자가 아닌 경우 예외를 발생시킨다. - [x] 자동차 댓수가 숫자가 아닌 경우 예외를 발생시킨다. - [x] 음수를 입력한 경우 예외를 발생시킨다. + +## 🚀 4단계 - 자동차 경주(우승자) +- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다. +- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 쉼표(,)를 기준으로 구분한다. +- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다. + +### 입력 값 검증 +- [x] 이름은 1자 이상 5자 이하이다. + - [x] 이름이 비어있거나 공백일 경우 예외를 발생시킨다. + - [x] 이름이 6자 이상일 경우 예외를 발생시킨다. + +### 자동차 객체 +- [x] 자동차의 이름을 부여한다. +- [x] 자동차 이름은 쉼표를 기준으로 구분한다. +- [x] 자동차 이름이 1자이상 5자이하인지 검증한다. + +### 비즈니스 로직 +- [x] 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- [x] 자동차 경주가 끝난 후 쉼표로 구분하여 우승자를 출력한다. + +### 결과 출력 +- [x] "a, b가 최종 우승했습니다."로 출력한다. diff --git a/src/main/java/Main.java b/src/main/java/Main.java deleted file mode 100644 index 8a2ffc22a77..00000000000 --- a/src/main/java/Main.java +++ /dev/null @@ -1,20 +0,0 @@ -import racingcar.model.RacingGame; -import racingcar.util.InputValidator; -import racingcar.view.InputView; - -import static racingcar.message.Message.*; - -public class Main { - public static void main(String[] args) { - InputView inputView = new InputView(); - - inputView.printMessage(CAR_COUNT_MESSAGE); - int carCount = InputValidator.validatePositiveNumber(inputView.readInput()); - - inputView.printMessage(ATTEMPT_COUNT_MESSAGE); - int attemptCount = InputValidator.validatePositiveNumber(inputView.readInput()); - - RacingGame racingGame = new RacingGame(carCount); - racingGame.race(attemptCount); - } -} diff --git a/src/main/java/racingcar/Main.java b/src/main/java/racingcar/Main.java new file mode 100644 index 00000000000..4c74570fa23 --- /dev/null +++ b/src/main/java/racingcar/Main.java @@ -0,0 +1,47 @@ +package racingcar; + +import racingcar.model.Car; +import racingcar.model.RacingGame; +import racingcar.util.InputValidator; +import racingcar.view.InputView; +import racingcar.view.OutputView; + +import java.util.List; + +import static racingcar.message.ErrorMessage.INVALID_NAME; +import static racingcar.message.Message.*; + +public class Main { + public static void main(String[] args) { + + final InputView inputView = new InputView(); + + final List names = getValidCarNames(inputView); + final int attemptCount = getValidAttemptCount(inputView); + + final RacingGame racingGame = RacingGame.createRacingGame(names); + + final RacingGame finalResult = racingGame.race(attemptCount); + + final List winners = finalResult.getWinners(); + OutputView.printWinners(winners); + } + + private static List getValidCarNames(InputView inputView) { + while (true) { + try { + inputView.printMessage(CAR_NAME_MESSAGE); + return InputValidator.validateNames(inputView.readInput()); + + } catch (IllegalArgumentException e) { + OutputView.print(INVALID_NAME); + } + } + } + + private static int getValidAttemptCount(InputView inputView) { + inputView.printMessage(ATTEMPT_COUNT_MESSAGE); + + return InputValidator.validatePositiveNumber(inputView.readInput()); + } +} diff --git a/src/main/java/racingcar/message/ErrorMessage.java b/src/main/java/racingcar/message/ErrorMessage.java index c593bfd2607..e1ec83b8547 100644 --- a/src/main/java/racingcar/message/ErrorMessage.java +++ b/src/main/java/racingcar/message/ErrorMessage.java @@ -1,8 +1,11 @@ package racingcar.message; public class ErrorMessage { + public static final String INVALID_NUMBER = "숫자를 입력해야 합니다."; public static final String POSITIVE_NUMBER = "양수를 입력해야 합니다."; + public static final String INVALID_NAME = "닉네임은 1자 이상 5자 이하여야 합니다. 다시 입력해주세요."; + public static final String INVALID_CAR_NAME_LENGTH = "자동차 이름은 5자 이하만 가능합니다."; private ErrorMessage() { } diff --git a/src/main/java/racingcar/message/Message.java b/src/main/java/racingcar/message/Message.java index 80495302128..8ab3d0ac445 100644 --- a/src/main/java/racingcar/message/Message.java +++ b/src/main/java/racingcar/message/Message.java @@ -1,9 +1,11 @@ package racingcar.message; public class Message { + public static final String RESULT_MESSAGE = "실행 결과"; - public static final String CAR_COUNT_MESSAGE = "자동차 대수는 몇 대 인가요?"; public static final String ATTEMPT_COUNT_MESSAGE = "시도할 회수는 몇 회 인가요?"; + public static final String CAR_NAME_MESSAGE = "경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분)."; + public static final String WINNING_MESSAGE = "가 최종 우승했습니다."; private Message() { } diff --git a/src/main/java/racingcar/model/Car.java b/src/main/java/racingcar/model/Car.java index ab6eb6cc24b..1f84f321d63 100644 --- a/src/main/java/racingcar/model/Car.java +++ b/src/main/java/racingcar/model/Car.java @@ -1,26 +1,31 @@ package racingcar.model; +import static racingcar.view.OutputView.NAME_POSITION_SEPERATOR; -public class Car { +public final class Car { + private final CarName name; private final Position position; + private static final int MOVE_CONDITION_NUMBER = 4; - public Car() { - this.position = new Position(); + public Car(CarName name) { + this(name, new Position(0)); } - public Car(int initialPosition) { - this.position = new Position(initialPosition); + public Car(CarName name, Position initialPosition) { + this.name = name; + this.position = initialPosition; } - public void move(int randomValue) { + public Car move(int randomValue) { if (canMove(randomValue)) { - position.incrementPosition(); + return new Car(this.name, this.position.incrementPosition()); } + return this; } - private static boolean canMove(int randomValue) { + private boolean canMove(int randomValue) { return randomValue >= MOVE_CONDITION_NUMBER; } @@ -28,7 +33,16 @@ public boolean isAtPosition(Position other) { return position.isSameAs(other); } - public void printPosition() { - System.out.println(position); + public CarName getName() { + return name; + } + + public int getPosition() { + return position.getPosition(); + } + + @Override + public String toString() { + return name + NAME_POSITION_SEPERATOR + position; } } diff --git a/src/main/java/racingcar/model/CarGenerator.java b/src/main/java/racingcar/model/CarGenerator.java deleted file mode 100644 index 25acd0b8a51..00000000000 --- a/src/main/java/racingcar/model/CarGenerator.java +++ /dev/null @@ -1,14 +0,0 @@ -package racingcar.model; - -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class CarGenerator { - - public static List createCars(int carCount) { - return IntStream.range(0, carCount) - .mapToObj(i -> new Car()) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/racingcar/model/CarName.java b/src/main/java/racingcar/model/CarName.java new file mode 100644 index 00000000000..81b81cb3411 --- /dev/null +++ b/src/main/java/racingcar/model/CarName.java @@ -0,0 +1,48 @@ +package racingcar.model; + +import static racingcar.message.ErrorMessage.INVALID_CAR_NAME_LENGTH; +import static racingcar.message.ErrorMessage.INVALID_NAME; + +public class CarName { + + private final String name; + + private static final int MAXIMUM_NAME_LENGTH = 5; + + public CarName(String value) { + validate(value); + this.name = value; + } + + private void validate(String value) { + if (value == null || value.isBlank()) { + throw new IllegalArgumentException(INVALID_NAME); + } + + if (value.length() > MAXIMUM_NAME_LENGTH) { + throw new IllegalArgumentException(INVALID_CAR_NAME_LENGTH); + } + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CarName)) return false; + CarName carName = (CarName) o; + return name.equals(carName.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/src/main/java/racingcar/model/Position.java b/src/main/java/racingcar/model/Position.java index 595371bd06e..ed2d24b4035 100644 --- a/src/main/java/racingcar/model/Position.java +++ b/src/main/java/racingcar/model/Position.java @@ -1,28 +1,33 @@ package racingcar.model; +import static racingcar.view.OutputView.MOVE; + public class Position { - private int position; - private static final String DELIMITER = "-"; + private final int position; public Position() { - this.position = 0; + this(0); } public Position(int initialPosition) { this.position = initialPosition; } - public void incrementPosition() { - position += 1; + public Position incrementPosition() { + return new Position(this.position + 1); } public boolean isSameAs(Position other) { return this.position == other.position; } + public int getPosition() { + return position; + } + @Override public String toString() { - return DELIMITER.repeat(position); + return MOVE.repeat(position); } } diff --git a/src/main/java/racingcar/model/RacingGame.java b/src/main/java/racingcar/model/RacingGame.java index 8937ed5845b..696a51e0c70 100644 --- a/src/main/java/racingcar/model/RacingGame.java +++ b/src/main/java/racingcar/model/RacingGame.java @@ -5,28 +5,89 @@ import racingcar.view.OutputView; import java.util.List; -import java.util.stream.IntStream; +import java.util.stream.Collectors; public class RacingGame { - List cars; + private final List cars; - public RacingGame(int carCount) { - this.cars = CarGenerator.createCars(carCount); + private RacingGame(List cars) { + this.cars = cars; } - public void race(int attemptCount) { + public static RacingGame createRacingGame(List names) { + List cars = createCars(names); + + return new RacingGame(cars); + } + + public static RacingGame ofCars(List cars) { + return new RacingGame(cars); + } + + private static List createCars(List names) { + return names.stream() + .map(name -> new Car(new CarName(name))) + .collect(Collectors.toList()); + } + + public boolean hasCarCount(int expectedCount) { + return cars.size() == expectedCount; + } + + public boolean areAllCarsAtPosition(Position position) { + return cars.stream().allMatch(car -> car.isAtPosition(position)); + } + + public RacingGame race(int attemptCount) { OutputView.print(Message.RESULT_MESSAGE); - IntStream.range(0, attemptCount) - .forEach(i -> { - moveCars(); - OutputView.print(""); - }); + List updatedCars = getCars(attemptCount); + + return new RacingGame(updatedCars); + } + + private List getCars(int attemptCount) { + List updatedCars = cars; + + updatedCars = executeRace(attemptCount, updatedCars); + return updatedCars; + } + + private List executeRace(int attemptCount, List updatedCars) { + for (int i = 0; i < attemptCount; i++) { + updatedCars = move(updatedCars); + OutputView.print(""); + } + return updatedCars; + } + + private List move(List currentCars) { + List movedCars = moveCars(currentCars); + + movedCars.forEach(System.out::println); + + return movedCars; + } + + private List moveCars(List currentCars) { + return currentCars.stream() + .map(car -> car.move(RandomNumberGenerator.generateNumber())) + .collect(Collectors.toList()); + } + + public List getWinners() { + int maxPosition = findMaxPosition(); + + return cars.stream() + .filter(car -> car.isAtPosition(new Position(maxPosition))) + .collect(Collectors.toList()); } - private void moveCars() { - cars.forEach(car -> car.move(RandomNumberGenerator.generateNumber())); - cars.forEach(Car::printPosition); + private int findMaxPosition() { + return cars.stream() + .mapToInt(Car::getPosition) + .max() + .orElse(0); } } diff --git a/src/main/java/racingcar/util/InputValidator.java b/src/main/java/racingcar/util/InputValidator.java index c12e27e41da..77668ecc0ea 100644 --- a/src/main/java/racingcar/util/InputValidator.java +++ b/src/main/java/racingcar/util/InputValidator.java @@ -2,19 +2,55 @@ import racingcar.view.InputView; +import java.util.List; + +import static racingcar.message.ErrorMessage.INVALID_NAME; import static racingcar.message.ErrorMessage.POSITIVE_NUMBER; +import static racingcar.view.OutputView.SEPERATOR; public class InputValidator { + private static final int MINIMUM_NAME_LENGTH = 1; + private static final int MAXIMUM_NAME_LENGTH = 5; + + private InputValidator() { + } + public static int validatePositiveNumber(String input) { int number = InputView.convertToInt(input); + validatePositive(number); + return number; } private static void validatePositive(int number) { - if (number <= 0) { + if (isLessThanMinimumLength(number)) { throw new IllegalArgumentException(POSITIVE_NUMBER); } } + + private static boolean isLessThanMinimumLength(int number) { + return number < MINIMUM_NAME_LENGTH; + } + + public static List validateNames(String input) { + List names = List.of(input.split(SEPERATOR)); + + return validateName(names); + } + + private static List validateName(List names) { + boolean hasInvalidName = checkInvalidName(names); + + if (hasInvalidName) { + throw new IllegalArgumentException(INVALID_NAME); + } + return List.copyOf(names); + } + + private static boolean checkInvalidName(List names) { + return names.stream() + .anyMatch(name -> name.isBlank() || name.length() > MAXIMUM_NAME_LENGTH); + } } diff --git a/src/main/java/racingcar/view/InputView.java b/src/main/java/racingcar/view/InputView.java index 7aa2a86f2c2..024bad97b06 100644 --- a/src/main/java/racingcar/view/InputView.java +++ b/src/main/java/racingcar/view/InputView.java @@ -5,6 +5,7 @@ import java.util.Scanner; public class InputView { + private final Scanner scanner; public InputView() { diff --git a/src/main/java/racingcar/view/OutputView.java b/src/main/java/racingcar/view/OutputView.java index c7ee3a9b25a..e3b20ec9891 100644 --- a/src/main/java/racingcar/view/OutputView.java +++ b/src/main/java/racingcar/view/OutputView.java @@ -1,7 +1,35 @@ package racingcar.view; +import racingcar.model.Car; + +import java.util.List; +import java.util.stream.Collectors; + +import static racingcar.message.Message.WINNING_MESSAGE; + public class OutputView { + + private OutputView() { + } + + private static final String WINNER_NAME_SEPERATOR = ", "; + public static final String NAME_POSITION_SEPERATOR = ":"; + public static final String MOVE = "-"; + public static final String SEPERATOR = ","; + public static void print(String message) { System.out.println(message); } + + public static void printWinners(List winners) { + String winnerNames = formatWinnersName(winners); + + print(winnerNames + WINNING_MESSAGE); + } + + private static String formatWinnersName(List winners) { + return winners.stream() + .map(car -> car.getName().getName()) + .collect(Collectors.joining(WINNER_NAME_SEPERATOR)); + } } diff --git a/src/main/java/step2/StringAddCalculator.java b/src/main/java/step2/StringAddCalculator.java index 8195854793d..851dd7ee72d 100644 --- a/src/main/java/step2/StringAddCalculator.java +++ b/src/main/java/step2/StringAddCalculator.java @@ -5,6 +5,7 @@ import java.util.regex.Pattern; public class StringAddCalculator { + private static final Pattern CUSTOM_SEPERATOR_PATTERN = Pattern.compile("//(.)\n(.*)"); private static final String DEFAULT_SEPERATOR_PATTERN = ",|:"; private static final int CUSTOM_SEPARATOR_GROUP_INDEX = 1; diff --git a/src/test/java/racingcar/model/CarGeneratorTest.java b/src/test/java/racingcar/model/CarGeneratorTest.java deleted file mode 100644 index f3a69a1e07c..00000000000 --- a/src/test/java/racingcar/model/CarGeneratorTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package racingcar.model; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class CarGeneratorTest { - - @Test - @DisplayName("입력한 숫자만큼 차량 객체를 생성하고, 초기 위치는 0이다.") - void createCars() { - assertThat(CarGenerator.createCars(3)) - .hasSize(3) - .allMatch(car -> car.isAtPosition(new Position(0))); - } -} diff --git a/src/test/java/racingcar/model/CarNameTest.java b/src/test/java/racingcar/model/CarNameTest.java new file mode 100644 index 00000000000..946135f5b09 --- /dev/null +++ b/src/test/java/racingcar/model/CarNameTest.java @@ -0,0 +1,36 @@ +package racingcar.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.params.provider.ValueSource; +import racingcar.message.ErrorMessage; + +class CarNameTest { + + @DisplayName("자동차명은 1자에서 5자 이하이다.") + @ParameterizedTest + @ValueSource(strings = {"a", "ab", "abc", "abcd", "abcde"}) + void valid_car_name(String carName) { + assertThatCode(() -> new Car(new CarName(carName))) + .doesNotThrowAnyException(); + } + + @DisplayName("자동차명이 null이면 exception을 발생시킨다.") + @Test + void car_name_with_blank() { + assertThatThrownBy(() -> new Car(new CarName(""))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.INVALID_NAME); + } + + @DisplayName("자동차명이 5자를 초과하면 exception을 발생시킨다.") + @Test + void car_name_exceed_max_length() { + assertThatThrownBy(() -> new Car(new CarName("abcdef"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(ErrorMessage.INVALID_CAR_NAME_LENGTH); + } +} diff --git a/src/test/java/racingcar/model/CarTest.java b/src/test/java/racingcar/model/CarTest.java index 8d2451b77bf..440382322de 100644 --- a/src/test/java/racingcar/model/CarTest.java +++ b/src/test/java/racingcar/model/CarTest.java @@ -1,6 +1,7 @@ package racingcar.model; 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; @@ -8,45 +9,84 @@ class CarTest { + @Test + @DisplayName("자동차의 이름과 초기 위치를 가지고 생성할 수 있다.") + void car_creation_test() { + Car car = new Car(new CarName("test"), new Position(5)); + + assertThat(car.getName().getName()).isEqualTo("test"); + assertThat(car.isAtPosition(new Position(5))).isTrue(); + } + + @Test + @DisplayName("자동차 기본 생성시 초기 위치는 0이다.") + void car_initialPosition_test() { + Car car = new Car(new CarName("test")); + + assertThat(car.isAtPosition(new Position(0))).isTrue(); + } + @ParameterizedTest(name = "초기 위치 {0}으로 생성된 자동차의 위치는 {0}이어야 한다.") @CsvSource({"0", "1", "5"}) @DisplayName("자동차는 주어진 위치로 초기화된다.") void car_initialPosition_test(int initialPosition) { - Car car = new Car(initialPosition); + String carName = "car"; + + Car car = new Car(new CarName(carName), new Position(initialPosition)); + + assertThat(car.getName().getName()).isEqualTo(carName); assertThat(car.isAtPosition(new Position(initialPosition))).isTrue(); } - @DisplayName("자동차가 이동하면 위치가 올바르게 증가한다.") + @DisplayName("랜덤 값이 4이상 이면 이동 한다.") @ParameterizedTest @CsvSource({ "0,4,1", - "3,3,3", + "3,5,4", "5,6,6", - "2,9,3", - "1,0,1" + "2,7,3", + "2,8,3", + "1,9,2" }) - void car_move_test(int initialPosition, int randomValue, int expectedPosition) { - Car car = new Car(initialPosition); + void car_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { + String carName = "car"; + Car initialCar = new Car(new CarName(carName), new Position(initialPosition)); - car.move(randomValue); + Car movedCar = initialCar.move(randomValue); - assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(movedCar.getName().getName()).isEqualTo(carName); + assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(initialCar).isNotEqualTo(movedCar); } - @DisplayName("초기 위치가 5인 자동차가 2번 이동 하면 현재 위치보다 2 증가한다.") + @DisplayName("랜덤 값이 3이하 이면 이동 하지 않는다.") @ParameterizedTest @CsvSource({ - "0,1,1,0", - "3,4,4,5", - "5,4,1,6", - "5,1,5,6" + "0,3,0", + "3,2,3", + "5,1,5", + "2,0,2", }) - void move_initial_move(int initialPosition, int randomValue, int randomValue2, int expectedPosition) { - Car car = new Car(initialPosition); + void car_not_move_logic_test(int initialPosition, int randomValue, int expectedPosition) { + String carName = "car"; + Car initialCar = new Car(new CarName(carName), new Position(initialPosition)); + + Car movedCar = initialCar.move(randomValue); + + assertThat(movedCar.getName().getName()).isEqualTo(carName); + assertThat(movedCar.isAtPosition(new Position(expectedPosition))).isTrue(); + } + + @DisplayName("자동차가 이동해도 기존 객체는 변하지 않는다.(불변 객체 테스트)") + @Test + void car_not_move_immutable_test() { + String carName = "car"; + Car initialCar = new Car(new CarName(carName)); - car.move(randomValue); - car.move(randomValue2); + Car movedCar = initialCar.move(4); - assertThat(car.isAtPosition(new Position(expectedPosition))).isTrue(); + assertThat(initialCar.isAtPosition(new Position(0))).isTrue(); + assertThat(movedCar.isAtPosition(new Position(1))).isTrue(); + assertThat(initialCar).isNotEqualTo(movedCar); } } diff --git a/src/test/java/racingcar/model/PositionTest.java b/src/test/java/racingcar/model/PositionTest.java new file mode 100644 index 00000000000..0e77371edd2 --- /dev/null +++ b/src/test/java/racingcar/model/PositionTest.java @@ -0,0 +1,27 @@ +package racingcar.model; + +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.assertThat; + +class PositionTest { + + @DisplayName("incrementPosition() 호출시 1 증가된 Position이 반환된다.") + @ParameterizedTest + @CsvSource({ + "0, 1", + "1, 2", + "2, 3", + "3, 4", + }) + void incrementPosition(int initialPosition, int expectedPosition) { + Position position = new Position(initialPosition); + + Position movedPosition = position.incrementPosition(); + + assertThat(movedPosition.getPosition()).isEqualTo(expectedPosition); + } +} diff --git a/src/test/java/racingcar/model/RacingGameTest.java b/src/test/java/racingcar/model/RacingGameTest.java index 8dc2a53063e..659d1a4ec34 100644 --- a/src/test/java/racingcar/model/RacingGameTest.java +++ b/src/test/java/racingcar/model/RacingGameTest.java @@ -3,16 +3,48 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; class RacingGameTest { @Test - @DisplayName("입력한 자동차 대수만큼 자동차 객체를 생성한다.") + @DisplayName("입력한 자동차 대수만큼 자동차 객체를 생성하고 초기 위치는 0이다.") void createCarsTest() { - int carCount = 3; - RacingGame racingGame = new RacingGame(carCount); + List carNames = List.of("car1", "car2", "car3"); + + RacingGame racingGame = RacingGame.createRacingGame(carNames); + + assertThat(racingGame.hasCarCount(carNames.size())).isTrue(); + assertThat(racingGame.areAllCarsAtPosition(new Position(0))).isTrue(); + } + + @Test + @DisplayName("우승자를 정확히 추출할 수 있다") + void get_winner_cars() { + + Car win = new Car(new CarName("win"), new Position(3)); + Car lose = new Car(new CarName("lose"), new Position(1)); + + RacingGame game = RacingGame.ofCars(List.of(win, lose)); + + List winners = game.getWinners(); + + assertThat(winners).containsExactly(win); + } + + @Test + @DisplayName("최대 위치를 정확히 찾는다") + void find_max_position_test() { + Car a = new Car(new CarName("a"), new Position(2)); + Car b = new Car(new CarName("b"), new Position(5)); + Car c = new Car(new CarName("c"), new Position(1)); + + RacingGame game = RacingGame.ofCars(List.of(a, b, c)); + + List winners = game.getWinners(); - assertThat(racingGame.cars).hasSize(carCount); + assertThat(winners).containsExactly(b); } } diff --git a/src/test/java/racingcar/view/InputViewTest.java b/src/test/java/racingcar/util/InputValidatorTest.java similarity index 75% rename from src/test/java/racingcar/view/InputViewTest.java rename to src/test/java/racingcar/util/InputValidatorTest.java index a791afc7b21..4348662b08c 100644 --- a/src/test/java/racingcar/view/InputViewTest.java +++ b/src/test/java/racingcar/util/InputValidatorTest.java @@ -1,27 +1,20 @@ -package racingcar.view; +package racingcar.util; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import racingcar.message.ErrorMessage; +import racingcar.view.InputView; import static org.assertj.core.api.Assertions.*; -class InputViewTest { - - private InputView inputView; - - @BeforeEach - void setUp() { - inputView = new InputView(); // 중복 제거 - } +class InputValidatorTest { @DisplayName("숫자 문자열을 입력했을 때 숫자로 변환한다.") @ParameterizedTest @ValueSource(strings = {"123", "42", "9876"}) void convertToInt_문자(String input) { - int result = inputView.convertToInt(input); + int result = InputView.convertToInt(input); assertThat(result).isEqualTo(Integer.parseInt(input)); } @@ -29,7 +22,7 @@ void setUp() { @ParameterizedTest @ValueSource(strings = {" 123 ", " 456 ", "\t789\t"}) void convertToInt_공백_문자(String input) { - int result = inputView.convertToInt(input); + int result = InputView.convertToInt(input); assertThat(result).isEqualTo(Integer.parseInt(input.trim())); } @@ -37,7 +30,7 @@ void setUp() { @ParameterizedTest @ValueSource(strings = {"abc", "123abc", "!@#$", " "}) void convertToInt_예외(String input) { - assertThatThrownBy(() -> inputView.convertToInt(input)) + assertThatThrownBy(() -> InputView.convertToInt(input)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining(ErrorMessage.INVALID_NUMBER + input); }