diff --git a/README.md b/README.md index 8fe711203..d71603320 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,38 @@ -## [NEXTSTEP 플레이그라운드의 미션 진행 과정](https://github.com/next-step/nextstep-docs/blob/master/playground/README.md) +# 자동차 경주 게임 ---- -## 학습 효과를 높이기 위해 추천하는 미션 진행 방법 +## 규칙 --- -1. 피드백 강의 전까지 미션 진행 -> 피드백 강의 전까지 혼자 힘으로 미션 진행. 미션을 진행하면서 하나의 작업이 끝날 때 마다 add, commit -> 예를 들어 다음 숫자 야구 게임의 경우 0, 1, 2단계까지 구현을 완료한 후 push +- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용 +- else 예약어를 쓰지 않는다 +- 3항 연산자를 쓰지 않는다. +- 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. +- **모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다.** +- **모든 원시 값과 문자열을 포장한다.** +- **일급 컬렉션을 쓴다.** +- **Getter를 쓰지 않는다.** -![mission baseball](https://raw.githubusercontent.com/next-step/nextstep-docs/master/playground/images/mission_baseball.png) +## 기능 요구사항 --- -2. 피드백 앞 단계까지 미션 구현을 완료한 후 피드백 강의를 학습한다. +- 각 자동차에 이름을 부여할 수 있다. 자동차 이름은 5자를 초과할 수 없다. +- 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다. +- 자동차 이름은 쉼표(,)를 기준으로 구분한다. +- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4이상일 경우이다. +- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한명 이상일 수 있다. ---- -3. Git 브랜치를 master 또는 main으로 변경한 후 피드백을 반영하기 위한 새로운 브랜치를 생성한 후 처음부터 다시 미션 구현을 도전한다. -``` -git branch -a // 모든 로컬 브랜치 확인 -git checkout master // 기본 브랜치가 master인 경우 -git checkout main // 기본 브랜치가 main인 경우 +## 구현 사항 -git checkout -b 브랜치이름 -ex) git checkout -b apply-feedback -``` +--- +- [ ] 자동차 이름들을 입력한다. + - [x] "자동차 이름"은 5자를 초과 할 수 없다. +- [ ] "시도 할 횟수"를 입력한다. + - [x] 시도 횟수는 음수 일 수 없다. +- [x] 경기를 시작한다. +- [x] "시도 횟수" 만큼 자동차들을 움직인다. + - [x] 모든 자동차를 움직인다. + - [x] 자동차를 움직인다. + - [x] 0 이상 9 이하의 랜덤 값을 받는다. + - [x] 4 이상일 경우 한 칸 전진한다. +- [ ] 우승자를 출력한다. diff --git a/src/main/java/AbstractRandomNumber.java b/src/main/java/AbstractRandomNumber.java new file mode 100644 index 000000000..d173aa6a2 --- /dev/null +++ b/src/main/java/AbstractRandomNumber.java @@ -0,0 +1,17 @@ +public abstract class AbstractRandomNumber { + + private final int number; + + public AbstractRandomNumber(int number) { + this.number = number; + } + + public boolean isMoreThan(int comparisonNumber) { + return comparisonNumber <= number; + } + + public boolean isLessThan(int comparisonNumber) { + return comparisonNumber >= number; + } + +} diff --git a/src/main/java/AbstractRandomNumberFactory.java b/src/main/java/AbstractRandomNumberFactory.java new file mode 100644 index 000000000..5837a2a73 --- /dev/null +++ b/src/main/java/AbstractRandomNumberFactory.java @@ -0,0 +1,5 @@ +public abstract class AbstractRandomNumberFactory { + + abstract AbstractRandomNumber produce(); + +} diff --git a/src/main/java/Car.java b/src/main/java/Car.java new file mode 100644 index 000000000..f7422f7a2 --- /dev/null +++ b/src/main/java/Car.java @@ -0,0 +1,48 @@ +import java.util.Objects; + +public class Car { + + private final Name name; + private Position position; + private final MoveStrategy strategy; + + public Car(String name, int position, MoveStrategy strategy) { + this(name, strategy); + this.position = new Position(position); + } + + public Car(String name, MoveStrategy strategy) { + validateMoveStrategy(strategy); + this.name = new Name(name); + this.position = new Position(); + this.strategy = strategy; + } + + private void validateMoveStrategy(MoveStrategy strategy) { + if (Objects.isNull(strategy)) { + throw new IllegalArgumentException("MoveStrategy must be not null"); + } + } + + public void move() { + this.position = strategy.move(this.position); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Car car = (Car) o; + return Objects.equals(name, car.name) && Objects.equals(position, car.position); + } + + @Override + public int hashCode() { + return Objects.hash(name, position); + } + +} diff --git a/src/main/java/Cars.java b/src/main/java/Cars.java new file mode 100644 index 000000000..88755bdd0 --- /dev/null +++ b/src/main/java/Cars.java @@ -0,0 +1,44 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class Cars { + + private final List cars = new ArrayList<>(); + + public Cars(List cars) { + validate(cars); + this.cars.addAll(cars); + } + + private void validate(List cars) { + if (Objects.isNull(cars)) { + throw new IllegalArgumentException("cars는 Null일 수 없습니다."); + } + if (cars.isEmpty()) { + throw new IllegalArgumentException("cars는 Enpty 일 수 없습니다."); + } + } + + public void move() { + cars.forEach(Car::move); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Cars cars1 = (Cars) o; + return Objects.equals(cars, cars1.cars); + } + + @Override + public int hashCode() { + return Objects.hash(cars); + } + +} diff --git a/src/main/java/MoveByRandomNumberStrategy.java b/src/main/java/MoveByRandomNumberStrategy.java new file mode 100644 index 000000000..e0fb74fa4 --- /dev/null +++ b/src/main/java/MoveByRandomNumberStrategy.java @@ -0,0 +1,19 @@ +public class MoveByRandomNumberStrategy implements MoveStrategy{ + + public static final int MOVABLE_CAR_MIN_NUMBER = 4; + private final AbstractRandomNumberFactory factory; + + public MoveByRandomNumberStrategy(AbstractRandomNumberFactory factory) { + this.factory = factory; + } + + @Override + public Position move(Position position) { + AbstractRandomNumber randomNumber = factory.produce(); + if (randomNumber.isMoreThan(MOVABLE_CAR_MIN_NUMBER)) { + return position.moveOneStep(); + } + return position; + } + +} diff --git a/src/main/java/MoveStrategy.java b/src/main/java/MoveStrategy.java new file mode 100644 index 000000000..0fd427180 --- /dev/null +++ b/src/main/java/MoveStrategy.java @@ -0,0 +1,3 @@ +public interface MoveStrategy { + Position move(Position position); +} diff --git a/src/main/java/Name.java b/src/main/java/Name.java new file mode 100644 index 000000000..65242b67c --- /dev/null +++ b/src/main/java/Name.java @@ -0,0 +1,38 @@ +import java.util.Objects; + +public class Name { + + public static final int MAX_NAME_LENGTH = 5; + private static final String NAME_LENGTH_OVER_MESSAGE = "자동차 이름은 5자를 초과할 수 없다."; + + private final String name; + + public Name(String name) { + validate(name); + this.name = name; + } + + private void validate(String name) { + if (Objects.isNull(name) || name.length() > MAX_NAME_LENGTH) { + throw new IllegalArgumentException(NAME_LENGTH_OVER_MESSAGE); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Name name1 = (Name) o; + return Objects.equals(name, name1.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + +} diff --git a/src/main/java/Position.java b/src/main/java/Position.java new file mode 100644 index 000000000..d0bf7af52 --- /dev/null +++ b/src/main/java/Position.java @@ -0,0 +1,45 @@ +import java.util.Objects; + +public class Position { + + private static final int DEFAULT_STEP_COUNT = 0; + + private final int step; + + public Position() { + this.step = DEFAULT_STEP_COUNT; + } + + public Position(int step) { + validate(step); + this.step = step; + } + + private void validate(int step) { + if (step < DEFAULT_STEP_COUNT) { + throw new IllegalArgumentException("step에 음수를 입력할 수 없습니다."); + } + } + + public Position moveOneStep() { + return new Position(step + 1); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Position position1 = (Position) o; + return step == position1.step; + } + + @Override + public int hashCode() { + return Objects.hash(DEFAULT_STEP_COUNT, step); + } + +} diff --git a/src/main/java/Race.java b/src/main/java/Race.java new file mode 100644 index 000000000..88026aa19 --- /dev/null +++ b/src/main/java/Race.java @@ -0,0 +1,19 @@ +public class Race { + + private TryCount tryCount; + + private final Cars cars; + + public Race(int tryCount, Cars cars) { + this.tryCount = new TryCount(tryCount); + this.cars = cars; + } + + public void start() { + while (!this.tryCount.isComplete()) { + cars.move(); + this.tryCount = tryCount.getNextTryCount(); + } + } + +} diff --git a/src/main/java/RangeableRandomNumber.java b/src/main/java/RangeableRandomNumber.java new file mode 100644 index 000000000..631f6d22c --- /dev/null +++ b/src/main/java/RangeableRandomNumber.java @@ -0,0 +1,30 @@ +public class RangeableRandomNumber extends AbstractRandomNumber { + + private static final int DEFAULT_MAX_RANDOM_NUMBER = RangeableRandomNumberFactory.DEFAULT_MAX_RANDOM_NUMBER; + private static final int DEFAULT_MIN_RANDOM_NUMBER = RangeableRandomNumberFactory.DEFAULT_MIN_RANDOM_NUMBER; + + private final int max; + + private final int min; + + public RangeableRandomNumber(int number, int max, int min) { + super(number); + validateNumber(number); + this.max = max; + this.min = min; + } + + public RangeableRandomNumber(int number) { + super(number); + this.max = DEFAULT_MAX_RANDOM_NUMBER; + this.min = DEFAULT_MIN_RANDOM_NUMBER; + validateNumber(number); + } + + private void validateNumber(int number) { + if (number < min || number > max) { + throw new IllegalArgumentException("RangeableRandomNumber는 " + min + " 보다 크고 " + max + "보다 작아야 합니다."); + } + } + +} diff --git a/src/main/java/RangeableRandomNumberFactory.java b/src/main/java/RangeableRandomNumberFactory.java new file mode 100644 index 000000000..451414f12 --- /dev/null +++ b/src/main/java/RangeableRandomNumberFactory.java @@ -0,0 +1,29 @@ +import java.util.Random; + +public class RangeableRandomNumberFactory extends AbstractRandomNumberFactory { + + public static final int DEFAULT_MAX_RANDOM_NUMBER = 9; + public static final int DEFAULT_MIN_RANDOM_NUMBER = 0; + + private final Random random; + private final int max; + private final int min; + + public RangeableRandomNumberFactory(int max, int min) { + random = new Random(); + this.max = max; + this.min = min; + } + + public RangeableRandomNumberFactory() { + random = new Random(); + this.max = DEFAULT_MAX_RANDOM_NUMBER; + this.min = DEFAULT_MIN_RANDOM_NUMBER; + } + + @Override + public AbstractRandomNumber produce() { + return new RangeableRandomNumber(random.nextInt(max+min) + min, max, min); + } + +} diff --git a/src/main/java/TryCount.java b/src/main/java/TryCount.java new file mode 100644 index 000000000..476547030 --- /dev/null +++ b/src/main/java/TryCount.java @@ -0,0 +1,61 @@ +import java.util.Objects; + +public class TryCount { + + private static final String TRY_COUNT_INVALID_MESSAGE = "Try 횟수는 1 이상만 입력이 가능합니다."; + public static final int MIN_TRY_COUNT = 0; + public static final int DEFAULT_CURRENT_TRY_COUNT = 0; + + private final int count; + + private final int currentCount; + +// public TryCount(int count, int currentCount) { +// this(count); +// this.currentCount = currentCount; +// } + + public TryCount(int count, int currentCount) { + validate(count); + this.count = count; + this.currentCount = currentCount; + } + + public TryCount(int count) { + validate(count); + this.count = count; + this.currentCount = DEFAULT_CURRENT_TRY_COUNT; + } + + private void validate(int count) { + if (count <= MIN_TRY_COUNT) { + throw new IllegalArgumentException(TRY_COUNT_INVALID_MESSAGE); + } + } + + public TryCount getNextTryCount() { + return new TryCount(this.count, this.currentCount+1); + } + + public boolean isComplete() { + return this.count <= this.currentCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TryCount tryCount = (TryCount) o; + return count == tryCount.count && currentCount == tryCount.currentCount; + } + + @Override + public int hashCode() { + return Objects.hash(count, currentCount); + } + +} diff --git a/src/test/java/CarTest.java b/src/test/java/CarTest.java new file mode 100644 index 000000000..eadbd1979 --- /dev/null +++ b/src/test/java/CarTest.java @@ -0,0 +1,23 @@ +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Car 단위 테스트") +public class CarTest { + + private static final String DEFAULT_CAR_NAME = "name"; + + @Test + void move_메서드는_주어진_전략에_따라_자동차를_움직입니다() { + + Car car = new Car(DEFAULT_CAR_NAME, Position::moveOneStep); + MoveStrategy fakeAbsoluteMoveStrategy = ( Position::moveOneStep ); + + Car movedCar = new Car(DEFAULT_CAR_NAME, 1, fakeAbsoluteMoveStrategy); + car.move(); + + assertThat(car).isEqualTo(movedCar); + } + +} diff --git a/src/test/java/CarsTest.java b/src/test/java/CarsTest.java new file mode 100644 index 000000000..e24caf353 --- /dev/null +++ b/src/test/java/CarsTest.java @@ -0,0 +1,52 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("Cars 단위 테스트") +class CarsTest { + + @ParameterizedTest + @MethodSource("provideInvalidArgumentsForConstructValidation") + void Cars는_Null이나_빈_리스트가_인자로_주어진다면_예외를_덥집니다(List input) { + assertThatThrownBy(() -> new Cars(input)) + .isInstanceOf(IllegalArgumentException.class); + } + + private static Stream provideInvalidArgumentsForConstructValidation() { + return Stream.of( + Arguments.of((Object) null), + Arguments.of(new ArrayList()) + ); + } + + @Test + void move_메서드는_주어진_전략에_따라_Car들을_전진시킵니다() { + List inputCarNames = Arrays.asList("a", "b", "c", "d", "e"); + MoveStrategy fakeAbsoluteMoveStrategy = Position::moveOneStep; + List resultCarList = new ArrayList<>( + inputCarNames.stream() + .map(s -> new Car(s, 1, fakeAbsoluteMoveStrategy)) + .collect(Collectors.toList()) + ); + Cars cars = new Cars( + inputCarNames.stream() + .map(s -> new Car(s, fakeAbsoluteMoveStrategy)) + .collect(Collectors.toList()) + ); + + cars.move(); + + assertThat(cars).isEqualTo(new Cars(resultCarList)); + } + +} diff --git a/src/test/java/FakeRandomNumberFactory.java b/src/test/java/FakeRandomNumberFactory.java new file mode 100644 index 000000000..4903fc311 --- /dev/null +++ b/src/test/java/FakeRandomNumberFactory.java @@ -0,0 +1,14 @@ +public class FakeRandomNumberFactory extends AbstractRandomNumberFactory { + + private int fakeNumber; + + public FakeRandomNumberFactory(int fakeNumber) { + this.fakeNumber = fakeNumber; + } + + @Override + public RangeableRandomNumber produce() { + return new RangeableRandomNumber(this.fakeNumber); + } + +} diff --git a/src/test/java/MoveByRandomNumberStrategyTest.java b/src/test/java/MoveByRandomNumberStrategyTest.java new file mode 100644 index 000000000..d14d94db8 --- /dev/null +++ b/src/test/java/MoveByRandomNumberStrategyTest.java @@ -0,0 +1,36 @@ +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +@DisplayName("MoveByRandomNumberStrategy 단위테스트") +class MoveByRandomNumberStrategyTest { + + @ParameterizedTest + @MethodSource("provideFakeRandomNumberForMoving") + void move는_MOVABLE_CAR_MIN_NUMBER_이상의_수를_입력하면_1칸_움직인_Position을_반환합니다(int fakeNumber, Position expect) { + Position position = new Position(); + MoveStrategy strategy = new MoveByRandomNumberStrategy(new FakeRandomNumberFactory(fakeNumber)); + Position result = strategy.move(position); + + assertThat(result).isEqualTo(expect); + } + + private static Stream provideFakeRandomNumberForMoving() { + int step = 0; + Position position = new Position(step); + Position movedPosition = new Position(step + 1); + + int fakeNumberForStop = MoveByRandomNumberStrategy.MOVABLE_CAR_MIN_NUMBER - 1; + int fakeNumberForMove = MoveByRandomNumberStrategy.MOVABLE_CAR_MIN_NUMBER; + + return Stream.of( + Arguments.of(fakeNumberForStop, position), + Arguments.of(fakeNumberForMove, movedPosition) + ); + } + +} diff --git a/src/test/java/NameTest.java b/src/test/java/NameTest.java new file mode 100644 index 000000000..0f0542f34 --- /dev/null +++ b/src/test/java/NameTest.java @@ -0,0 +1,26 @@ +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.platform.commons.function.Try.success; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Name 단위테스트") +class NameTest { + + private final String VALID_NAME = "12345"; + private final String INVALID_NAME = "123456"; + + private final int MAX_NAME_LENGTH = Name.MAX_NAME_LENGTH; + + @Test + void 이름의_길이는_MAX_NAME_LENGTH_자를_초과_할_수_없다() { + assertThatThrownBy(() -> new Name(INVALID_NAME)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void 길이_MAX_NAME_LENGTH_이하의_문자열을_통해_Name_객체를_생성한다() { + success(new Name(VALID_NAME)); + } + +} diff --git a/src/test/java/PositionTest.java b/src/test/java/PositionTest.java new file mode 100644 index 000000000..765b38ed7 --- /dev/null +++ b/src/test/java/PositionTest.java @@ -0,0 +1,34 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Position 단위 테스트") +class PositionTest { + + private final int INVALID_STEP_NUMBER = -1; + private Position position; + + @BeforeEach + void setUp() { + position = new Position(); + } + + @Test + void Position은_step에_음수가_입력된다면_예외를_던집니다() { + assertThatThrownBy(() -> new Position(INVALID_STEP_NUMBER)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void moveOneStep은_Position의_step을_1_증가_시킨_후_반환합니다() { + Position result = this.position.moveOneStep(); + Position expected = new Position(1); + + assertThat(result).isEqualTo(expected); + } + +} diff --git a/src/test/java/RaceTest.java b/src/test/java/RaceTest.java new file mode 100644 index 000000000..bd888c9c9 --- /dev/null +++ b/src/test/java/RaceTest.java @@ -0,0 +1,46 @@ +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("Race 단위 테스트") +public class RaceTest { + + private final int TRY_COUNT = 5; + + public Cars cars; + public Race race; + + private MoveStrategy fakeAbsoluteMoveStrategy; + private List inputCarNames; + + @BeforeEach + void setUp() { + inputCarNames = Arrays.asList("a", "b", "c", "d", "e"); + fakeAbsoluteMoveStrategy = (MoveStrategy) Position::moveOneStep; + + cars = new Cars( + inputCarNames.stream() + .map(s -> new Car(s, fakeAbsoluteMoveStrategy)) + .collect(Collectors.toList()) + ); + race = new Race(TRY_COUNT, cars); + } + + @Test + void start는_tryCount번_반복해서_자동차들을_Strategy에_따라_전진시킵니다() { + List resultCarList = inputCarNames.stream() + .map(s -> new Car(s, TRY_COUNT, fakeAbsoluteMoveStrategy)) + .collect(Collectors.toList()); + + race.start(); + + assertThat(cars).isEqualTo(new Cars(resultCarList)); + } + +} diff --git a/src/test/java/RangeableRandomNumberTest.java b/src/test/java/RangeableRandomNumberTest.java new file mode 100644 index 000000000..28f0917f3 --- /dev/null +++ b/src/test/java/RangeableRandomNumberTest.java @@ -0,0 +1,57 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertTrue; + +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 org.junit.jupiter.params.provider.ValueSource; + +@DisplayName("RandomNumber 단위테스트") +public class RangeableRandomNumberTest { + + public final int MIN_RANDOM_NUMBER = RangeableRandomNumberFactory.DEFAULT_MIN_RANDOM_NUMBER; + public final int MAX_RANDOM_NUMBER = RangeableRandomNumberFactory.DEFAULT_MAX_RANDOM_NUMBER; + + @ParameterizedTest + @ValueSource(ints = {-1, 10}) + void RandomNumber에_MIN_RANDOM_NUMBER_이하의_수_혹은_MAX_RANDOM_NUMBER_이상의_수가_주어진다면_예외를_던집니다(int number) { + assertThatThrownBy(() -> new RangeableRandomNumber(number, MAX_RANDOM_NUMBER, MAX_RANDOM_NUMBER)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void RandomNumber는_MIN_RANDOM_NUMBER_이상_MAX_RANDOM_NUMBER_이하의_난수로_생성됩니다() { + RangeableRandomNumber testBasicRangeableRangeableRandomNumber01 = new RangeableRandomNumber(1); + RangeableRandomNumber testBasicRangeableRangeableRandomNumber02 = new RangeableRandomNumber(2); + RangeableRandomNumber testBasicRangeableRangeableRandomNumber03 = new RangeableRandomNumber(3); + + assertAll( + () -> assertTrue(testBasicRangeableRangeableRandomNumber01.isMoreThan(MIN_RANDOM_NUMBER)), + () -> assertTrue(testBasicRangeableRangeableRandomNumber01.isLessThan(MAX_RANDOM_NUMBER)), + () -> assertTrue(testBasicRangeableRangeableRandomNumber02.isMoreThan(MIN_RANDOM_NUMBER)), + () -> assertTrue(testBasicRangeableRangeableRandomNumber02.isLessThan(MAX_RANDOM_NUMBER)), + () -> assertTrue(testBasicRangeableRangeableRandomNumber03.isMoreThan(MIN_RANDOM_NUMBER)), + () -> assertTrue(testBasicRangeableRangeableRandomNumber03.isLessThan(MAX_RANDOM_NUMBER)) + ); + } + + @ParameterizedTest + @CsvSource(value = {"4:true", "5:true", "6:false"}, delimiter = ':') + void isMoreThan는_RandomNumber가_주어진_파라미터_이상인지_검사합니다(int element, boolean expected) { + RangeableRandomNumber basicRangeableRangeableRandomNumberFive = new RangeableRandomNumber(5); + + assertThat(basicRangeableRangeableRandomNumberFive.isMoreThan(element)).isEqualTo(expected); + } + + @ParameterizedTest + @CsvSource(value = {"4:false", "5:true", "6:true"}, delimiter = ':') + void isLessThan는_RandomNumber가_주어진_파라미터_이하인지_검사합니다(int element, boolean expected) { + RangeableRandomNumber basicRangeableRangeableRandomNumberFive = new RangeableRandomNumber(5); + + assertThat(basicRangeableRangeableRandomNumberFive.isLessThan(element)).isEqualTo(expected); + } + +} diff --git a/src/test/java/TryCountTest.java b/src/test/java/TryCountTest.java new file mode 100644 index 000000000..0338c1c10 --- /dev/null +++ b/src/test/java/TryCountTest.java @@ -0,0 +1,41 @@ +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +@DisplayName("TryCount 단위 테스트") +class TryCountTest { + + @Test + void TryCount는_0_이하를_인자로_전달할_경우_예외를_던집니다() { + assertThatThrownBy(() -> new TryCount(TryCount.MIN_TRY_COUNT)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void TryCount는_1_이상을_인자로_전달할_경우_인스턴스를_생성합니다() { + TryCount tryCount = new TryCount(TryCount.MIN_TRY_COUNT + 1); + + assertThat(tryCount).isNotNull(); + } + + @Test + void getNextTryCount_메서드는_전체_TryCount_수에서_한번_사용한_TryCount를_반환합니다() { + int INPUT_TRT_COUNT = 5; + TryCount tryCount = new TryCount(INPUT_TRT_COUNT); + + assertThat(tryCount.getNextTryCount()).isEqualTo(new TryCount(INPUT_TRT_COUNT, TryCount.DEFAULT_CURRENT_TRY_COUNT + 1)); + } + + @Test + void complete_메서드는_TryCount_완료_여부를_반환합니다() { + int INPUT_TRT_COUNT = 1; + TryCount tryCount = new TryCount(INPUT_TRT_COUNT, TryCount.DEFAULT_CURRENT_TRY_COUNT); + assertThat(tryCount.isComplete()).isFalse(); + + TryCount nextTryCount = tryCount.getNextTryCount(); + assertThat(nextTryCount.isComplete()).isTrue(); + } + +}