diff --git a/README.md b/README.md index 4fc0ae874..78e748504 100644 --- a/README.md +++ b/README.md @@ -1 +1,156 @@ # kotlin-lotto-precourse + +# 기능 구현 목록 +### 1. 입력 +- [x] 로또 구입 금액을 입력받는다. + - [x] [예외] 가격이 숫자가 아닌 경우. + - [x] [예외] 가격이 1000원 미만인 경우. + +- [x] 당첨 번호를 입력받는다. + - [x] [예외] 문자인 경우. + - [x] [예외] 1~45사이의 숫자가 아닌 경우. + - [x] [예외] 숫자가 중복인 경우. + - [x] [예외] 6개의 숫자가 아닌 경우. + +- [x] 보너스 번호를 입력받는다. + - [x] [예외] 가격이 숫자가 아닌 경우. + - [x] [예외] 1~45사이의 숫자가 아닌 경우. + - [x] [예외] 당첨번호와 중복될 경우 + +- [x] 사용자가 잘못된 값을 입력할 경우 + - [x] `IllegalArgumentException`을 발생시킨다. + - [x] "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다. + - [x] `Exception`이 아닌 `IllegalArgumentException`, `IllegalStateException` 등과 같은 명확한 유형을 처리한다. + +### 2. 로또 발행 + +- [x] 로또를 발행한다. + - [x] 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다. + - [x] 오름차순으로 정렬한다. + - [x] 구입 금액에 해당하는 만큼 로또를 발행한다. + - [x] 로또 1장의 가격은 1,000원이다. + +- [x] 로또가 알맞은 형식인지 검사한다. + - [x] [예외] 1~45사이의 숫자가 아닌 경우. + - [x] [예외] 숫자가 중복인 경우. + - [x] [예외] 6개의 숫자가 아닌 경우. + - [x] [예외] 오름차순이 아닌 경우. + +### 3. 당첨 내역 저장 + +- [x] 당첨 여부를 비교한다. + - [x] 로또 리스트에서 로또 하나씩 사용자가 구매한 로또 번호와 당첨 번호를 비교한다. + - [x] 몇등을 했는지 당첨 내역을 구한다. + +- [x] 수익률을 구한다. + - [x] 당첨 내역을 토대로 수익을 구한다. + +### 4. 출력 +- [x] n개일치가 몇 번 있는지 출력한다. +- [x] 수익률을 출력한다. + +# 입출력 요구 사항 + +## 입력 + +- 로또 구입 금액을 입력 받는다. 구입 금액은 1,000원 단위로 입력 받으며 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다. + +`14000` + +- 당첨 번호를 입력 받는다. 번호는 쉼표(,)를 기준으로 구분한다. + +`1,2,3,4,5,6` + +- 보너스 번호를 입력 받는다. + +`7` + +## 출력 + +- 발행한 로또 수량 및 번호를 출력한다. + - 로또 번호는 오름차순으로 정렬하여 보여준다. + +``` +8개를 구매했습니다. + [8, 21, 23, 41, 42, 43] + [3, 5, 11, 16, 32, 38] + [7, 11, 16, 35, 36, 44] + [1, 8, 11, 31, 41, 42] + [13, 14, 16, 38, 42, 45] + [7, 11, 30, 40, 42, 43] + [2, 13, 22, 32, 38, 45] + [1, 3, 5, 14, 22, 45] +``` + +- 당첨 내역을 출력한다. + +``` +3개 일치 (5,000원) - 1개 +4개 일치 (50,000원) - 0개 +5개 일치 (1,500,000원) - 0개 +5개 일치, 보너스 볼 일치 (30,000,000원) - 0개 +6개 일치 (2,000,000,000원) - 0개 +``` + +- 수익률을 출력한다. + - 수익률은 소수점 둘째 자리에서 반올림한다. (ex. 100.0%, 51.5%, 1,000,000.0%) + - `총 수익률은 62.5%입니다.` + +- 예외 상황 시 에러 문구를 출력해야 한다. + - 단, 에러 문구는 "[ERROR]"로 시작해야 한다. + `[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.` + +# 프로그래밍 요구 사항 1 + +- Kotlin 1.9.24에서 실행 가능해야 한다. +- Java 코드가 아닌 Kotlin 코드로만 구현해야 한다. +- 프로그램 실행의 시작점은 Application의 main()이다. +- build.gradle.kts 파일은 변경할 수 없으며, 제공된 라이브러리 이외의 외부 라이브러리는 사용하지 않는다. +- 프로그램 종료 시 System.exit() 또는 exitProcess()를 호출하지 않는다. +- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 등의 이름을 바꾸거나 이동하지 않는다. +- 코틀린 코드 컨벤션을 지키면서 프로그래밍한다. +- 기본적으로 Kotlin Style Guide를 원칙으로 한다. + +## 프로그래밍 요구 사항 2 + +- [x] indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다. + - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. + - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. +- [x] 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라. + +- JUnit 5와 AssertJ를 이용하여 정리한 기능 목록이 정상적으로 작동하는지 테스트 코드로 확인한다. + - 테스트 도구 사용법이 익숙하지 않다면 아래 문서를 참고하여 학습한 후 테스트를 구현한다. + ``` + JUnit 5 User Guide + AssertJ User Guide + AssertJ Exception Assertions + Guide to JUnit 5 Parameterized Tests + ``` + +## 프로그래밍 요구 사항 3 + +- [x] 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다. +- [x] 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다. +- [x] else를 지양한다. + - 때로는 if/else, when문을 사용하는 것이 더 깔끔해 보일 수 있다. 어느 경우에 쓰는 것이 적절할지 스스로 고민해 본다. + - 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다. +- [x] Enum 클래스를 적용하여 프로그램을 구현한다. +- [x] 구현한 기능에 대한 단위 테스트를 작성한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다. + - 단위 테스트 작성이 익숙하지 않다면 LottoTest를 참고하여 학습한 후 테스트를 작성한다. + +# 피드백 + +- [x] 기능 목록을 재검토한다. + - [x] 기능 목록을 작성할 때 클래스 설계와 구현, 메서드 설계와 구현 등은 포함하지 않는다. + - [x] 예외상황도 함께 정리한다. +- [x] 기능 목록을 업데이트한다. 기능을 구현하면서 문서를 지속적으로 업데이트한다. +- [X] **문자열이나 숫자 값을 하드 코딩하지 않는다. 상수를 정의하고 의미있는 이름을 부여하여 해당 값이 어떤 역할을 하는지 명확히 드러낸다.** +- [x] 구현 순서도 코딩 컨벤션이다. + - [x] 프로퍼티, init블록, 부 생성자, 메서드, 동반 객체 순으로 작성한다. +- [x] 변수 이름에 자료형은 사용하지 않는다. 변수 이름은 의미를 명확히 드러낼 수 있도록 한다. +- [x] 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다. (회고때 포함) + - [x] 테스트 작성 과정을 통해 구현한 기능의 문제를 빠르게 발견할 수 있을 뿐만 아니라, 코드의 구조와 의도를 명확히 이해하는 데도 도움을 받을 수 있다. 학습 도구로도 활용할 수 있는데, 수 많은 + 테스트의 장점 중 본인이 가장 공감하는 작성 이유를 작성해 본다. +- [x] 처음부터 큰 단위 테스트를 만들지 않는다. → 테스트 주도 개발을 하자 + - [x] 작은 단위 테스트 : 무작위 값이 4 이상이면 자동차가 전진한다. + - [x] 큰 단위 테스트 : 자동차 경주 게임을 시작하여, 사용자가 이름과 진행횟수를 입력하고, 게임을진행한 후 결과를 확인한다. \ No newline at end of file diff --git a/src/main/kotlin/lotto/Application.kt b/src/main/kotlin/lotto/Application.kt index 151821c9c..b096585c6 100644 --- a/src/main/kotlin/lotto/Application.kt +++ b/src/main/kotlin/lotto/Application.kt @@ -1,5 +1,13 @@ package lotto +import lotto.controller.LottoDraw +import lotto.view.InputView +import lotto.view.OutputView + fun main() { // TODO: 프로그램 구현 + val inputView = InputView() + val outputView = OutputView() + val lottoDraw = LottoDraw() + lottoDraw.run(inputView, outputView) } diff --git a/src/main/kotlin/lotto/Lotto.kt b/src/main/kotlin/lotto/Lotto.kt deleted file mode 100644 index b97abc385..000000000 --- a/src/main/kotlin/lotto/Lotto.kt +++ /dev/null @@ -1,9 +0,0 @@ -package lotto - -class Lotto(private val numbers: List) { - init { - require(numbers.size == 6) { "[ERROR] 로또 번호는 6개여야 합니다." } - } - - // TODO: 추가 기능 구현 -} diff --git a/src/main/kotlin/lotto/controller/LottoDraw.kt b/src/main/kotlin/lotto/controller/LottoDraw.kt new file mode 100644 index 000000000..aa3a4f7a2 --- /dev/null +++ b/src/main/kotlin/lotto/controller/LottoDraw.kt @@ -0,0 +1,26 @@ +package lotto.controller + +import lotto.model.Lotto +import lotto.model.Store +import lotto.util.ErrorMessages +import lotto.view.InputView +import lotto.view.OutputView + +class LottoDraw { + fun run(inputView: InputView, outputView: OutputView) { + val price = inputView.getPrice() + + val store = Store() + val lottos = store.buyLotto(price) + + val myLotto = inputView.getMyLotto() + val myBonus = inputView.getBonusNumber(myLotto) + + outputView.purchasedMessage(store.numberOfLottoPurchased) + outputView.purchasedLotto(lottos) + + val ranking = LottoResultChecker.checkWinningStatus(lottos, myLotto, myBonus) + val profitRatio = LottoResultChecker.calculateProfitRate(price, ranking) + outputView.resultStatistics(ranking, profitRatio) + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/controller/LottoResultChecker.kt b/src/main/kotlin/lotto/controller/LottoResultChecker.kt new file mode 100644 index 000000000..ac1fbb4c8 --- /dev/null +++ b/src/main/kotlin/lotto/controller/LottoResultChecker.kt @@ -0,0 +1,45 @@ +package lotto.controller + +import lotto.model.Lotto + +object LottoResultChecker { + + fun checkWinningStatus(lottos: List, myLotto: Lotto, myBonus: Int): List { + val ranking = MutableList(6) { 0 } + + for (lotto in lottos) { + val (duplicateCount, isBonus) = compareLotto(lotto, myLotto, myBonus) + when (duplicateCount) { + 3 -> ranking[5]++ + 4 -> ranking[4]++ + 5 -> if (isBonus) ranking[2]++ else ranking[3]++ + 6 -> ranking[1]++ + } + } + return ranking + } + + fun compareLotto(purchasedLotto: Lotto, myLotto: Lotto, myBonus: Int): Pair { + val sameValueOfLotto = purchasedLotto.getNumbers().intersect(myLotto.getNumbers().toSet()) + val duplicateCount = sameValueOfLotto.size + val isBonus = myBonus in purchasedLotto.getNumbers() + + return Pair(duplicateCount, isBonus) + } + + fun calculateProfitRate(money: Int, ranking: List): Double { + val profit = RankPerPrice.entries.toTypedArray().sumOf { rank -> + (ranking.getOrNull(rank.ranked) ?: 0) * rank.price + } + val profitRate = profit.toDouble() / money + return profitRate * 100 + } + + enum class RankPerPrice(val ranked: Int, val price: Int) { + FIRST(1, 2000000000), + SECOND(2, 30000000), + THIRD(3, 1500000), + FORTH(4, 50000), + FIFTH(5, 5000); + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/model/Lotto.kt b/src/main/kotlin/lotto/model/Lotto.kt new file mode 100644 index 000000000..366f5d5b1 --- /dev/null +++ b/src/main/kotlin/lotto/model/Lotto.kt @@ -0,0 +1,20 @@ +package lotto.model + +import lotto.util.ErrorMessages + +class Lotto(private val numbers: List) { + init { + require(numbers.size == 6) { ErrorMessages.INVALID_NUMBER_SIZE } + require(numbers.distinct().size == numbers.size) { ErrorMessages.DUPLICATE_NUMBERS } + require(numbers.all { it in 1..45 }) { ErrorMessages.OUT_OF_RANGE } + require(numbers == numbers.sorted()) { ErrorMessages.NOT_SORTED } + } + + fun getNumbers(): List { + return numbers + } + + override fun toString(): String { + return numbers.toString() + } +} diff --git a/src/main/kotlin/lotto/model/Store.kt b/src/main/kotlin/lotto/model/Store.kt new file mode 100644 index 000000000..7bbb1d80c --- /dev/null +++ b/src/main/kotlin/lotto/model/Store.kt @@ -0,0 +1,25 @@ +package lotto.model + +import camp.nextstep.edu.missionutils.Randoms + +class Store { + var numberOfLottoPurchased: Int = 0 + val purchasedLottos = mutableListOf() + + fun buyLotto(money: Int): List { + numberOfLottoPurchased = money / 1000 + repeat(numberOfLottoPurchased) { + purchasedLottos.add(generateLotto()) + } + return purchasedLottos + } + + fun generateLotto(): Lotto { + var numbers = Randoms.pickUniqueNumbersInRange(1, 45, 6) + while (numbers.distinct().size != numbers.size) { + numbers = Randoms.pickUniqueNumbersInRange(1, 45, 6) + } + val lotto = Lotto(numbers.sorted()) + return lotto + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/ErrorMessages.kt b/src/main/kotlin/lotto/util/ErrorMessages.kt new file mode 100644 index 000000000..33bd2cdfa --- /dev/null +++ b/src/main/kotlin/lotto/util/ErrorMessages.kt @@ -0,0 +1,14 @@ +package lotto.util + +object ErrorMessages { + const val INVALID_NUMBER_SIZE = "[ERROR] 로또 번호는 6개여야 합니다." + const val DUPLICATE_NUMBERS = "[ERROR] 로또 번호는 중복되지 않아야 합니다." + const val OUT_OF_RANGE = "[ERROR] 모든 로또 번호는 1부터 45 사이여야 합니다." + const val NOT_SORTED = "[ERROR] 로또 번호는 오름차순으로 정렬되어 있어야 합니다." + const val NULL_PRICE = "[ERROR] 구입금액을 입력해 주세요." + const val NOT_INT = "[ERROR] 입력이 숫자가 아닙니다." + const val MINIMUM_PRICE = "[ERROR] 로또 한 개의 가격은 1000원 이상이어야 합니다" + const val NULL_LOTTO_NUMBER = "[ERROR] 당첨 번호를 입력해 주세요." + const val NULL_BONUS_NUMBER = "[ERROR] 보너스 번호를 입력해 주세요." + const val DUPLICATED_BONUS = "[ERROR] 보너스 번호는 로또 번호와 중복될 수 없습니다." +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/util/InputValidate.kt b/src/main/kotlin/lotto/util/InputValidate.kt new file mode 100644 index 000000000..d9a9fe563 --- /dev/null +++ b/src/main/kotlin/lotto/util/InputValidate.kt @@ -0,0 +1,18 @@ +package lotto.util + +import lotto.model.Lotto + +object InputValidate { + fun checkPrice(input: String, price: Int?) { + require(input != "") { ErrorMessages.NULL_PRICE } + require(price != null) { ErrorMessages.NOT_INT } + require(price >= 1000) { ErrorMessages.MINIMUM_PRICE } + } + + fun checkMyBonus(input: String, bonusNumber: Int?, myLotto: Lotto) { + require(input != "") { ErrorMessages.NULL_BONUS_NUMBER } + require(bonusNumber != null) { ErrorMessages.NOT_INT } + require(bonusNumber in 1..45) { ErrorMessages.OUT_OF_RANGE } + require(bonusNumber !in myLotto.getNumbers()) { ErrorMessages.DUPLICATED_BONUS } + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/InputView.kt b/src/main/kotlin/lotto/view/InputView.kt new file mode 100644 index 000000000..19da8f4d6 --- /dev/null +++ b/src/main/kotlin/lotto/view/InputView.kt @@ -0,0 +1,62 @@ +package lotto.view + +import camp.nextstep.edu.missionutils.Console +import lotto.model.Lotto +import lotto.util.ErrorMessages +import lotto.util.InputValidate + +class InputView { + fun getPrice(): Int { + println(GET_PRICE) + while (true) { + val input = Console.readLine() + try { + val price = input.toIntOrNull() + InputValidate.checkPrice(input, price) + return price ?: 0 + } catch (e: IllegalArgumentException) { + println(e.message) + } + } + } + + fun getMyLotto(): Lotto { + println(GET_MY_LOTTO) + while (true) { + try { + val input = Console.readLine() + require(input != "") { ErrorMessages.NULL_LOTTO_NUMBER } + + val lottoNumber = input.split(",").map { it.trim().toIntOrNull() } + val notNullLottoNumber: List = lottoNumber.filterNotNull().sorted() + require(lottoNumber.all { it != null }) { ErrorMessages.NOT_INT } + + return Lotto(notNullLottoNumber) + } catch (e: IllegalArgumentException) { + println(e.message) + } + } + } + + fun getBonusNumber(myLotto: Lotto): Int { + println(GET_BONUS_NUMBER) + while (true) { + try { + val input = Console.readLine() + val bonusNumber = input.toIntOrNull() + + InputValidate.checkMyBonus(input, bonusNumber, myLotto) + + return bonusNumber ?: 0 + } catch (e: IllegalArgumentException) { + println(e.message) + } + } + } + + companion object{ + const val GET_PRICE = "구입금액을 입력해 주세요." + const val GET_MY_LOTTO = "당첨 번호를 입력해 주세요." + const val GET_BONUS_NUMBER = "보너스 번호를 입력해 주세요." + } +} \ No newline at end of file diff --git a/src/main/kotlin/lotto/view/OutputView.kt b/src/main/kotlin/lotto/view/OutputView.kt new file mode 100644 index 000000000..69bf04886 --- /dev/null +++ b/src/main/kotlin/lotto/view/OutputView.kt @@ -0,0 +1,28 @@ +package lotto.view + +import lotto.model.Lotto + +class OutputView { + fun purchasedMessage(num: Int) { + println("${num}개를 구매했습니다.") + } + + fun purchasedLotto(lottos: List) { + for (lotto in lottos) { + println(lotto) + } + } + + fun resultStatistics(ranking: List, profitRatio: Double) { + println( + "당첨 통계\n" + + "---" + ) + println("${3}개 일치 (5,000원) - ${ranking[5]}개\n" + + "${4}개 일치 (50,000원) - ${ranking[4]}개\n" + + "${5}개 일치 (1,500,000원) - ${ranking[3]}개\n" + + "${5}개 일치, 보너스 볼 일치 (30,000,000원) - ${ranking[2]}개\n" + + "${6}개 일치 (2,000,000,000원) - ${ranking[1]}개\n") + println("총 수익률은 ${profitRatio}%입니다.") + } +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/LottoTest.kt b/src/test/kotlin/lotto/LottoTest.kt deleted file mode 100644 index 122fae572..000000000 --- a/src/test/kotlin/lotto/LottoTest.kt +++ /dev/null @@ -1,23 +0,0 @@ -package lotto - -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows - -class LottoTest { - @Test - fun `로또 번호의 개수가 6개가 넘어가면 예외가 발생한다`() { - assertThrows { - Lotto(listOf(1, 2, 3, 4, 5, 6, 7)) - } - } - - // TODO: 테스트가 통과하도록 프로덕션 코드 구현 - @Test - fun `로또 번호에 중복된 숫자가 있으면 예외가 발생한다`() { - assertThrows { - Lotto(listOf(1, 2, 3, 4, 5, 5)) - } - } - - // TODO: 추가 기능 구현에 따른 테스트 코드 작성 -} diff --git a/src/test/kotlin/lotto/controller/LottoDrawTest.kt b/src/test/kotlin/lotto/controller/LottoDrawTest.kt new file mode 100644 index 000000000..65cb680e0 --- /dev/null +++ b/src/test/kotlin/lotto/controller/LottoDrawTest.kt @@ -0,0 +1,12 @@ +package lotto.controller + +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +class LottoDrawTest { + + @Test + fun `run 함수가 `() { + } +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/controller/LottoResultCheckerTest.kt b/src/test/kotlin/lotto/controller/LottoResultCheckerTest.kt new file mode 100644 index 000000000..b8e4d66af --- /dev/null +++ b/src/test/kotlin/lotto/controller/LottoResultCheckerTest.kt @@ -0,0 +1,43 @@ +package lotto.controller + +import lotto.model.Lotto +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertEquals + +class LottoResultCheckerTest { + @Test + fun `checkWinningStatus함수가 의도한 값을 반환하는지 확인`() { + val lottos = listOf( + Lotto(listOf(1, 2, 3, 4, 5, 6)), // 1등 + Lotto(listOf(1, 2, 3, 4, 5, 7)), // 2등 (보너스 포함) + Lotto(listOf(1, 2, 3, 4, 5, 8)), // 3등 + Lotto(listOf(1, 2, 3, 4, 9, 10)), // 4등 + Lotto(listOf(1, 2, 3, 11, 12, 13)) // 5등 + ) + + val myLotto = Lotto(listOf(1, 2, 3, 4, 5, 6)) + val myBonus = 7 + + val ranking = LottoResultChecker.checkWinningStatus(lottos, myLotto, myBonus) + + assertEquals(listOf(0, 1, 1, 1, 1, 1), ranking) + } + + @Test + fun `compareLotto 겹치는 개수 정상적으로 계산하는지 확인`() { + val lotto = Lotto(listOf(1, 2, 3, 4, 5, 6)) + val myLotto = Lotto(listOf(1, 2, 3, 4, 5, 9)) + val myBonus = 6 + val (duplicateCount, isBonus) = LottoResultChecker.compareLotto(lotto, myLotto, myBonus) + assertEquals(duplicateCount, 5) + assertEquals(isBonus, true) + } + + @Test + fun `수익률 정상적으로 계산하는지 확인`() { + val ranking = listOf(0, 1, 1, 1, 1, 1) + val money = 5000 + val profitRate = LottoResultChecker.calculateProfitRate(money, ranking) + assertEquals(profitRate, (2000000000 + 30000000 + 1500000 + 50000 + 5000) / money.toDouble()) + } +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/model/LottoTest.kt b/src/test/kotlin/lotto/model/LottoTest.kt new file mode 100644 index 000000000..2d890fba0 --- /dev/null +++ b/src/test/kotlin/lotto/model/LottoTest.kt @@ -0,0 +1,59 @@ +package lotto.model + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class LottoTest { + @Test + fun `로또 안의 숫자가 1~45사이의 숫자가 아니면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(-1, 2, 3, 4, 5, 6)) + } + assertThrows { + Lotto(listOf(1, 2, 4, 5, 6, 333)) + } + } + + @Test + fun `로또 번호의 개수가 6개가 넘어가면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(1, 2, 3, 4, 5, 6, 7)) + } + } + + @Test + fun `로또 번호의 개수가 6개 미만이면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(1, 2, 3, 4, 5)) + } + } + + @Test + fun `로또 번호에 중복된 숫자가 있으면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(1, 2, 3, 4, 5, 5)) + } + } + + @Test + fun `로또 번호가 오름차순이 아니면 예외가 발생한다`() { + assertThrows { + Lotto(listOf(1, 3, 2, 4, 5, 6)) + } + } + + // TODO: 추가 기능 구현에 따른 테스트 코드 작성 + @Test + fun `getNumbers 함수에서 list가 정상 반환되는지 확인`() { + val lotto = Lotto(listOf(1, 2, 3, 4, 5, 6)) + assertEquals(lotto.getNumbers(), listOf(1, 2, 3, 4, 5, 6)) + } + + @Test + fun `toString 함수가 해쉬코드가 아닌 값을 반환하는지 확인`() { + val lotto = Lotto(listOf(1, 2, 3, 4, 5, 6)) + assertEquals(lotto.toString(), "[1, 2, 3, 4, 5, 6]") + + } +} diff --git a/src/test/kotlin/lotto/model/StoreTest.kt b/src/test/kotlin/lotto/model/StoreTest.kt new file mode 100644 index 000000000..1f7852886 --- /dev/null +++ b/src/test/kotlin/lotto/model/StoreTest.kt @@ -0,0 +1,22 @@ +package lotto.model + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Assertions.assertDoesNotThrow +import org.assertj.core.api.Assertions.assertThat + +class StoreTest { + val store = Store() + val lotto = store.generateLotto() + @Test + fun `생성한 로또가 예외를 발생시키지는 않는지 검사한다`() { + assertDoesNotThrow { + store.generateLotto() + } + } + + @Test + fun `2000원 냈을 때 로또 2개를 반환하는지 검사한다`() { + assertThat(store.buyLotto(2000)).hasSize(2) + } + +} \ No newline at end of file diff --git a/src/test/kotlin/lotto/util/InputValidateTest.kt b/src/test/kotlin/lotto/util/InputValidateTest.kt new file mode 100644 index 000000000..fe1cb2b20 --- /dev/null +++ b/src/test/kotlin/lotto/util/InputValidateTest.kt @@ -0,0 +1,64 @@ +package lotto.util + +import lotto.model.Lotto +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.assertThrows + +class InputValidateTest { + + @Test + fun `checkPrice 돈을 안내면 예외가 발생한다`() { + assertThrows { + InputValidate.checkPrice("", null) + } + } + + @Test + fun `checkPrice 문자를 입력하면 예외가 발생한다`() { + assertThrows { + InputValidate.checkPrice("text", null) + } + } + + @Test + fun `checkPrice 1000원보다 적은 돈을 내면 예외가 발생한다`() { + assertThrows { + InputValidate.checkPrice("900", 900) + } + } + + + @Test + fun `checkMyBonus 값을 입력하지 않으면 예외가 발생한다`() { + val lotto = Lotto(listOf(1,2,3,4,5,6)) + assertThrows { + InputValidate.checkMyBonus("", null, lotto) + } + } + + @Test + fun `checkMyBonus 문자를 입력하면 예외가 발생한다`() { + val lotto = Lotto(listOf(1,2,3,4,5,6)) + assertThrows { + InputValidate.checkMyBonus("text", null, lotto) + } + } + + @Test + fun `checkMyBonus 1과 45사이의 값이 아니면 예외가 발생한다`() { + val lotto = Lotto(listOf(1,2,3,4,5,6)) + assertThrows { + InputValidate.checkMyBonus("900", 900, lotto) + } + } + + @Test + fun `checkMyBonus 보너스 번호와 당첨번호가 겹치면 예외가 발생한다`() { + val lotto = Lotto(listOf(1,2,3,4,5,6)) + assertThrows { + InputValidate.checkMyBonus("3", 3, lotto) + } + } +} \ No newline at end of file