diff --git a/README.md b/README.md index cb44fbb4e3..905d38c7bd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ - **[1단계 - 문자열 계산기](./docs/01-string-calculator.md)** - **[2단계 - 로또(자동)](./docs/02-lotto-auto.md)** - **[3단계 - 로또(2등)](./docs/03-lotto-rank-second.md)** -- **[4단계 - 로또(수동)]()** +- **[4단계 - 로또(수동)](./docs/04-lotto-manual.md)** ## 진행 방법 * 로또 요구사항을 파악한다. * 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다. diff --git a/docs/04-lotto-manual.md b/docs/04-lotto-manual.md new file mode 100644 index 0000000000..a1c3403938 --- /dev/null +++ b/docs/04-lotto-manual.md @@ -0,0 +1,123 @@ +# 4단계 - 로또(수동) +*** +## 코드 리뷰 +> PR 링크: +> **[https://github.com/next-step/java-lotto/pull/4232](https://github.com/next-step/java-lotto/pull/4232)** +## 나의 학습 목표 +- TDD 사이클로 구현 +- 객체지향 생활 체조 원칙 준수 +- 테스트 작성하기 쉬운 구조로 설계 +- 체크리스트 및 피드백 준수 +- 기능 추가 시 컴파일 에러를 최소화하며 점진적인 리팩터링에 도전 +## 기능 요구 사항 +- 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다. +- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다. +## 힌트 +- 규칙 3: 모든 원시값과 문자열을 포장한다. + - 로또 숫자 하나는 int 타입이다. 이 숫자 하나를 추상화한 LottoNo 객체를 추가해 구현한다. +- 예외 처리를 통해 프로그램이 중단되지 않고 다시 입력할 수 있도록 구현한다. + - 사용자가 잘못된 값을 입력했을 때 java exception으로 에러 처리를 한다. + - java8에 추가된 Optional을 적용해 NullPointerException이 발생하지 않도록 한다. +## 프로그래밍 요구사항 +- 규칙 3: 모든 원시값과 문자열을 포장한다. +- 규칙 5: 줄여쓰지 않는다(축약 금지). +- 예외 처리를 통해 에러가 발생하지 않도록 한다. +- 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 +- java enum을 적용해 프로그래밍을 구현한다. +- 규칙 8: 일급 콜렉션을 쓴다. +- indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. +- 함수(또는 메소드)의 길이가 15라인을 넘어가지 않도록 구현한다. +- 자바 코드 컨벤션을 지키면서 프로그래밍한다. +- else 예약어를 쓰지 않는다. +## PR 전 점검 +**[체크리스트 확인하기](checklist.md)** +## 구현 기능 목록 +### 공통 +- [x] 금액 (Money) + - [x] 0원 이상의 정수로 생성 + - [x] 금액 비교 (미만 여부) + - [x] 나눗셈 가능 여부 판단 + - [x] 나눗셈 연산 + - [x] 비율 계산 + - [x] 곱셈 연산 + - [x] 덧셈 연산 + - [x] 원화 문자열 변환 + +### 로또 번호 +- [x] 로또 번호 (LottoNumber) + - [x] 1~45 범위의 정수로 생성 + - [x] 문자열 입력으로 생성 + - [x] 범위 벗어날 시 예외 발생 + - [x] 동일 값은 캐싱된 인스턴스 반환 + +### 로또 +- [x] 로또 (Lotto) + - [x] 6개의 로또 번호로 생성 + - [x] 중복된 번호 존재 시 예외 발생 + - [x] 번호 누락 시 예외 발생 + - [x] 6개가 아닐 시 예외 발생 + - [x] 다른 로또와 일치하는 번호 개수 계산 + - [x] 특정 번호 포함 여부 판단 + - [x] 정렬된 출력용 문자열 반환 + +### 로또 구매 +- [x] 로또 구매 개수 (LottoCount) + - [x] 0 이상의 정수로 생성 + - [x] 문자열 입력으로 생성 + - [x] 빈 문자열일 시 예외 발생 + - [x] 음수일 시 예외 발생 + - [x] 다른 개수와 차감 연산 + - [x] 차감 결과가 음수일 시 예외 발생 + +- [x] 로또 구매 금액 (LottoPurchaseAmount) + - [x] 금액으로 생성 + - [x] 문자열 입력으로 생성 + - [x] 정수 입력으로 생성 + - [x] 최소 금액(1,000원) 미달 시 예외 발생 + - [x] 1,000원 단위가 아닐 시 예외 발생 + - [x] 구매 가능한 로또 개수 계산 + +- [x] 구매한 로또 목록 (PurchasedLottos) + - [x] 로또 목록으로 생성 + - [x] 빈 목록일 시 예외 발생 + - [x] 당첨 로또와 비교하여 결과 생성 + +### 당첨 판정 +- [x] 당첨 로또 (WinningLotto) + - [x] 로또와 보너스 번호로 생성 + - [x] 보너스 번호가 당첨 번호와 중복 시 예외 발생 + - [x] 구매 로또와 비교하여 등수 판정 + +- [x] 등수 (LottoRank) + - [x] 일치 개수와 보너스 일치 여부로 등수 결정 + - [x] 3개 미만 일치 시 MISS 반환 + - [x] 3개 일치 시 FIFTH (5,000원) + - [x] 4개 일치 시 FOURTH (50,000원) + - [x] 5개 일치 시 THIRD (1,500,000원) + - [x] 5개 일치 + 보너스 일치 시 SECOND (30,000,000원) + - [x] 6개 일치 시 FIRST (2,000,000,000원) + - [x] 등수별 총 상금 계산 + - [x] 일치 개수 출력용 문자열 반환 + - [x] 상금 출력용 문자열 반환 + +- [x] 로또 결과 (LottoResult) + - [x] 빈 상태로 생성 + - [x] 등수 추가 + - [x] 총 상금 계산 + - [x] 등수별 결과 출력용 문자열 반환 + +- [x] 수익률 (ReturnRate) + - [x] 구매금액과 총 상금으로 생성 + - [x] 수익률 0 미만일 시 예외 발생 + - [x] 수익률 출력용 문자열 반환 + +### 유틸리티 +- [x] 자동 로또 생성기 (AutoBasedLottoGenerator) + - [x] 1~45 범위의 번호 풀 보유 + - [x] 지정 개수만큼 로또 생성 + - [x] 셔플 방식으로 6개 번호 선택 +- [x] 수동 로또 생성기 (ManualBasedLottoGenerator) + - [x] 문자열 목록을 입력받아 로또 목록 생성 + +- [x] 로또 번호 파서 (LottoNumberParser) + - [x] 쉼표 구분 문자열을 로또 번호 목록으로 변환 \ No newline at end of file diff --git a/src/main/java/lotto/Application.java b/src/main/java/lotto/Application.java index da7c70e75a..9b116fa68f 100644 --- a/src/main/java/lotto/Application.java +++ b/src/main/java/lotto/Application.java @@ -1,38 +1,93 @@ package lotto; +import static lotto.view.InputView.*; +import static lotto.view.ResultView.*; + import java.util.List; +import java.util.function.Supplier; import lotto.domain.*; -import lotto.utils.AutoBasedLottoGenerator; -import lotto.utils.LottoNumberParser; -import lotto.view.InputView; -import lotto.view.ResultView; +import lotto.domain.AutoBasedLottoGenerator; +import lotto.domain.LottoNumberParser; +import lotto.domain.ManualBasedLottoGenerator; public class Application { public static void main(String[] args) { - LottoPurchaseAmount purchaseAmount = getPurchaseAmount(); - PurchasedLottos purchased = new PurchasedLottos(generateLottos(purchaseAmount)); + LottoPurchaseAmount purchaseAmount = createPurchaseAmount(); + Lottos purchased = purchaseLottos(purchaseAmount); + + printPurchasedLottos(purchased); + + LottoResult result = purchased.result(createWinningLotto()); + + printResult(result, purchaseAmount); + } + + private static LottoPurchaseAmount createPurchaseAmount() { + return retryUntilSuccess(() -> new LottoPurchaseAmount(readPurchaseAmount())); + } + + private static Lottos purchaseLottos(LottoPurchaseAmount purchaseAmount) { + LottoCount totalCount = purchaseAmount.lottoCount(); + LottoCount manualCount = createManualLottoCount(totalCount); + LottoCount autoCount = totalCount.subtract(manualCount); + + printPurchaseCount(manualCount, autoCount); - ResultView.printPurchaseCount(purchased); - ResultView.printPurchasedLottos(purchased); + return createManualLottos(manualCount).merge(generateAutoLottos(autoCount)); + } - LottoResult result = purchased.result(getWinningLotto()); + private static LottoCount createManualLottoCount(LottoCount totalCount) { + return retryUntilSuccess(() -> { + LottoCount manualCount = new LottoCount(readManualLottoCount()); + totalCount.validateSubtractable(manualCount); + return manualCount; + }); + } - ResultView.printResult(result, purchaseAmount); + private static Lottos createManualLottos(LottoCount manualCount) { + return retryUntilSuccess( + () -> new ManualBasedLottoGenerator(readManualLottoNumbers(manualCount.value())).generate()); } - private static LottoPurchaseAmount getPurchaseAmount() { - return new LottoPurchaseAmount(InputView.readPurchaseAmount()); + private static Lottos generateAutoLottos(LottoCount autoCount) { + return new AutoBasedLottoGenerator(autoCount).generate(); } - private static List generateLottos(LottoPurchaseAmount purchaseAmount) { - return new AutoBasedLottoGenerator().generate(purchaseAmount.lottoCount()); + private static WinningLotto createWinningLotto() { + Lotto lotto = createLottoForWinning(); + LottoNumber bonus = createBonusNumber(lotto); + return new WinningLotto(lotto, bonus); } - private static WinningLotto getWinningLotto() { - String winningNumbers = InputView.readWinningNumbers(); - String bonusNumber = InputView.readBonusNumber(); + private static Lotto createLottoForWinning() { + return retryUntilSuccess(() -> new Lotto(createWinningNumbers())); + } + + private static List createWinningNumbers() { + return new LottoNumberParser().parse(readWinningNumbers()); + } + + private static LottoNumber createBonusNumber(Lotto lotto) { + return retryUntilSuccess(() -> { + LottoNumber bonus = LottoNumber.of(readBonusNumber()); + validateBonusNotDuplicated(lotto, bonus); + return bonus; + }); + } + + private static void validateBonusNotDuplicated(Lotto lotto, LottoNumber bonus) { + if (lotto.contains(bonus)) { + throw new IllegalArgumentException("보너스 번호는 당첨 번호와 중복될 수 없습니다."); + } + } - List numbers = new LottoNumberParser().parse(winningNumbers); - return new WinningLotto(numbers, bonusNumber); + private static T retryUntilSuccess(Supplier action) { + while (true) { + try { + return action.get(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } } } diff --git a/src/main/java/lotto/utils/AutoBasedLottoGenerator.java b/src/main/java/lotto/domain/AutoBasedLottoGenerator.java similarity index 71% rename from src/main/java/lotto/utils/AutoBasedLottoGenerator.java rename to src/main/java/lotto/domain/AutoBasedLottoGenerator.java index 81f8c0cadb..42ddf17d98 100644 --- a/src/main/java/lotto/utils/AutoBasedLottoGenerator.java +++ b/src/main/java/lotto/domain/AutoBasedLottoGenerator.java @@ -1,28 +1,28 @@ -package lotto.utils; +package lotto.domain; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -import lotto.domain.Lotto; -import lotto.domain.LottoCount; -import lotto.domain.LottoNumber; -public class AutoBasedLottoGenerator { +public class AutoBasedLottoGenerator implements LottosGenerator { private static final int LOTTO_NUMBER_MIN = 1; private static final int LOTTO_NUMBER_MAX = 45; private static final int LOTTO_PICK_SIZE = 6; private final List numbers; + private final LottoCount count; - public AutoBasedLottoGenerator() { + public AutoBasedLottoGenerator(LottoCount count) { + this.count = count; this.numbers = IntStream.rangeClosed(LOTTO_NUMBER_MIN, LOTTO_NUMBER_MAX) .mapToObj(LottoNumber::of) .collect(Collectors.toList()); } - public List generate(LottoCount count) { - return generateLottos(count.value()); + @Override + public Lottos generate() { + return new Lottos(generateLottos(count.value())); } private List generateLottos(int count) { diff --git a/src/main/java/lotto/domain/LottoCount.java b/src/main/java/lotto/domain/LottoCount.java index cd6c2b444e..18e9e03d6a 100644 --- a/src/main/java/lotto/domain/LottoCount.java +++ b/src/main/java/lotto/domain/LottoCount.java @@ -1,11 +1,36 @@ package lotto.domain; public record LottoCount(int value) { - private static final int MIN_COUNT = 1; + + public LottoCount(String input) { + this(toInt(input)); + } + + private static int toInt(String input) { + if (input == null || input.isBlank()) { + throw new IllegalArgumentException("구매 개수는 필수입니다."); + } + return Integer.parseInt(input); + } public LottoCount { - if (value < MIN_COUNT) { - throw new IllegalArgumentException("로또 구매 개수는 %d개 이상이어야 합니다.".formatted(MIN_COUNT)); + if (value < 0) { + throw new IllegalArgumentException("구매 개수는 0이상이어야 합니다."); + } + } + + public LottoCount subtract(LottoCount other) { + validateSubtractable(other); + return new LottoCount(this.value - other.value); + } + + public void validateSubtractable(LottoCount other) { + if (isLessThan(other)) { + throw new IllegalArgumentException("차감할 수 없습니다."); } } + + private boolean isLessThan(LottoCount other) { + return this.value < other.value; + } } diff --git a/src/main/java/lotto/utils/LottoNumberParser.java b/src/main/java/lotto/domain/LottoNumberParser.java similarity index 87% rename from src/main/java/lotto/utils/LottoNumberParser.java rename to src/main/java/lotto/domain/LottoNumberParser.java index 461ffb7ea0..b9c571138a 100644 --- a/src/main/java/lotto/utils/LottoNumberParser.java +++ b/src/main/java/lotto/domain/LottoNumberParser.java @@ -1,8 +1,7 @@ -package lotto.utils; +package lotto.domain; import java.util.Arrays; import java.util.List; -import lotto.domain.LottoNumber; public class LottoNumberParser { private static final String DELIMITER = ","; diff --git a/src/main/java/lotto/domain/PurchasedLottos.java b/src/main/java/lotto/domain/Lottos.java similarity index 63% rename from src/main/java/lotto/domain/PurchasedLottos.java rename to src/main/java/lotto/domain/Lottos.java index 5c6a176950..391c8849b1 100644 --- a/src/main/java/lotto/domain/PurchasedLottos.java +++ b/src/main/java/lotto/domain/Lottos.java @@ -1,14 +1,15 @@ package lotto.domain; +import java.util.ArrayList; import java.util.List; -public record PurchasedLottos(List values) { +public record Lottos(List values) { - public PurchasedLottos(Lotto... inputs) { + public Lottos(Lotto... inputs) { this(List.of(inputs)); } - public PurchasedLottos { + public Lottos { validateNotBlank(values); } @@ -18,6 +19,14 @@ private void validateNotBlank(List inputs) { } } + public Lottos merge(Lottos other) { + List merged = new ArrayList<>(this.values); + + merged.addAll(other.values); + + return new Lottos(merged); + } + public LottoResult result(WinningLotto winningLotto) { LottoResult result = new LottoResult(); @@ -28,11 +37,7 @@ public LottoResult result(WinningLotto winningLotto) { return result; } - public String purchaseCountForDisplay() { - return "%d개를 구매했습니다.".formatted(size()); - } - - private int size() { - return values.size(); + public int size() { + return values().size(); } } diff --git a/src/main/java/lotto/domain/LottosGenerator.java b/src/main/java/lotto/domain/LottosGenerator.java new file mode 100644 index 0000000000..8e4d0e273d --- /dev/null +++ b/src/main/java/lotto/domain/LottosGenerator.java @@ -0,0 +1,6 @@ +package lotto.domain; + +@FunctionalInterface +public interface LottosGenerator { + Lottos generate(); +} diff --git a/src/main/java/lotto/domain/ManualBasedLottoGenerator.java b/src/main/java/lotto/domain/ManualBasedLottoGenerator.java new file mode 100644 index 0000000000..d02cf40583 --- /dev/null +++ b/src/main/java/lotto/domain/ManualBasedLottoGenerator.java @@ -0,0 +1,26 @@ +package lotto.domain; + +import java.util.List; + +public class ManualBasedLottoGenerator implements LottosGenerator { + private final List manualInputs; + private final LottoNumberParser parser; + + public ManualBasedLottoGenerator(List manualInputs) { + this(manualInputs, new LottoNumberParser()); + } + + private ManualBasedLottoGenerator(List manualInputs, LottoNumberParser parser) { + this.manualInputs = manualInputs; + this.parser = parser; + } + + @Override + public Lottos generate() { + return new Lottos(generateLottos(manualInputs)); + } + + private List generateLottos(List inputs) { + return inputs.stream().map(parser::parse).map(Lotto::new).toList(); + } +} diff --git a/src/main/java/lotto/domain/WinningLotto.java b/src/main/java/lotto/domain/WinningLotto.java index 475b815747..581a273eb3 100644 --- a/src/main/java/lotto/domain/WinningLotto.java +++ b/src/main/java/lotto/domain/WinningLotto.java @@ -1,13 +1,7 @@ package lotto.domain; -import java.util.List; - public record WinningLotto(Lotto lotto, LottoNumber bonus) { - public WinningLotto(List numbers, String bonus) { - this(new Lotto(numbers), LottoNumber.of(bonus)); - } - public WinningLotto(Lotto lotto, int bonus) { this(lotto, LottoNumber.of(bonus)); } diff --git a/src/main/java/lotto/view/InputView.java b/src/main/java/lotto/view/InputView.java index 6a1b581352..2af7bdc8bb 100644 --- a/src/main/java/lotto/view/InputView.java +++ b/src/main/java/lotto/view/InputView.java @@ -1,6 +1,8 @@ package lotto.view; +import java.util.List; import java.util.Scanner; +import java.util.stream.IntStream; public class InputView { private static final Scanner scanner = new Scanner(System.in); @@ -11,6 +13,18 @@ public static String readPurchaseAmount() { return scanner.nextLine(); } + public static String readManualLottoCount() { + System.out.println("수동으로 구매할 로또 수를 입력해 주세요."); + + return scanner.nextLine(); + } + + public static List readManualLottoNumbers(int count) { + System.out.println("수동으로 구매할 번호를 입력해 주세요."); + + return IntStream.range(0, count).mapToObj(i -> scanner.nextLine()).toList(); + } + public static String readWinningNumbers() { System.out.println("지난 주 당첨 번호를 입력해 주세요."); diff --git a/src/main/java/lotto/view/ResultView.java b/src/main/java/lotto/view/ResultView.java index bd6c06e391..21b1ea86b7 100644 --- a/src/main/java/lotto/view/ResultView.java +++ b/src/main/java/lotto/view/ResultView.java @@ -4,11 +4,11 @@ public class ResultView { - public static void printPurchaseCount(PurchasedLottos purchased) { - System.out.println(purchased.purchaseCountForDisplay()); + public static void printPurchaseCount(LottoCount manualCount, LottoCount auto) { + System.out.printf("수동으로 %d장, 자동으로 %d개를 구매했습니다.%n", manualCount.value(), auto.value()); } - public static void printPurchasedLottos(PurchasedLottos purchased) { + public static void printPurchasedLottos(Lottos purchased) { for (Lotto lottoV2 : purchased.values()) { System.out.println(lottoV2.sortedValuesForDisplay()); } diff --git a/src/test/java/lotto/utils/AutoBasedLottoGeneratorTest.java b/src/test/java/lotto/domain/AutoBasedLottoGeneratorTest.java similarity index 71% rename from src/test/java/lotto/utils/AutoBasedLottoGeneratorTest.java rename to src/test/java/lotto/domain/AutoBasedLottoGeneratorTest.java index 1a6f8e25b9..557d6aced3 100644 --- a/src/test/java/lotto/utils/AutoBasedLottoGeneratorTest.java +++ b/src/test/java/lotto/domain/AutoBasedLottoGeneratorTest.java @@ -1,8 +1,7 @@ -package lotto.utils; +package lotto.domain; import static org.assertj.core.api.Assertions.*; -import lotto.domain.LottoCount; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; @@ -12,6 +11,7 @@ class AutoBasedLottoGeneratorTest { @Test void generate_지정개수_생성() { - assertThat(new AutoBasedLottoGenerator().generate(new LottoCount(5))).hasSize(5); + assertThat(new AutoBasedLottoGenerator(new LottoCount(5)).generate().size()) + .isEqualTo(5); } } diff --git a/src/test/java/lotto/domain/LottoCountTest.java b/src/test/java/lotto/domain/LottoCountTest.java index 3454ca0b29..da97fd7e85 100644 --- a/src/test/java/lotto/domain/LottoCountTest.java +++ b/src/test/java/lotto/domain/LottoCountTest.java @@ -5,19 +5,60 @@ import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; 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.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class LottoCountTest { + @ParameterizedTest(name = "입력값:{0}") + @ValueSource(ints = {0, 5}) + void 생성자_정상값_생성성공(int input) { + assertThatCode(() -> new LottoCount(input)).doesNotThrowAnyException(); + } + + @ParameterizedTest(name = "빈값:{0}") + @NullAndEmptySource + @ValueSource(strings = {" "}) + void 생성자_빈문자열_예외발생(String input) { + assertThatThrownBy(() -> new LottoCount(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("구매 개수는 필수입니다."); + } + + @Test + void 생성자_음수입력_예외발생() { + assertThatThrownBy(() -> new LottoCount(-1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("구매 개수는 0이상이어야 합니다."); + } + + @ParameterizedTest(name = "원본:{0} - 차감:{1} = 결과:{2}") + @CsvSource({"10, 3, 7", "5, 5, 0"}) + void subtract_정상값_차감(int original, int subtrahend, int expected) { + assertThat(new LottoCount(original).subtract(new LottoCount(subtrahend))) + .isEqualTo(new LottoCount(expected)); + } + + @Test + void subtract_초과값_예외발생() { + assertThatThrownBy(() -> new LottoCount(3).subtract(new LottoCount(5))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("차감할 수 없습니다."); + } + @Test - void 생성자_정상값_생성성공() { - assertThatCode(() -> new LottoCount(1)).doesNotThrowAnyException(); + void validateSubtractable_정상값_예외없음() { + assertThatCode(() -> new LottoCount(10).validateSubtractable(new LottoCount(5))) + .doesNotThrowAnyException(); } @Test - void 생성자_1미만입력_예외발생() { - assertThatThrownBy(() -> new LottoCount(0)) + void validateSubtractable_초과값_예외발생() { + assertThatThrownBy(() -> new LottoCount(3).validateSubtractable(new LottoCount(5))) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("로또 구매 개수는 1개 이상이어야 합니다."); + .hasMessage("차감할 수 없습니다."); } } diff --git a/src/test/java/lotto/utils/LottoNumberParserTest.java b/src/test/java/lotto/domain/LottoNumberParserTest.java similarity index 92% rename from src/test/java/lotto/utils/LottoNumberParserTest.java rename to src/test/java/lotto/domain/LottoNumberParserTest.java index df9cf33823..99b70c55e7 100644 --- a/src/test/java/lotto/utils/LottoNumberParserTest.java +++ b/src/test/java/lotto/domain/LottoNumberParserTest.java @@ -1,10 +1,9 @@ -package lotto.utils; +package lotto.domain; import static org.assertj.core.api.Assertions.*; import java.util.Arrays; import java.util.List; -import lotto.domain.LottoNumber; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; diff --git a/src/test/java/lotto/domain/PurchasedLottosTest.java b/src/test/java/lotto/domain/LottosTest.java similarity index 63% rename from src/test/java/lotto/domain/PurchasedLottosTest.java rename to src/test/java/lotto/domain/LottosTest.java index 688a67a292..123728048d 100644 --- a/src/test/java/lotto/domain/PurchasedLottosTest.java +++ b/src/test/java/lotto/domain/LottosTest.java @@ -10,25 +10,28 @@ import org.junit.jupiter.params.provider.NullAndEmptySource; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -class PurchasedLottosTest { +class LottosTest { @Test void 생성자_정상입력_생성성공() { - assertThatCode(() -> new PurchasedLottos(new Lotto(1, 2, 3, 4, 5, 6))).doesNotThrowAnyException(); + assertThatCode(() -> new Lottos(new Lotto(1, 2, 3, 4, 5, 6))).doesNotThrowAnyException(); } @ParameterizedTest(name = "입력:{0}") @NullAndEmptySource void 생성자_빈값입력_예외발생(List inputs) { - assertThatThrownBy(() -> new PurchasedLottos(inputs)) + assertThatThrownBy(() -> new Lottos(inputs)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("구매한 로또는 1개 이상이어야 합니다."); } @Test - void purchaseCountForDisplay_구매개수_표시() { - PurchasedLottos purchased = new PurchasedLottos(new Lotto(1, 2, 3, 4, 5, 6)); + void merge_두_로또_목록을_합친다() { + Lottos first = new Lottos(new Lotto(1, 2, 3, 4, 5, 6)); + Lottos second = new Lottos(new Lotto(7, 8, 9, 10, 11, 12)); - assertThat(purchased.purchaseCountForDisplay()).isEqualTo("1개를 구매했습니다."); + Lottos merged = first.merge(second); + + assertThat(merged.size()).isEqualTo(2); } } diff --git a/src/test/java/lotto/domain/ManualBasedLottoGeneratorTest.java b/src/test/java/lotto/domain/ManualBasedLottoGeneratorTest.java new file mode 100644 index 0000000000..ef520c17f0 --- /dev/null +++ b/src/test/java/lotto/domain/ManualBasedLottoGeneratorTest.java @@ -0,0 +1,18 @@ +package lotto.domain; + +import static org.assertj.core.api.Assertions.*; + +import java.util.List; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class ManualBasedLottoGeneratorTest { + + @Test + void generate_문자열목록_생성() { + assertThat(new ManualBasedLottoGenerator(List.of("1, 2, 3, 4, 5, 6", "7, 8, 9, 10, 11, 12")).generate()) + .isEqualTo(new Lottos(List.of(new Lotto(1, 2, 3, 4, 5, 6), new Lotto(7, 8, 9, 10, 11, 12)))); + } +}