-
Notifications
You must be signed in to change notification settings - Fork 98
[그리디] 서현진 자동차 경주 미션 3, 4단계 제출합니다. #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: nonactress
Are you sure you want to change the base?
Changes from all commits
fbfab99
1c54f83
dee665e
a9af148
c6d9acc
560ac39
aeb4ab7
dcb4ec5
c11d098
480f751
c0d037a
62b3941
864e6c0
97b4d95
035ecdd
0de29df
f660a28
7f5f429
630df3a
22dc5a0
704cf09
c19c73a
b608f5b
b471111
cd70b8a
66e64b6
68814e7
4f1b377
ced1092
fd0a317
76330fc
03ef929
3e12240
cd944bc
5ca9b26
fb563ce
482cf13
d5ef197
ad763d8
cab4c5f
b160676
2831966
ada34f1
eb25bf2
c2e519f
43190b6
f6c6e25
3fb578e
7d22b1d
72497ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import controller.RacingController; | ||
|
||
public class RacingGame { | ||
public static void main(String[] args) { | ||
RacingController racingController = new RacingController(); | ||
racingController.run(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package controller; | ||
|
||
import model.Cars; | ||
import model.CarsWinner; | ||
import view.InputView; | ||
import view.OutputView; | ||
|
||
|
||
public class RacingController { | ||
public void run() { | ||
String[] carNames = InputView.getCarNames(); | ||
int raceCount = InputView.getRaceCount(); | ||
|
||
Cars cars = new Cars(carNames); | ||
CarsWinner carsWinner = new CarsWinner(); | ||
|
||
OutputView.printResultMessage(); | ||
RacingService racingService = new RacingService(); | ||
racingService.startRace(cars, raceCount); | ||
|
||
OutputView.printWinners(carsWinner.findWinners(cars)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package controller; | ||
|
||
import model.Cars; | ||
import model.CarsWinner; | ||
import model.Number.IsMovable; | ||
import view.OutputView; | ||
|
||
public class RacingService { | ||
public void startRace(Cars cars, int raceCount) { | ||
IsMovable isMovable = new IsMovable(); | ||
CarsWinner carsWinner = new CarsWinner(); | ||
|
||
for (int i = 0; i < raceCount; i++) { | ||
cars.moveAll(isMovable); // Model의 상태 변경 요청 | ||
OutputView.printRoundResult(cars.getCars()); // View에 출력 요청 | ||
} | ||
carsWinner.findWinners(cars); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package model; | ||
|
||
import java.util.ArrayList; | ||
|
||
public class Car { | ||
|
||
private final String name; | ||
private int position = 0; | ||
|
||
public Car(String name) { | ||
this.name = name; | ||
} | ||
|
||
public void move() { | ||
this.position++; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
public int getPosition() { | ||
return position; | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package model; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import model.Number.IsMovable; | ||
|
||
public class Cars { | ||
private final List<Car> cars; | ||
|
||
public Cars(String[] carNames) { | ||
this.cars = new ArrayList<>(); | ||
for (String name : carNames) { | ||
cars.add(new Car(name)); | ||
} | ||
} | ||
|
||
public void moveAll(IsMovable isMovable) { | ||
for (Car car : cars) { | ||
move(car, isMovable); | ||
} | ||
} | ||
|
||
private void move(Car car, IsMovable isMovable) { | ||
if (isMovable.getcheck()) { | ||
car.move(); | ||
} | ||
} | ||
|
||
public List<Car> getCars() { | ||
return Collections.unmodifiableList(cars); | ||
|
||
/*return this.cars; | ||
*위 방식을 안쓴 이유는 객체를 받아서 다른 메소드나 클래스에서 | ||
*수정이 가능해 지기 때문에 위 컬렉션 메소드로 반환값 설정 | ||
* */ | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package model; | ||
|
||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class CarsWinner { | ||
private final List<String> winners = new ArrayList<>(); | ||
|
||
|
||
public List<String> findWinners(Cars cars) { | ||
int maxPosition = findMaxPosition(cars); | ||
for (Car car : cars.getCars()) { | ||
checkAndAddWinner(winners, car, maxPosition); | ||
} | ||
return winners; | ||
} | ||
|
||
private void checkAndAddWinner(List<String> winners, Car car, int maxPosition) { | ||
if (car.getPosition() == maxPosition) { | ||
winners.add(car.getName()); | ||
} | ||
} | ||
|
||
private int findMaxPosition(Cars cars) { | ||
int maxPosition = 0; | ||
for (Car car : cars.getCars()) { | ||
maxPosition = Math.max(car.getPosition(), maxPosition); | ||
} | ||
return maxPosition; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package model.Number; | ||
|
||
public class FixedNumberGenerator implements NumberGenerator { | ||
private static final int NOT_MOVE_CONITION = 1; | ||
|
||
@Override | ||
public int genrator() { | ||
return NOT_MOVE_CONITION; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package model.Number; | ||
|
||
public class IsMovable { | ||
private NumberGenerator movable = new RandomNumberGenerator(); | ||
private NumberGenerator notNovable = new FixedNumberGenerator(); | ||
|
||
private static final int MOVE_CONITION = 4; | ||
|
||
public Boolean getcheck() { | ||
//return movable.genrator() > MOVE_CONITION; | ||
return notNovable.genrator() > MOVE_CONITION; | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package model.Number; | ||
|
||
public interface NumberGenerator { | ||
int genrator(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package model.Number; | ||
|
||
import java.util.Random; | ||
|
||
public class RandomNumberGenerator implements NumberGenerator { | ||
|
||
@Override | ||
public int genrator() | ||
{ | ||
final Random random = new Random(); | ||
return random.nextInt(10); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package view; | ||
|
||
import java.util.Scanner; | ||
|
||
public class InputView { | ||
private static final Scanner scanner = new Scanner(System.in); | ||
|
||
public static String[] getCarNames() { | ||
String[] splits = null; | ||
boolean splitsCheck = false; | ||
while (true) { | ||
try { | ||
System.out.println("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"); | ||
splits = scanner.nextLine().split(",", -1); | ||
|
||
// 예외가 발생할 수 있는 검증 메서드를 호출 | ||
splitsCheck = isValid(splits); | ||
} catch (IllegalArgumentException e) { | ||
// validateCarNames에서 예외를 던지면 이 코드가 실행됨 | ||
// 예외에 담긴 메시지를 출력하고, while 루프의 처음으로 돌아감 | ||
System.out.println(e.getMessage()); | ||
} | ||
if (splits != null && splitsCheck) return splits; | ||
} | ||
} | ||
|
||
private static String[] getStrings(String[] splitCar) { | ||
if (isValid(splitCar)) { | ||
return splitCar; | ||
} | ||
return null; | ||
} | ||
|
||
public static int getRaceCount() { | ||
System.out.println("시도할 회수는 몇회인가요?"); | ||
int count = scanner.nextInt(); | ||
scanner.nextLine(); // 개행 문자 제거 | ||
return count; | ||
} | ||
|
||
public static boolean isValid(String[] cars) { | ||
if (cars.length <= 1) { | ||
// boolean을 반환하는 대신, 예외를 생성하고 던집니다. | ||
throw new IllegalArgumentException("[ERROR] 두 개 이상의 자동차를 입력해주세요!"); | ||
} | ||
|
||
for (String car : cars) { | ||
if (car.trim().isEmpty()) { | ||
System.out.println("자동차의 이름이 공백일 순 없습니다!"); | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package view; | ||
|
||
import model.Car; | ||
|
||
import java.util.List; | ||
|
||
public class OutputView { | ||
|
||
public static void printResultMessage() { | ||
System.out.println("\n실행 결과"); | ||
} | ||
|
||
public static void printRoundResult(List<Car> cars) { | ||
for (Car car : cars) { | ||
System.out.print(car.getName() + " : "); | ||
printCarPosition(car); | ||
System.out.println(); | ||
} | ||
System.out.println(); | ||
} | ||
|
||
private static void printCarPosition(Car car) { | ||
System.out.print("-".repeat(car.getPosition())); | ||
} | ||
|
||
public static void printWinners(List<String> winners) { | ||
String winnerNames = String.join(", ", winners); | ||
System.out.println("최종 우승자 : " + winnerNames); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package model; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
class CarTest { | ||
|
||
@Test | ||
@DisplayName("자동차 생성 시 이름과 초기 위치(0)를 올바르게 설정한다.") | ||
void createCar() { | ||
// given: "pobi"라는 이름을 가진 자동차를 준비하고 | ||
String carName = "pobi"; | ||
|
||
// when: 해당 이름으로 자동차를 생성하면 | ||
Car car = new Car(carName); | ||
|
||
// then: 이름은 "pobi"이고 위치는 0이어야 한다. | ||
assertEquals(carName, car.getName()); | ||
assertEquals(0, car.getPosition()); | ||
} | ||
|
||
@Test | ||
@DisplayName("move 메서드를 호출하면 위치가 1 증가한다.") | ||
void moveCar() { | ||
// given: "woni"라는 이름의 자동차를 생성하고 | ||
Car car = new Car("woni"); | ||
|
||
// when: move 메서드를 한 번 호출하면 | ||
car.move(); | ||
|
||
// then: 자동차의 위치는 1이 되어야 한다. | ||
assertEquals(1, car.getPosition()); | ||
} | ||
|
||
@Test | ||
@DisplayName("move 메서드를 여러 번 호출하면 호출한 횟수만큼 위치가 증가한다.") | ||
void moveCarMultipleTimes() { | ||
// given: "jun"이라는 이름의 자동차를 생성하고 | ||
Car car = new Car("jun"); | ||
int moveCount = 5; | ||
|
||
// when: move 메서드를 5번 호출하면 | ||
for (int i = 0; i < moveCount; i++) { | ||
car.move(); | ||
} | ||
|
||
// then: 자동차의 위치는 5가 되어야 한다. | ||
assertEquals(moveCount, car.getPosition()); | ||
} | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package model.random; | ||
|
||
import model.random.*; | ||
import model.Car; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
public class RandomMoveStrategyTest { | ||
|
||
@Test | ||
@DisplayName("값이 랜덤한지 확인") | ||
void checkRandom (){ | ||
// given: "pobi"라는 이름을 가진 자동차를 준비하고 | ||
String carName = "pobi"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 테스트가 어떤 걸 테스트하고 싶은지 잘 모르겠습니다! 실제로 랜덤한 값이 나오는 것을 테스트하고 싶으신 건가요?? 만약 그렇다면, 그건 저희가 직접 테스트하기 아주 어려운 영역이라고 생각합니다. '진짜 랜덤'은 테스트를 실행할 때마다 결과가 계속 바뀌기 때문에, 결과를 예측하고 검증하는 자동화된 테스트를 만들기 거의 불가능하기 때문입니다. 이건 저희 코드의 로직보다는 Java의 Random 클래스 자체의 기능을 테스트하는 셈이라 테스트하지 않아도 되는 영역 같습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아아 위 코드를 작성한 이유는 만약에 제가 RandomGenerator를 만들지 않았다면 랜덤한 값이 나오는 메소드인지 확인해보지 않을까?? 하는 생각에서 작성한 코드 였습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 결론부터 말씀드리면, 프로젝트 규모가 아무리 커져도 이유를 크게 두 가지로 생각해봤는데요,
저희는 외부 라이브러리의 기능 자체를 검증하기보다는 '그 라이브러리를 사용하는 우리 코드가 생각대로 잘 동작하는가'에 집중하는 것이 일반적인 테스트 전략인 것 같아요! 덕분에 테스트의 역할과 범위에 대해 다시 한 번 생각해볼 수 있었네요. 좋은 질문 감사합니다! 😊 |
||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
give-when-then으로 테스트 잘 작성해주셨네요 👍
@DisplayName
대신 한국어로 테스트 이름을 바로 지을 수도 있어요!