From c5928a78811a641b34cdbb2871fa9f33645603b2 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:12:28 +0900
Subject: [PATCH 01/13] =?UTF-8?q?DOCS:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?=
=?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=EA=B3=BC=20=ED=94=84=EB=A1=9C?=
=?UTF-8?q?=EA=B7=B8=EB=9E=98=EB=B0=8D=20=EC=9A=94=EA=B5=AC=EC=82=AC?=
=?UTF-8?q?=ED=95=AD=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 76 ++++++++++++++++++++++++++++++++++++++++++
src/main/java/.gitkeep | 0
2 files changed, 76 insertions(+)
create mode 100644 README.md
delete mode 100644 src/main/java/.gitkeep
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..a9823886
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+## 움직이는 자동차 [O]
+### 기능 요구사항
+- 자동차는 이름을 가지고 있다.
+- 자동차는 움직일 수 있다.
+- 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다.
+### 새로운 프로그래밍 요구사항
+- 자동차가 움직이는 기능이 의도대로 동작하는지 테스트한다.
+- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
+- 기본적으로 Java Style Guide을 원칙으로 한다.
+- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
+ - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
+ - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
+- 3항 연산자를 쓰지 않는다.
+- else 예약어를 쓰지 않는다.
+ - else 예약어를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
+ - 힌트: if문에서 값을 반환하는 방식으로 구현하면 else 예약어를 사용하지 않아도 된다.
+- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다.
+ - 함수(또는 메소드)가 한 가지 일만 잘 하도록 구현한다.
+### 기존 프로그래밍 요구사항
+- 메인 메서드는 만들지 않는다.
+
+## 우승 자동차 구하기 [O]
+### 기능 요구사항
+- n대의 자동차가 참여할 수 있다.
+- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
+ - 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다.
+- 자동차 경주 게임을 완료한 후 누가 우승했는지를 구할 수 있다. 우승자는 한 명 이상일 수 있다.
+### 새로운 프로그래밍 요구사항
+- 우승자를 구하는 기능이 의도대로 동작하는지 테스트한다.
+
+## 게임 실행 [O]
+### 기능 요구사항
+- 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
+- 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
+- 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
+- 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
+- 전진하는 조건은 0에서 9 사이에서 random 값을 구한 후 random 값이 4 이상일 경우 전진하고, 3 이하의 값이면 멈춘다.
+- 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
+
**실행 결과**
+- 위 요구사항에 따라 3대의 자동차가 5번 움직였을 경우 프로그램을 실행한 결과는 다음과 같다.
+```
+경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).
+neo,brie,brown
+시도할 회수는 몇회인가요?
+5
+
+실행 결과
+neo : -
+brie : -
+brown : -
+
+neo : --
+brie : -
+brown : --
+
+neo : ---
+brie : --
+brown : ---
+
+neo : ----
+brie : ---
+brown : ----
+
+neo : -----
+brie : ----
+brown : -----
+
+neo : -----
+brie : ----
+brown : -----
+
+neo, brown가 최종 우승했습니다.
+```
+
+### 새로운 프로그래밍 요구사항
+- 메인 메서드를 추가하여 실행 가능한 애플리케이션으로 만든다.
\ No newline at end of file
diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep
deleted file mode 100644
index e69de29b..00000000
From 298065d41658c99cf5d2fe453e581c340a359fe8 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:12:48 +0900
Subject: [PATCH 02/13] =?UTF-8?q?Remove:=20=ED=95=84=EC=9A=94=EC=97=86?=
=?UTF-8?q?=EB=8A=94=20.gitkeep=20=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/test/java/.gitkeep | 0
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 src/test/java/.gitkeep
diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep
deleted file mode 100644
index e69de29b..00000000
From 49ecbf807af2799e03049937bcc1130e57ac8b54 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:13:39 +0900
Subject: [PATCH 03/13] =?UTF-8?q?Feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8=20?=
=?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/RacingCar.java | 49 ++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 src/main/java/RacingCar.java
diff --git a/src/main/java/RacingCar.java b/src/main/java/RacingCar.java
new file mode 100644
index 00000000..fbe76af4
--- /dev/null
+++ b/src/main/java/RacingCar.java
@@ -0,0 +1,49 @@
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class RacingCar {
+ private final String name;
+ private int score = 0;
+ private final List results = new ArrayList<>();
+
+ public RacingCar(String name) {
+ this.name = name;
+ }
+
+ public int move() {
+ Random rand = new Random();
+
+ boolean result = rand.nextInt(10) >= 4;
+
+ if (result)
+ ++score;
+
+ results.add(result);
+
+ return score;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getScore() {
+ return score;
+ }
+
+ public String getResultString(int phase) {
+ StringBuilder resultString = new StringBuilder();
+ for (int i = 0; i < phase && i < results.size(); i++) {
+ resultString.append(resultToString(results.get(i)));
+ }
+ return resultString.toString();
+ }
+
+ private String resultToString(Boolean result) {
+ if (result)
+ return "-";
+
+ return "";
+ }
+}
From 1ca6611d3f160fc0ae53c3c3fb748e22f195f7e0 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:14:10 +0900
Subject: [PATCH 04/13] =?UTF-8?q?Feat:=20=EC=9A=B0=EC=8A=B9=20=EC=9E=90?=
=?UTF-8?q?=EB=8F=99=EC=B0=A8=20=EA=B5=AC=ED=95=98=EB=8A=94=20=EA=B8=B0?=
=?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/RacingCarGame.java | 87 ++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
create mode 100644 src/main/java/RacingCarGame.java
diff --git a/src/main/java/RacingCarGame.java b/src/main/java/RacingCarGame.java
new file mode 100644
index 00000000..e7dd7656
--- /dev/null
+++ b/src/main/java/RacingCarGame.java
@@ -0,0 +1,87 @@
+import java.util.ArrayList;
+import java.util.InputMismatchException;
+import java.util.List;
+import java.util.Scanner;
+
+public class RacingCarGame {
+
+ int highScore;
+ int phase = 0;
+ List racingCars = new ArrayList<>();
+ boolean isGameInit = false;
+
+ public void setGame() {
+ Scanner scanner = new Scanner(System.in);
+
+ System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
+ String input = scanner.nextLine();
+
+ for (String name : input.split(","))
+ racingCars.add(new RacingCar(name));
+
+ if (racingCars.size() < 2)
+ throw new InputMismatchException("최소한 두 명 이상의 플레이어가 필요합니다.");
+
+ System.out.println("시도할 회수는 몇회인가요?");
+ try {
+ phase = scanner.nextInt();
+ if (phase < 0) {
+ throw new NumberFormatException("음수는 유효한 숫자가 아닙니다.");
+ }
+ } catch (InputMismatchException e) {
+ throw new InputMismatchException("유효한 숫자가 아닙니다.");
+ }
+
+
+ isGameInit = true;
+ }
+
+ public void startGame() {
+ if (!isGameInit)
+ throw new IllegalStateException("게임이 초기화되지 않았습니다.");
+
+ for(int i = 0; i < phase; ++i){
+ moveAllRacingCars();
+ }
+
+ printResult();
+ }
+
+ public void resetGame() {
+ racingCars.clear();
+ highScore = 0;
+ }
+
+ private void moveAllRacingCars() {
+ for(RacingCar racingCar : racingCars)
+ racingCar.move();
+ }
+
+ private void printResult() {
+ System.out.println("\n실행 결과");
+
+ for (int i = 1; i <= phase; ++i){
+ printAllRacingCarResults(i);
+ System.out.println();
+ }
+
+ System.out.println(String.join(", ", getWinnerNames()) + "가 최종 우승했습니다.");
+ }
+
+ private void printAllRacingCarResults(int phase) {
+ for (RacingCar racingCar : racingCars) {
+ System.out.println(racingCar.getName() + " : " + racingCar.getResultString(phase));
+ }
+ }
+
+ private List getWinnerNames() {
+ return racingCars.stream().filter(this::checkWinner).map(RacingCar::getName).toList();
+ }
+
+ private boolean checkWinner(RacingCar racingCar) {
+ if (racingCar.getScore() > highScore)
+ highScore = racingCar.getScore();
+
+ return racingCar.getScore() == highScore;
+ }
+}
From f461973c2356c76ba6af4aeb1b35a2ba498d99cd Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:15:26 +0900
Subject: [PATCH 05/13] =?UTF-8?q?Feat:=20=EC=9E=90=EB=8F=99=EC=B0=A8?=
=?UTF-8?q?=EC=99=80=20=EA=B2=8C=EC=9E=84=20=EA=B4=80=EB=A0=A8=20=ED=85=8C?=
=?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/test/java/RacingCarTest.java | 67 ++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 src/test/java/RacingCarTest.java
diff --git a/src/test/java/RacingCarTest.java b/src/test/java/RacingCarTest.java
new file mode 100644
index 00000000..955cd089
--- /dev/null
+++ b/src/test/java/RacingCarTest.java
@@ -0,0 +1,67 @@
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.ByteArrayInputStream;
+import java.util.InputMismatchException;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+public class RacingCarTest {
+
+ @Test
+ @DisplayName("자동차 이동 테스트")
+ void racingCarMove() {
+ RacingCar racingCar = new RacingCar("Test");
+ int expected = racingCar.getScore();
+ int actual = racingCar.move();
+
+ assertThat(actual).isIn(expected, expected + 1);
+ }
+
+ @Test
+ @DisplayName("자동차 결과 텍스트 테스트")
+ void racingCarResultString() {
+ RacingCar racingCar = new RacingCar("Test");
+
+ for (int i = 0; i < 5; ++i)
+ racingCar.move();
+
+
+ String actual = racingCar.getResultString(5);
+ String expected = new String(new char[racingCar.getScore()]).replace("\0", "-");
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Nested
+ @DisplayName("자동차 게임 설정 테스트")
+ class setGame {
+ @Test
+ @DisplayName("자동차 이름 입력이 하나일 경우 테스트")
+ void setGameWithLessThanTwoNameInput() {
+ RacingCarGame racingCarGame = new RacingCarGame();
+ System.setIn(new ByteArrayInputStream("test1\n1".getBytes()));
+
+ assertThatThrownBy(racingCarGame::setGame).isInstanceOf(InputMismatchException.class).hasMessage("최소한 두 명 이상의 플레이어가 필요합니다.");
+ }
+
+ @Test
+ @DisplayName("시도할 횟수 입력이 음수일 경우 테스트")
+ void setGameWithNegativePhaseInput() {
+ RacingCarGame racingCarGame = new RacingCarGame();
+ System.setIn(new ByteArrayInputStream("test1,test2\n-1\n".getBytes()));
+
+ assertThatThrownBy(racingCarGame::setGame).isInstanceOf(NumberFormatException.class).hasMessage("음수는 유효한 숫자가 아닙니다.");
+ }
+
+ @Test
+ @DisplayName("시도할 횟수 입력이 숫자가 아닌 경우 테스트")
+ void setGameWithInvalidPhaseInput() {
+ RacingCarGame racingCarGame = new RacingCarGame();
+ System.setIn(new ByteArrayInputStream("test1,test2\nabc\n".getBytes()));
+
+ assertThatThrownBy(racingCarGame::setGame).isInstanceOf(InputMismatchException.class).hasMessage("유효한 숫자가 아닙니다.");
+ }
+ }
+}
From e6a5ecef0db14533bfb0489b63984e95977f97b8 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Thu, 3 Oct 2024 20:15:49 +0900
Subject: [PATCH 06/13] =?UTF-8?q?Feat:=20=EA=B2=8C=EC=9E=84=20=EC=8B=A4?=
=?UTF-8?q?=ED=96=89=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=A9=94=EC=9D=B8=20?=
=?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/Main.java | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 src/main/java/Main.java
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
new file mode 100644
index 00000000..d5e19f46
--- /dev/null
+++ b/src/main/java/Main.java
@@ -0,0 +1,8 @@
+public class Main {
+ public static void main(String[] args) {
+ RacingCarGame game = new RacingCarGame();
+ game.setGame();
+ game.startGame();
+ game.resetGame();
+ }
+}
From 5e1aff276ab8571322754e1ec11f26b6ba68da60 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Sat, 5 Oct 2024 04:44:19 +0900
Subject: [PATCH 07/13] =?UTF-8?q?Fix:=20=EC=B1=85=EC=9E=84=20=EB=B6=84?=
=?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20randPower=EC=99=80=20?=
=?UTF-8?q?checkPower=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80=20?=
=?UTF-8?q?=ED=9B=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B8=EB=B6=84?=
=?UTF-8?q?=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/RacingCar.java | 22 +++++++++++++---
src/test/java/RacingCarTest.java | 44 +++++++++++++++++++++++++++-----
2 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/src/main/java/RacingCar.java b/src/main/java/RacingCar.java
index fbe76af4..e264cefd 100644
--- a/src/main/java/RacingCar.java
+++ b/src/main/java/RacingCar.java
@@ -11,19 +11,33 @@ public RacingCar(String name) {
this.name = name;
}
- public int move() {
+ private int randPower() {
Random rand = new Random();
+ return rand.nextInt(10);
+ }
- boolean result = rand.nextInt(10) >= 4;
+ public int move() {
+ return move(randPower());
+ }
- if (result)
+ public int move(int power) {
+ boolean isMovable = checkPower(power);
+
+ if (isMovable)
++score;
- results.add(result);
+ results.add(isMovable);
return score;
}
+ private boolean checkPower(int power) {
+ if (power < 0 || power > 9)
+ throw new IllegalArgumentException("0~9 사이의 Power 값을 필요로 합니다.");
+
+ return power >= 4;
+ }
+
public String getName() {
return name;
}
diff --git a/src/test/java/RacingCarTest.java b/src/test/java/RacingCarTest.java
index 955cd089..3327e0ac 100644
--- a/src/test/java/RacingCarTest.java
+++ b/src/test/java/RacingCarTest.java
@@ -9,15 +9,45 @@
public class RacingCarTest {
- @Test
+ @Nested
@DisplayName("자동차 이동 테스트")
- void racingCarMove() {
- RacingCar racingCar = new RacingCar("Test");
- int expected = racingCar.getScore();
- int actual = racingCar.move();
+ class RacingCarMove {
+ @Test
+ @DisplayName("자동차 랜덤 이동 테스트")
+ void randomMove() {
+ RacingCar racingCar = new RacingCar("Test");
+ int expected = racingCar.getScore();
+ int actual = racingCar.move();
+
+ assertThat(actual).isIn(expected, expected + 1);
+ }
+
+ @Test
+ @DisplayName("자동차 이동 조건 테스트")
+ void moveCondition() {
+ RacingCar racingCar = new RacingCar("Test");
+ int expected = 0;
+ int actual = racingCar.move(3);
- assertThat(actual).isIn(expected, expected + 1);
+ assertThat(actual).isEqualTo(expected);
+
+ expected = 1;
+ actual = racingCar.move(5);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ @Test
+ @DisplayName("자동차 이동 조건 예외처리 테스트")
+ void moveConditionException() {
+ RacingCar racingCar = new RacingCar("Test");
+
+ assertThatThrownBy(() -> racingCar.move(-1)).isInstanceOf(IllegalArgumentException.class).hasMessage("0~9 사이의 Power 값을 필요로 합니다.");
+
+ assertThatThrownBy(() -> racingCar.move(10)).isInstanceOf(IllegalArgumentException.class).hasMessage("0~9 사이의 Power 값을 필요로 합니다.");
+ }
}
+
@Test
@DisplayName("자동차 결과 텍스트 테스트")
@@ -36,7 +66,7 @@ void racingCarResultString() {
@Nested
@DisplayName("자동차 게임 설정 테스트")
- class setGame {
+ class SetRacingCarGameTest {
@Test
@DisplayName("자동차 이름 입력이 하나일 경우 테스트")
void setGameWithLessThanTwoNameInput() {
From 74656e577d24164459596e8d579b8fbc22f2cce2 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Fri, 11 Oct 2024 07:58:08 +0900
Subject: [PATCH 08/13] Remove: Remove class unused in mvc model
---
src/main/java/Main.java | 8 -----
src/main/java/RacingCar.java | 63 ------------------------------------
2 files changed, 71 deletions(-)
delete mode 100644 src/main/java/Main.java
delete mode 100644 src/main/java/RacingCar.java
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
deleted file mode 100644
index d5e19f46..00000000
--- a/src/main/java/Main.java
+++ /dev/null
@@ -1,8 +0,0 @@
-public class Main {
- public static void main(String[] args) {
- RacingCarGame game = new RacingCarGame();
- game.setGame();
- game.startGame();
- game.resetGame();
- }
-}
diff --git a/src/main/java/RacingCar.java b/src/main/java/RacingCar.java
deleted file mode 100644
index e264cefd..00000000
--- a/src/main/java/RacingCar.java
+++ /dev/null
@@ -1,63 +0,0 @@
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-public class RacingCar {
- private final String name;
- private int score = 0;
- private final List results = new ArrayList<>();
-
- public RacingCar(String name) {
- this.name = name;
- }
-
- private int randPower() {
- Random rand = new Random();
- return rand.nextInt(10);
- }
-
- public int move() {
- return move(randPower());
- }
-
- public int move(int power) {
- boolean isMovable = checkPower(power);
-
- if (isMovable)
- ++score;
-
- results.add(isMovable);
-
- return score;
- }
-
- private boolean checkPower(int power) {
- if (power < 0 || power > 9)
- throw new IllegalArgumentException("0~9 사이의 Power 값을 필요로 합니다.");
-
- return power >= 4;
- }
-
- public String getName() {
- return name;
- }
-
- public int getScore() {
- return score;
- }
-
- public String getResultString(int phase) {
- StringBuilder resultString = new StringBuilder();
- for (int i = 0; i < phase && i < results.size(); i++) {
- resultString.append(resultToString(results.get(i)));
- }
- return resultString.toString();
- }
-
- private String resultToString(Boolean result) {
- if (result)
- return "-";
-
- return "";
- }
-}
From 664ce8d41ab81b787b5c07d9537e4626bd961a63 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Fri, 11 Oct 2024 07:59:26 +0900
Subject: [PATCH 09/13] Refactor: Refactor design pattern to mvc model
---
src/main/java/RacingCarGame.java | 96 +++----------------
.../java/controller/RacingCarController.java | 39 ++++++++
.../java/converter/RacingCarConverter.java | 27 ++++++
src/main/java/dao/RacingCarDao.java | 20 ++++
src/main/java/domain/RacingCar.java | 15 +++
src/main/java/dto/RacingCarCreateDto.java | 14 +++
src/main/java/dto/RacingCarResultDto.java | 16 ++++
src/main/java/service/RacingCarService.java | 13 +++
.../java/service/RacingCarServiceImpl.java | 36 +++++++
src/main/java/view/RacingCarView.java | 45 +++++++++
10 files changed, 238 insertions(+), 83 deletions(-)
create mode 100644 src/main/java/controller/RacingCarController.java
create mode 100644 src/main/java/converter/RacingCarConverter.java
create mode 100644 src/main/java/dao/RacingCarDao.java
create mode 100644 src/main/java/domain/RacingCar.java
create mode 100644 src/main/java/dto/RacingCarCreateDto.java
create mode 100644 src/main/java/dto/RacingCarResultDto.java
create mode 100644 src/main/java/service/RacingCarService.java
create mode 100644 src/main/java/service/RacingCarServiceImpl.java
create mode 100644 src/main/java/view/RacingCarView.java
diff --git a/src/main/java/RacingCarGame.java b/src/main/java/RacingCarGame.java
index e7dd7656..eb07fee6 100644
--- a/src/main/java/RacingCarGame.java
+++ b/src/main/java/RacingCarGame.java
@@ -1,87 +1,17 @@
-import java.util.ArrayList;
-import java.util.InputMismatchException;
-import java.util.List;
-import java.util.Scanner;
+import controller.RacingCarController;
+import dao.RacingCarDao;
+import service.RacingCarService;
+import service.RacingCarServiceImpl;
+import view.RacingCarView;
public class RacingCarGame {
-
- int highScore;
- int phase = 0;
- List racingCars = new ArrayList<>();
- boolean isGameInit = false;
-
- public void setGame() {
- Scanner scanner = new Scanner(System.in);
-
- System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
- String input = scanner.nextLine();
-
- for (String name : input.split(","))
- racingCars.add(new RacingCar(name));
-
- if (racingCars.size() < 2)
- throw new InputMismatchException("최소한 두 명 이상의 플레이어가 필요합니다.");
-
- System.out.println("시도할 회수는 몇회인가요?");
- try {
- phase = scanner.nextInt();
- if (phase < 0) {
- throw new NumberFormatException("음수는 유효한 숫자가 아닙니다.");
- }
- } catch (InputMismatchException e) {
- throw new InputMismatchException("유효한 숫자가 아닙니다.");
- }
-
-
- isGameInit = true;
- }
-
- public void startGame() {
- if (!isGameInit)
- throw new IllegalStateException("게임이 초기화되지 않았습니다.");
-
- for(int i = 0; i < phase; ++i){
- moveAllRacingCars();
- }
-
- printResult();
- }
-
- public void resetGame() {
- racingCars.clear();
- highScore = 0;
- }
-
- private void moveAllRacingCars() {
- for(RacingCar racingCar : racingCars)
- racingCar.move();
- }
-
- private void printResult() {
- System.out.println("\n실행 결과");
-
- for (int i = 1; i <= phase; ++i){
- printAllRacingCarResults(i);
- System.out.println();
- }
-
- System.out.println(String.join(", ", getWinnerNames()) + "가 최종 우승했습니다.");
- }
-
- private void printAllRacingCarResults(int phase) {
- for (RacingCar racingCar : racingCars) {
- System.out.println(racingCar.getName() + " : " + racingCar.getResultString(phase));
- }
- }
-
- private List getWinnerNames() {
- return racingCars.stream().filter(this::checkWinner).map(RacingCar::getName).toList();
- }
-
- private boolean checkWinner(RacingCar racingCar) {
- if (racingCar.getScore() > highScore)
- highScore = racingCar.getScore();
-
- return racingCar.getScore() == highScore;
+ public static void main(String[] args) {
+ RacingCarView racingCarView = new RacingCarView();
+ RacingCarDao racingCarDao = new RacingCarDao();
+ RacingCarService racingCarService = new RacingCarServiceImpl(racingCarDao);
+ RacingCarController game = new RacingCarController(racingCarView, racingCarService);
+
+ game.set();
+ game.run();
}
}
diff --git a/src/main/java/controller/RacingCarController.java b/src/main/java/controller/RacingCarController.java
new file mode 100644
index 00000000..4b03f50b
--- /dev/null
+++ b/src/main/java/controller/RacingCarController.java
@@ -0,0 +1,39 @@
+package controller;
+
+import converter.RacingCarConverter;
+import lombok.RequiredArgsConstructor;
+import service.RacingCarService;
+import view.RacingCarView;
+
+@RequiredArgsConstructor
+public class RacingCarController {
+
+ final RacingCarView racingCarView;
+ final RacingCarService racingCarService;
+
+ int round;
+ boolean isGameInit = false;
+
+ public void set() {
+ racingCarService.createRacingCar(racingCarView.inputRacingCarName().stream().map(
+ RacingCarConverter::toRacingCarCreateDto).toList());
+ round = racingCarView.inputRound();
+
+ isGameInit = true;
+ }
+
+ public void run() {
+ if (!isGameInit)
+ throw new IllegalStateException("게임이 초기화되지 않았습니다.");
+
+ racingCarView.printResultTitle();
+ for(int currentRound = 0; currentRound < round; ++currentRound){
+ racingCarService.move();
+ racingCarView.printResult(racingCarService.getResults());
+ }
+
+ racingCarView.printWinner(racingCarService.getResults());
+
+ isGameInit = false;
+ }
+}
diff --git a/src/main/java/converter/RacingCarConverter.java b/src/main/java/converter/RacingCarConverter.java
new file mode 100644
index 00000000..8486fbb5
--- /dev/null
+++ b/src/main/java/converter/RacingCarConverter.java
@@ -0,0 +1,27 @@
+package converter;
+
+import domain.RacingCar;
+import dto.RacingCarCreateDto;
+import dto.RacingCarResultDto;
+import java.util.stream.Collectors;
+
+public class RacingCarConverter {
+ public static RacingCarCreateDto toRacingCarCreateDto(String name) {
+ return RacingCarCreateDto.builder().name(name).build();
+ }
+
+ public static RacingCarResultDto toRacingCarResultDto(RacingCar racingCar) {
+ return RacingCarResultDto.builder().
+ name(racingCar.getName())
+ .resultString(racingCar.getResults().stream().map(RacingCarConverter::resultToString).collect(
+ Collectors.joining()))
+ .distance((int) racingCar.getResults().stream().filter(v -> v).count()).build();
+ }
+
+ public static String resultToString(Boolean result) {
+ if (result)
+ return "-";
+
+ return "";
+ }
+}
diff --git a/src/main/java/dao/RacingCarDao.java b/src/main/java/dao/RacingCarDao.java
new file mode 100644
index 00000000..a6075410
--- /dev/null
+++ b/src/main/java/dao/RacingCarDao.java
@@ -0,0 +1,20 @@
+package dao;
+
+import domain.RacingCar;
+import dto.RacingCarCreateDto;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RacingCarDao {
+ private final List racingCars = new ArrayList<>();
+
+ public RacingCar insert(RacingCarCreateDto racingCarCreateDto) {
+ RacingCar racingCar = new RacingCar(racingCarCreateDto.getName());
+ racingCars.add(racingCar);
+ return racingCar;
+ }
+
+ public List select() {
+ return racingCars;
+ }
+}
diff --git a/src/main/java/domain/RacingCar.java b/src/main/java/domain/RacingCar.java
new file mode 100644
index 00000000..813e634f
--- /dev/null
+++ b/src/main/java/domain/RacingCar.java
@@ -0,0 +1,15 @@
+package domain;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@RequiredArgsConstructor
+public class RacingCar {
+ private final String name;
+ private final List results = new ArrayList<>();
+}
diff --git a/src/main/java/dto/RacingCarCreateDto.java b/src/main/java/dto/RacingCarCreateDto.java
new file mode 100644
index 00000000..536c6fcb
--- /dev/null
+++ b/src/main/java/dto/RacingCarCreateDto.java
@@ -0,0 +1,14 @@
+package dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Builder
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class RacingCarCreateDto {
+ private String name;
+}
diff --git a/src/main/java/dto/RacingCarResultDto.java b/src/main/java/dto/RacingCarResultDto.java
new file mode 100644
index 00000000..29d0d9eb
--- /dev/null
+++ b/src/main/java/dto/RacingCarResultDto.java
@@ -0,0 +1,16 @@
+package dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Builder
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+public class RacingCarResultDto {
+ private String name;
+ private String resultString;
+ private int distance;
+}
diff --git a/src/main/java/service/RacingCarService.java b/src/main/java/service/RacingCarService.java
new file mode 100644
index 00000000..31329d38
--- /dev/null
+++ b/src/main/java/service/RacingCarService.java
@@ -0,0 +1,13 @@
+package service;
+
+import dto.RacingCarCreateDto;
+import dto.RacingCarResultDto;
+import java.util.List;
+
+public interface RacingCarService {
+ void createRacingCar(List racingCarCreateDtoList);
+
+ void move();
+
+ List getResults();
+}
diff --git a/src/main/java/service/RacingCarServiceImpl.java b/src/main/java/service/RacingCarServiceImpl.java
new file mode 100644
index 00000000..a9ddd97f
--- /dev/null
+++ b/src/main/java/service/RacingCarServiceImpl.java
@@ -0,0 +1,36 @@
+package service;
+
+import converter.RacingCarConverter;
+import dao.RacingCarDao;
+import domain.RacingCar;
+import dto.RacingCarCreateDto;
+import dto.RacingCarResultDto;
+import java.util.List;
+import java.util.Random;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class RacingCarServiceImpl implements RacingCarService {
+ final RacingCarDao racingCarDao;
+
+ @Override
+ public void createRacingCar(final List racingCarCreateDtoList) {
+ List racingCars = racingCarCreateDtoList.stream().map(racingCarDao::insert).toList();
+ }
+
+ @Override
+ public void move() {
+ for (RacingCar racingCar : racingCarDao.select()){
+ Random rand = new Random();
+
+ boolean result = rand.nextInt(10) >= 4;
+
+ racingCar.getResults().add(result);
+ }
+ }
+
+ @Override
+ public List getResults() {
+ return racingCarDao.select().stream().map(RacingCarConverter::toRacingCarResultDto).toList();
+ }
+}
diff --git a/src/main/java/view/RacingCarView.java b/src/main/java/view/RacingCarView.java
new file mode 100644
index 00000000..eebf7f01
--- /dev/null
+++ b/src/main/java/view/RacingCarView.java
@@ -0,0 +1,45 @@
+package view;
+
+import dto.RacingCarResultDto;
+import java.util.List;
+import java.util.Scanner;
+
+public class RacingCarView {
+
+ public List inputRacingCarName() {
+ Scanner scanner = new Scanner(System.in);
+
+ System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
+ String input = scanner.nextLine();
+
+ return List.of(input.split(","));
+ }
+
+ public int inputRound() {
+ Scanner scanner = new Scanner(System.in);
+
+ System.out.println("시도할 회수는 몇회인가요?");
+ int round = scanner.nextInt();
+
+ return round;
+ }
+
+ public void printResultTitle() {
+ System.out.println("\n실행 결과");
+ }
+
+ public void printResult(List racingCarResultDtoList) {
+ for (RacingCarResultDto racingCarResultDto : racingCarResultDtoList) {
+ System.out.printf("%s : %s%n", racingCarResultDto.getName(), racingCarResultDto.getResultString());
+ }
+ System.out.println();
+ }
+
+ public void printWinner(List racingCarResultDtoList) {
+ int maxDistance = racingCarResultDtoList.stream().mapToInt(RacingCarResultDto::getDistance).max().orElseThrow();
+
+ List winners = racingCarResultDtoList.stream().filter(v -> v.getDistance() == maxDistance).map(RacingCarResultDto::getName).toList();
+
+ System.out.println(String.join(", ", winners) + "가 최종 우승했습니다.");
+ }
+}
From 83fbd7190d0aafa7c325078145aeae90f5e827ea Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Fri, 11 Oct 2024 08:00:54 +0900
Subject: [PATCH 10/13] Refactor: Add implementation of lombok
---
build.gradle | 2 ++
1 file changed, 2 insertions(+)
diff --git a/build.gradle b/build.gradle
index 239f9e78..85891c16 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,6 +14,8 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
+ compileOnly("org.projectlombok:lombok:1.18.34")
+ annotationProcessor('org.projectlombok:lombok:1.18.34')
}
test {
From 13a911b171ab64c8cfb453ad3100a07bfd3325c4 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Sat, 12 Oct 2024 07:26:21 +0900
Subject: [PATCH 11/13] Refactor: Add implementation of mockito
---
build.gradle | 1 +
1 file changed, 1 insertion(+)
diff --git a/build.gradle b/build.gradle
index 85891c16..8d5f4636 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,6 +14,7 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
+ testImplementation("org.mockito:mockito-core:5.14.1")
compileOnly("org.projectlombok:lombok:1.18.34")
annotationProcessor('org.projectlombok:lombok:1.18.34')
}
From 1a3d4b56b342305467a8f9ea882d851e305a92a0 Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Sat, 12 Oct 2024 07:40:41 +0900
Subject: [PATCH 12/13] Feat: Add NumberGenerateUtil as Bean for test
---
src/main/java/RacingCarGame.java | 4 +++-
src/main/java/service/RacingCarServiceImpl.java | 12 +++++++-----
src/main/java/util/NumberGenerateUtil.java | 11 +++++++++++
3 files changed, 21 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/util/NumberGenerateUtil.java
diff --git a/src/main/java/RacingCarGame.java b/src/main/java/RacingCarGame.java
index eb07fee6..453a0b2d 100644
--- a/src/main/java/RacingCarGame.java
+++ b/src/main/java/RacingCarGame.java
@@ -2,13 +2,15 @@
import dao.RacingCarDao;
import service.RacingCarService;
import service.RacingCarServiceImpl;
+import util.NumberGenerateUtil;
import view.RacingCarView;
public class RacingCarGame {
public static void main(String[] args) {
RacingCarView racingCarView = new RacingCarView();
RacingCarDao racingCarDao = new RacingCarDao();
- RacingCarService racingCarService = new RacingCarServiceImpl(racingCarDao);
+ NumberGenerateUtil numberGenerateUtil = new NumberGenerateUtil();
+ RacingCarService racingCarService = new RacingCarServiceImpl(racingCarDao, numberGenerateUtil);
RacingCarController game = new RacingCarController(racingCarView, racingCarService);
game.set();
diff --git a/src/main/java/service/RacingCarServiceImpl.java b/src/main/java/service/RacingCarServiceImpl.java
index a9ddd97f..7cfb31e0 100644
--- a/src/main/java/service/RacingCarServiceImpl.java
+++ b/src/main/java/service/RacingCarServiceImpl.java
@@ -6,12 +6,13 @@
import dto.RacingCarCreateDto;
import dto.RacingCarResultDto;
import java.util.List;
-import java.util.Random;
import lombok.RequiredArgsConstructor;
+import util.NumberGenerateUtil;
@RequiredArgsConstructor
public class RacingCarServiceImpl implements RacingCarService {
final RacingCarDao racingCarDao;
+ final NumberGenerateUtil numberGenerateUtil;
@Override
public void createRacingCar(final List racingCarCreateDtoList) {
@@ -21,11 +22,12 @@ public void createRacingCar(final List racingCarCreateDtoLis
@Override
public void move() {
for (RacingCar racingCar : racingCarDao.select()){
- Random rand = new Random();
+ int power = numberGenerateUtil.generateRandomNumber();
- boolean result = rand.nextInt(10) >= 4;
-
- racingCar.getResults().add(result);
+ if (0 <= power && power <= 9)
+ racingCar.getResults().add(power >= 4);
+ else
+ throw new NumberFormatException("0~9 사이의 Power 값을 필요로 합니다.");
}
}
diff --git a/src/main/java/util/NumberGenerateUtil.java b/src/main/java/util/NumberGenerateUtil.java
new file mode 100644
index 00000000..2acba90b
--- /dev/null
+++ b/src/main/java/util/NumberGenerateUtil.java
@@ -0,0 +1,11 @@
+package util;
+
+import java.security.SecureRandom;
+
+public class NumberGenerateUtil {
+
+ public int generateRandomNumber() {
+ SecureRandom secureRandom = new SecureRandom();
+ return secureRandom.nextInt(10);
+ }
+}
From 68f54a03ccdb3ef8d7e21b351c0b323015e94e1c Mon Sep 17 00:00:00 2001
From: IDLE <83659656+idle2534@users.noreply.github.com>
Date: Sat, 12 Oct 2024 07:42:37 +0900
Subject: [PATCH 13/13] Feat: Fix and Add test following mvc pattern
---
src/main/java/view/RacingCarView.java | 41 +++++++-
src/test/java/RacingCarConverterTest.java | 38 ++++++++
src/test/java/RacingCarTest.java | 114 +++++++---------------
src/test/java/RacingCarViewTest.java | 64 ++++++++++++
4 files changed, 176 insertions(+), 81 deletions(-)
create mode 100644 src/test/java/RacingCarConverterTest.java
create mode 100644 src/test/java/RacingCarViewTest.java
diff --git a/src/main/java/view/RacingCarView.java b/src/main/java/view/RacingCarView.java
index eebf7f01..24875ea7 100644
--- a/src/main/java/view/RacingCarView.java
+++ b/src/main/java/view/RacingCarView.java
@@ -1,27 +1,60 @@
package view;
import dto.RacingCarResultDto;
+import java.lang.module.ResolutionException;
+import java.util.InputMismatchException;
import java.util.List;
import java.util.Scanner;
+import java.util.regex.Pattern;
+
public class RacingCarView {
+ public static class RacingCarInputException extends RuntimeException {
+
+ public RacingCarInputException() {
+ super("유효하지 않은 입력입니다.");
+ }
+
+ public RacingCarInputException(final String s) {
+ super(s);
+ }
+ }
public List inputRacingCarName() {
Scanner scanner = new Scanner(System.in);
System.out.println("경주할 자동차 이름을 입력하세요(이름은 쉼표(,)를 기준으로 구분).");
- String input = scanner.nextLine();
+ String input = scanner.nextLine().replaceAll(" ", "");
+
+ if (Pattern.compile("[!@#$%^&*().?\"{}|<>]").matcher(input).find())
+ throw new RacingCarInputException("이름에 특수기호를 입력할 수 없습니다.");
- return List.of(input.split(","));
+ List names = List.of(input.split(","));
+
+ if (names.size() <= 1)
+ throw new RacingCarInputException("최소한 두 명 이상의 플레이어가 필요합니다.");
+
+
+ return names;
}
public int inputRound() {
Scanner scanner = new Scanner(System.in);
System.out.println("시도할 회수는 몇회인가요?");
- int round = scanner.nextInt();
- return round;
+ try {
+ int round = scanner.nextInt();
+
+ if (round <= 0)
+ throw new NumberFormatException("횟수는 1회 이상이여야 합니다.");
+
+ return round;
+ } catch (InputMismatchException e) {
+ throw new RacingCarInputException();
+ } catch (NumberFormatException e) {
+ throw new RacingCarInputException(e.getMessage());
+ }
}
public void printResultTitle() {
diff --git a/src/test/java/RacingCarConverterTest.java b/src/test/java/RacingCarConverterTest.java
new file mode 100644
index 00000000..16537fd4
--- /dev/null
+++ b/src/test/java/RacingCarConverterTest.java
@@ -0,0 +1,38 @@
+import static org.assertj.core.api.Assertions.assertThat;
+
+import converter.RacingCarConverter;
+import domain.RacingCar;
+import dto.RacingCarCreateDto;
+import dto.RacingCarResultDto;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+public class RacingCarConverterTest {
+
+ @Test
+ public void testToRacingCarCreateDto() {
+ RacingCarCreateDto expected = new RacingCarCreateDto("tester");
+ RacingCarCreateDto actual = RacingCarConverter.toRacingCarCreateDto("tester");
+ assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
+ }
+
+ @Test
+ public void testToRacingCarResultDto() {
+ RacingCarResultDto expected = new RacingCarResultDto("tester", "---", 3);
+ RacingCar racingCar = new RacingCar("tester");
+ racingCar.getResults().addAll(List.of(false, false, true, true, true));
+ RacingCarResultDto actual = RacingCarConverter.toRacingCarResultDto(racingCar);
+ assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
+ }
+
+ @ParameterizedTest
+ @ValueSource(booleans = {true, false})
+ public void testResultToString(boolean value) {
+ String expected = value ? "-" : "";
+ String actual = RacingCarConverter.resultToString(value);
+
+ assertThat(actual).isEqualTo(expected);
+ }
+}
diff --git a/src/test/java/RacingCarTest.java b/src/test/java/RacingCarTest.java
index 3327e0ac..7b373836 100644
--- a/src/test/java/RacingCarTest.java
+++ b/src/test/java/RacingCarTest.java
@@ -1,97 +1,57 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import java.io.ByteArrayInputStream;
-import java.util.InputMismatchException;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import converter.RacingCarConverter;
+import dao.RacingCarDao;
+import dto.RacingCarCreateDto;
+import java.util.List;
+import java.util.stream.Stream;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import service.RacingCarService;
+import service.RacingCarServiceImpl;
+import util.NumberGenerateUtil;
public class RacingCarTest {
@Nested
@DisplayName("자동차 이동 테스트")
- class RacingCarMove {
- @Test
- @DisplayName("자동차 랜덤 이동 테스트")
- void randomMove() {
- RacingCar racingCar = new RacingCar("Test");
- int expected = racingCar.getScore();
- int actual = racingCar.move();
-
- assertThat(actual).isIn(expected, expected + 1);
- }
-
- @Test
+ class RacingCarMoveTest {
+ @ParameterizedTest
+ @ValueSource(ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
@DisplayName("자동차 이동 조건 테스트")
- void moveCondition() {
- RacingCar racingCar = new RacingCar("Test");
- int expected = 0;
- int actual = racingCar.move(3);
+ void testCondition(int value) {
+ NumberGenerateUtil numberGenerateUtil = mock(NumberGenerateUtil.class);
+ when(numberGenerateUtil.generateRandomNumber()).thenReturn(value);
+ RacingCarDao racingCarDao = new RacingCarDao();
+ RacingCarService racingCarService = new RacingCarServiceImpl(racingCarDao, numberGenerateUtil);
+ List racingCarCreateDtoList = Stream.of("tester1", "tester2").map(v -> RacingCarConverter.toRacingCarCreateDto("")).toList();
+ racingCarService.createRacingCar(racingCarCreateDtoList);
- assertThat(actual).isEqualTo(expected);
+ racingCarService.move();
- expected = 1;
- actual = racingCar.move(5);
+ int expected = value >= 4 ? 1 : 0;
+ int actual = racingCarService.getResults().get(0).getDistance();
assertThat(actual).isEqualTo(expected);
}
- @Test
+ @ParameterizedTest
+ @ValueSource(ints = {-1, 10})
@DisplayName("자동차 이동 조건 예외처리 테스트")
- void moveConditionException() {
- RacingCar racingCar = new RacingCar("Test");
-
- assertThatThrownBy(() -> racingCar.move(-1)).isInstanceOf(IllegalArgumentException.class).hasMessage("0~9 사이의 Power 값을 필요로 합니다.");
-
- assertThatThrownBy(() -> racingCar.move(10)).isInstanceOf(IllegalArgumentException.class).hasMessage("0~9 사이의 Power 값을 필요로 합니다.");
- }
- }
-
-
- @Test
- @DisplayName("자동차 결과 텍스트 테스트")
- void racingCarResultString() {
- RacingCar racingCar = new RacingCar("Test");
-
- for (int i = 0; i < 5; ++i)
- racingCar.move();
-
-
- String actual = racingCar.getResultString(5);
- String expected = new String(new char[racingCar.getScore()]).replace("\0", "-");
-
- assertThat(actual).isEqualTo(expected);
- }
-
- @Nested
- @DisplayName("자동차 게임 설정 테스트")
- class SetRacingCarGameTest {
- @Test
- @DisplayName("자동차 이름 입력이 하나일 경우 테스트")
- void setGameWithLessThanTwoNameInput() {
- RacingCarGame racingCarGame = new RacingCarGame();
- System.setIn(new ByteArrayInputStream("test1\n1".getBytes()));
-
- assertThatThrownBy(racingCarGame::setGame).isInstanceOf(InputMismatchException.class).hasMessage("최소한 두 명 이상의 플레이어가 필요합니다.");
- }
-
- @Test
- @DisplayName("시도할 횟수 입력이 음수일 경우 테스트")
- void setGameWithNegativePhaseInput() {
- RacingCarGame racingCarGame = new RacingCarGame();
- System.setIn(new ByteArrayInputStream("test1,test2\n-1\n".getBytes()));
-
- assertThatThrownBy(racingCarGame::setGame).isInstanceOf(NumberFormatException.class).hasMessage("음수는 유효한 숫자가 아닙니다.");
- }
-
- @Test
- @DisplayName("시도할 횟수 입력이 숫자가 아닌 경우 테스트")
- void setGameWithInvalidPhaseInput() {
- RacingCarGame racingCarGame = new RacingCarGame();
- System.setIn(new ByteArrayInputStream("test1,test2\nabc\n".getBytes()));
-
- assertThatThrownBy(racingCarGame::setGame).isInstanceOf(InputMismatchException.class).hasMessage("유효한 숫자가 아닙니다.");
+ void moveConditionException(int value) {
+ NumberGenerateUtil numberGenerateUtil = mock(NumberGenerateUtil.class);
+ when(numberGenerateUtil.generateRandomNumber()).thenReturn(value);
+ RacingCarDao racingCarDao = new RacingCarDao();
+ RacingCarService racingCarService = new RacingCarServiceImpl(racingCarDao, numberGenerateUtil);
+ List racingCarCreateDtoList = Stream.of("tester1", "tester2").map(v -> RacingCarConverter.toRacingCarCreateDto("")).toList();
+ racingCarService.createRacingCar(racingCarCreateDtoList);
+
+ assertThatThrownBy(racingCarService::move).isInstanceOf(NumberFormatException.class).hasMessage("0~9 사이의 Power 값을 필요로 합니다.");
}
}
}
diff --git a/src/test/java/RacingCarViewTest.java b/src/test/java/RacingCarViewTest.java
new file mode 100644
index 00000000..e04f2eae
--- /dev/null
+++ b/src/test/java/RacingCarViewTest.java
@@ -0,0 +1,64 @@
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.ByteArrayInputStream;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import view.RacingCarView;
+import view.RacingCarView.RacingCarInputException;
+
+public class RacingCarViewTest {
+
+ @Nested
+ class InputRacingCarNameTest {
+ @Test
+ @DisplayName("자동차 이름 입력이 하나일 경우 테스트")
+ void inputWithLessThanTwoName() {
+ RacingCarView racingCarView = new RacingCarView();
+ System.setIn(new ByteArrayInputStream("test1\n".getBytes()));
+
+ assertThatThrownBy(racingCarView::inputRacingCarName).isInstanceOf(RacingCarInputException.class).hasMessage("최소한 두 명 이상의 플레이어가 필요합니다.");
+ }
+
+ @Test
+ @DisplayName("자동차 이름에 띄어쓰기가 있을 경우 테스트")
+ void inputWithSpace() {
+ RacingCarView racingCarView = new RacingCarView();
+ System.setIn(new ByteArrayInputStream("test1, test2\n".getBytes()));
+
+ assertThat(racingCarView.inputRacingCarName().stream().noneMatch(s -> s.contains(" "))).isTrue();
+ }
+
+ @Test
+ @DisplayName("자동차 이름에 특수기호 있을 경우 테스트")
+ void inputWithSpecialSymbol() {
+ RacingCarView racingCarView = new RacingCarView();
+ System.setIn(new ByteArrayInputStream("test1#,test2&\n".getBytes()));
+
+ assertThatThrownBy(racingCarView::inputRacingCarName).isInstanceOf(RacingCarInputException.class).hasMessage("이름에 특수기호를 입력할 수 없습니다.");
+ }
+ }
+
+ @Nested
+ class InputRoundTest {
+ @Test
+ @DisplayName("시도할 횟수 입력이 음수일 경우 테스트")
+ void inputWithNegativeNumber() {
+ RacingCarView racingCarView = new RacingCarView();
+ System.setIn(new ByteArrayInputStream("-1\n".getBytes()));
+
+ assertThatThrownBy(racingCarView::inputRound).isInstanceOf(RacingCarInputException.class).hasMessage("횟수는 1회 이상이여야 합니다.");
+ }
+
+ @Test
+ @DisplayName("시도할 횟수 입력이 숫자가 아닌 경우 테스트")
+ void inputWithInvalidCharacter() {
+ RacingCarView racingCarView = new RacingCarView();
+ System.setIn(new ByteArrayInputStream("abc\n".getBytes()));
+
+ assertThatThrownBy(racingCarView::inputRound).isInstanceOf(RacingCarInputException.class).hasMessage("유효하지 않은 입력입니다.");
+ }
+ }
+
+}