diff --git a/src/main/kotlin/lotto/LottoApplication.kt b/src/main/kotlin/lotto/LottoApplication.kt new file mode 100644 index 0000000000..c186e33f5d --- /dev/null +++ b/src/main/kotlin/lotto/LottoApplication.kt @@ -0,0 +1,7 @@ +package lotto + +import lotto.application.LottoController + +fun main() { + LottoController.start() +} diff --git a/src/main/kotlin/lotto/README.md b/src/main/kotlin/lotto/README.md new file mode 100644 index 0000000000..08c94c5272 --- /dev/null +++ b/src/main/kotlin/lotto/README.md @@ -0,0 +1,118 @@ +## 문자열 덧셈 계산기 + + +### 기능 요구사항 +- [v] 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다. +- [v] 로또 1장의 가격은 1000원이다. + +### 실행 결과 +``` +구입금액을 입력해 주세요. +14000 +14개를 구매했습니다. +[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] +[23, 25, 33, 36, 39, 41] +[1, 3, 5, 14, 22, 45] +[5, 9, 38, 41, 43, 44] +[2, 8, 9, 18, 19, 21] +[13, 14, 18, 21, 23, 35] +[17, 21, 29, 37, 42, 45] +[3, 8, 27, 30, 35, 44] + +지난 주 당첨 번호를 입력해 주세요. +1, 2, 3, 4, 5, 6 + +당첨 통계 +--------- +3개 일치 (5000원)- 1개 +4개 일치 (50000원)- 0개 +5개 일치 (1500000원)- 0개 +6개 일치 (2000000000원)- 0개 +총 수익률은 0.35입니다.(기준이 1이기 때문에 결과적으로 손해라는 의미임) +``` + +### 프로그래밍 요구 사항 +- [v] 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. 단, UI(System.out, System.in) 로직은 제외 +- [v] 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 구분한다. +- [v] UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다. +- [v] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다. + - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. + - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다. + +- [v] 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다. +- [v] 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다. +- [v] 기능을 구현하기 전에 README.md 파일에 구현할 기능 목록을 정리해 추가한다. +- [v] git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다. + +## 구현할 기능 목록 + +### View +- [v] InputView + - [v] 구입금액을 입력받는다 + - "구입금액을 입력해 주세요."라는 안내문구를 출력한다. + - [v] 지난 주 당첨 번호를 입력받는다 + - "지난 주 당첨 번호를 입력해 주세요."라는 안내문구를 출력한다. +- [v] Result View + - [v] 구입한 로또의 개수를 출력한다. + - [v] 구입한 로또의 번호를 출력한다. + - [v] 각각의 번호는 ","로 구분된다. + - [v] 로또 번호 Prefix는 '[', postfix는 ']' 를 사용한다. + - [v] 당첨 통계를 출력한다. + - [v] 3,4,5,6 개의 번호의 일치여부를 각각 출력한다. + - [v] 수익률을 표시한다. + +### Domain +- [v] lotto market + - [v] 금액을 입력받는다 + - [v] 숫자가 아니거나, 1000원보다 작거나, 음수이거나, 숫자가 아닐 경우 RuntimeExeption을 반환한다. + - [v] 구매 번호 만큼 로또를 생성한다. +- [v] lotto number generator + - 1부터 45까지의 숫자중 각기 다른 6개의 숫자를 발생시킨다. +- [v] Lotto + - [v] 6개의 각기 다른 번호를 가지고 있다. + - [v] 당첨 번호를 입력받아 매칭된 번호의 개수를 반환한다. +- [v] Lottos + - [v] lotto List의 콜렉션 기능을 담당한다. +- [v] WinningChecker + - [v] 당첨번호와 Lotto들을 입력받아 당첨여부를 판단한다 +- [v] YieldCalculator + - [v] 당첨 금액을 계산한다. + - [v] 수익률을 계산한다. +- [v] WinningRank + - [v] Enum으로 만든다. + - [v] 복권의 당첨개수와, 그에 따른 금액을 기술한다. + +### Service +- [v] lottoMarketService +- [v] lottoYieldService + +### Controller +- [v] LottoController + +### 설계 흐름 +#### 로또 구매 프로세스 +1. InputView: 구매 금액 입력. +2. LottoService: + 1. LottoMarket을 호출하여 구매 금액 검증 + 2. 로또 생성. + 2. 생성된 로또 리스트 반환. +4. ResultView + 1. 로또 구매 개수와 번호 출력. + +#### 당첨 및 수익률 계산 프로세스 +1. InputView: 지난주 당첨 번호 입력. +2. LottoWinningStatisticsService + 1. WinningChecker 호출하여 당첨 여부 판별. + 2. 수익률 계산. +3. ResultView: 수익률 출력. + + + + + diff --git a/src/main/kotlin/lotto/application/LottoController.kt b/src/main/kotlin/lotto/application/LottoController.kt new file mode 100644 index 0000000000..38e984e7de --- /dev/null +++ b/src/main/kotlin/lotto/application/LottoController.kt @@ -0,0 +1,18 @@ +package lotto.application + +import lotto.core.LottoMarket +import lotto.presentation.InputView +import lotto.presentation.ResultView + +object LottoController { + fun start() { + val purchaseAmount = InputView.inputPurchaseAmount() + val lottos = LottoMarket.purchase(purchaseAmount) + ResultView.printLottos(lottos) + + val winningNumbers = InputView.inputWinningNumbers() + val winningStatistics = LottoWinningStatisticsService.start(lottos, winningNumbers) + + ResultView.printWinningStatistics(winningStatistics) + } +} diff --git a/src/main/kotlin/lotto/application/LottoWinningStatisticsService.kt b/src/main/kotlin/lotto/application/LottoWinningStatisticsService.kt new file mode 100644 index 0000000000..a186621ad2 --- /dev/null +++ b/src/main/kotlin/lotto/application/LottoWinningStatisticsService.kt @@ -0,0 +1,18 @@ +package lotto.application + +import lotto.core.LottoWinningStatistics +import lotto.core.Lottos +import lotto.core.WinningNumbers +import lotto.core.YieldCalculator + +object LottoWinningStatisticsService { + fun start( + lottos: Lottos, + numbers: List, + ): LottoWinningStatistics { + val winningNumbers = WinningNumbers(numbers) + val winningRankCount = lottos.countWinningRanks(winningNumbers) + + return LottoWinningStatistics(winningRankCount, YieldCalculator.calculate(winningRankCount, lottos.size)) + } +} diff --git a/src/main/kotlin/lotto/core/Lotto.kt b/src/main/kotlin/lotto/core/Lotto.kt new file mode 100644 index 0000000000..2676164c29 --- /dev/null +++ b/src/main/kotlin/lotto/core/Lotto.kt @@ -0,0 +1,3 @@ +package lotto.core + +data class Lotto(val numbers: List) diff --git a/src/main/kotlin/lotto/core/LottoMarket.kt b/src/main/kotlin/lotto/core/LottoMarket.kt new file mode 100644 index 0000000000..7bc79e9f78 --- /dev/null +++ b/src/main/kotlin/lotto/core/LottoMarket.kt @@ -0,0 +1,25 @@ +package lotto.core + +import lotto.core.constant.LottoConstants + +object LottoMarket { + fun purchase(purchaseAmount: String): Lottos { + val purchasableCount = calculatePurchasableCount(purchaseAmount) + val lottoList = issueLotto(purchasableCount) + return Lottos(lottoList) + } + + private fun calculatePurchasableCount(purchaseAmount: String): Int { + val amount = purchaseAmount.toIntOrNull() ?: throw IllegalArgumentException("잘못된 금액이 입력되었습니다.") + return amount / LottoConstants.LOTTO_PRICE + } + + private fun issueLotto(count: Int): List { + return List(count) { Lotto(generateNumbers()) } + } + + private fun generateNumbers(): List = + (LottoConstants.LOTTO_NUMBER_MIN..LottoConstants.LOTTO_NUMBER_MAX).shuffled().take( + LottoConstants.LOTTO_NUMBER_COUNT, + ).sorted() +} diff --git a/src/main/kotlin/lotto/core/LottoWinningStatistics.kt b/src/main/kotlin/lotto/core/LottoWinningStatistics.kt new file mode 100644 index 0000000000..104a175d60 --- /dev/null +++ b/src/main/kotlin/lotto/core/LottoWinningStatistics.kt @@ -0,0 +1,3 @@ +package lotto.core + +data class LottoWinningStatistics(val winningRankCount: Map, val yieldRate: Float) diff --git a/src/main/kotlin/lotto/core/Lottos.kt b/src/main/kotlin/lotto/core/Lottos.kt new file mode 100644 index 0000000000..fc1dbce961 --- /dev/null +++ b/src/main/kotlin/lotto/core/Lottos.kt @@ -0,0 +1,16 @@ +package lotto.core + +class Lottos(private val lottos: List) : List by lottos { + fun countWinningRanks(winningNumbers: WinningNumbers): Map { + val results = this.map { checkWinningState(it, winningNumbers) } + + return results.groupingBy { it }.eachCount() + } + + private fun checkWinningState( + lotto: Lotto, + winningNumbers: WinningNumbers, + ): WinningRank { + return WinningRank.getWinningAmount(winningNumbers.countCommonNumbers(lotto)) + } +} diff --git a/src/main/kotlin/lotto/core/WinningNumbers.kt b/src/main/kotlin/lotto/core/WinningNumbers.kt new file mode 100644 index 0000000000..d721bef157 --- /dev/null +++ b/src/main/kotlin/lotto/core/WinningNumbers.kt @@ -0,0 +1,15 @@ +package lotto.core + +import lotto.core.constant.LottoConstants + +data class WinningNumbers(val winningNumbers: List) { + init { + if (winningNumbers.size != LottoConstants.LOTTO_NUMBER_COUNT) { + throw IllegalArgumentException("당첨 번호의 숫자가 잘못되었습니다.") + } + } + + fun countCommonNumbers(lotto: Lotto): Int { + return winningNumbers.filter { it in lotto.numbers }.size + } +} diff --git a/src/main/kotlin/lotto/core/WinningRank.kt b/src/main/kotlin/lotto/core/WinningRank.kt new file mode 100644 index 0000000000..6b1414e021 --- /dev/null +++ b/src/main/kotlin/lotto/core/WinningRank.kt @@ -0,0 +1,18 @@ +package lotto.core + +enum class WinningRank(val winningCount: Int, val winningAmount: Int) { + RANK0(0, 0), + RANK4(3, 5_000), + RANK3(4, 50_000), + RANK2(5, 1_500_000), + RANK1(6, 2_000_000_000), + ; + + companion object { + private val map = entries.associateBy(WinningRank::winningCount) + + fun getWinningAmount(winningCount: Int): WinningRank { + return map[winningCount] ?: RANK0 + } + } +} diff --git a/src/main/kotlin/lotto/core/YieldCalculator.kt b/src/main/kotlin/lotto/core/YieldCalculator.kt new file mode 100644 index 0000000000..2fe7b54b9f --- /dev/null +++ b/src/main/kotlin/lotto/core/YieldCalculator.kt @@ -0,0 +1,15 @@ +package lotto.core + +import lotto.core.constant.LottoConstants + +object YieldCalculator { + fun calculate( + winningRankCount: Map, + lottoCount: Int, + ): Float { + val totalBudget = lottoCount * LottoConstants.LOTTO_PRICE + val totalWinningAmount = winningRankCount.map { it.key.winningAmount * it.value }.sum() + + return totalWinningAmount.toFloat() / totalBudget + } +} diff --git a/src/main/kotlin/lotto/core/constant/LottoConstants.kt b/src/main/kotlin/lotto/core/constant/LottoConstants.kt new file mode 100644 index 0000000000..490214bd5d --- /dev/null +++ b/src/main/kotlin/lotto/core/constant/LottoConstants.kt @@ -0,0 +1,8 @@ +package lotto.core.constant + +object LottoConstants { + const val LOTTO_NUMBER_COUNT = 6 + const val LOTTO_NUMBER_MIN = 1 + const val LOTTO_NUMBER_MAX = 45 + const val LOTTO_PRICE = 1000 +} diff --git a/src/main/kotlin/lotto/presentation/InputView.kt b/src/main/kotlin/lotto/presentation/InputView.kt new file mode 100644 index 0000000000..35e79d56ef --- /dev/null +++ b/src/main/kotlin/lotto/presentation/InputView.kt @@ -0,0 +1,47 @@ +package lotto.presentation + +import lotto.core.constant.LottoConstants + +object InputView { + fun inputPurchaseAmount(): String { + println(GUIDE_INPUT_PURCHASE_AMOUNT) + + return readlnOrNull() ?: throw RuntimeException("잘못된 값이 입력되었습니다.") + } + + fun inputWinningNumbers(): List { + println(GUIDE_INPUT_LAST_WINNING_NUMBER) + + return splitNumbers(readlnOrNull() ?: throw RuntimeException("잘못된 값이 입력되었습니다.")) + } + + private fun splitNumbers(winningNumbers: String): List { + val numberList = winningNumbers.split(DELIMITER) + val numbers = transformNumbers(numberList) + checkInsideLottoNumber(numbers) + checkDuplicates(numbers) + return numbers + } + + private fun transformNumbers(numberList: List): List { + return numberList.map { number -> number.trim().toIntOrNull() ?: throw NumberFormatException("숫자가 아닙니다.") } + } + + private fun checkDuplicates(list: List) { + if (list.size != list.toSet().size) { + throw IllegalArgumentException("중복된 숫자가 있습니다.") + } + } + + private fun checkInsideLottoNumber(numbers: List) { + numbers.forEach { + if (it < LottoConstants.LOTTO_NUMBER_MIN || LottoConstants.LOTTO_NUMBER_MAX < it) { + throw IllegalArgumentException("로또 숫자의 범위를 넘어섰습니다.") + } + } + } + + private const val GUIDE_INPUT_PURCHASE_AMOUNT = "구입금액을 입력해 주세요." + private const val GUIDE_INPUT_LAST_WINNING_NUMBER = "지난 주 당첨 번호를 입력해 주세요." + private const val DELIMITER = "," +} diff --git a/src/main/kotlin/lotto/presentation/ResultView.kt b/src/main/kotlin/lotto/presentation/ResultView.kt new file mode 100644 index 0000000000..fa091562d6 --- /dev/null +++ b/src/main/kotlin/lotto/presentation/ResultView.kt @@ -0,0 +1,57 @@ +package lotto.presentation + +import lotto.core.LottoWinningStatistics +import lotto.core.Lottos +import lotto.core.WinningRank + +object ResultView { + fun printLottos(lottos: Lottos) { + val stringBuffer = StringBuffer() + + stringBuffer.append(lottos.size) + stringBuffer.append(STR_PURCHASED_COUNT) + stringBuffer.append(STR_NEW_LINE) + lottos.forEach { + stringBuffer.append(it.numbers.joinToString(",", "[", "]")) + stringBuffer.append(STR_NEW_LINE) + } + + println(stringBuffer.toString()) + } + + fun printWinningStatistics(winningStatistics: LottoWinningStatistics) { + val stringBuffer = StringBuffer() + stringBuffer.append(STR_WINNING_STATISTICS) + stringBuffer.append(STR_NEW_LINE) + stringBuffer.append(STR_SEPARATOR) + stringBuffer.append(STR_NEW_LINE) + + winningStatistics.winningRankCount.filter { (it.key != WinningRank.RANK0) } + .map { + stringBuffer.append(it.key.winningCount) + stringBuffer.append(STR_MATCH) + stringBuffer.append(it.key.winningAmount) + stringBuffer.append(STR_AMOUNT) + stringBuffer.append(it.value) + stringBuffer.append(STR_COUNT) + stringBuffer.append(STR_NEW_LINE) + } + + stringBuffer.append("총 수익률은 ") + stringBuffer.append(winningStatistics.yieldRate) + stringBuffer.append("입니다.") + stringBuffer.append(if (winningStatistics.yieldRate < 1) STR_PROFIT_IS_LOSS else STR_PROFIT_IS_GOOD) + + println(stringBuffer.toString()) + } + + private const val STR_PURCHASED_COUNT = "개를 구매하였습니다." + private const val STR_NEW_LINE = "\n" + private const val STR_WINNING_STATISTICS = "당첨 통계" + private const val STR_SEPARATOR = "---------" + private const val STR_MATCH = "개 일치(" + private const val STR_AMOUNT = "원) - " + private const val STR_COUNT = "개" + private const val STR_PROFIT_IS_LOSS = "기준이 1이기 때문에 결과적으로 손해라는 의미임" + private const val STR_PROFIT_IS_GOOD = "기준이 1이기 때문에 결과적으로 손해는 아니라는 의미임" +} diff --git a/src/main/kotlin/additionparser/README.md b/src/main/kotlin/stringcalculator/README.md similarity index 100% rename from src/main/kotlin/additionparser/README.md rename to src/main/kotlin/stringcalculator/README.md diff --git a/src/main/kotlin/stringcalculator/core/Calculator.kt b/src/main/kotlin/stringcalculator/core/Calculator.kt index 26984e3ebc..2bb9cb6c86 100644 --- a/src/main/kotlin/stringcalculator/core/Calculator.kt +++ b/src/main/kotlin/stringcalculator/core/Calculator.kt @@ -2,8 +2,7 @@ package stringcalculator.core object Calculator { fun sum(numbers: List): Int { - val sum = numbers.reduce { number1, number2 -> number1 + number2 } - + val sum = numbers.reduce(Number::plus) return sum.number } } diff --git a/src/main/kotlin/stringcalculator/core/FormulaParser.kt b/src/main/kotlin/stringcalculator/core/FormulaParser.kt index 7a5fe6c69d..c4018d959f 100644 --- a/src/main/kotlin/stringcalculator/core/FormulaParser.kt +++ b/src/main/kotlin/stringcalculator/core/FormulaParser.kt @@ -1,8 +1,8 @@ package stringcalculator.core object FormulaParser { - private const val REGEX_FIND_CUSTOM_DELIMITER = "(?<=//)(.*?)(?=\n)" - private val DELIMITER_FIND_PATTERN = Regex(REGEX_FIND_CUSTOM_DELIMITER) + private val DELIMITER_FIND_PATTERN = Regex("(?<=//)(.*?)(?=\n)") + private const val CUSTOM_DELIMITER_DECLARE_LEN = 4 fun parse(str: String?): List { if (str.isNullOrBlank()) { @@ -15,14 +15,14 @@ object FormulaParser { } private fun makeSplitter(str: String): StringSplitter { - if (str.length < 4) { + if (str.length < CUSTOM_DELIMITER_DECLARE_LEN) { return StringSplitter(str) } val delimiter = extractCustomDelimiter(str) if (delimiter.isNullOrBlank()) { return StringSplitter(str) } - return StringSplitter(str.substring(4), delimiter) + return StringSplitter(str.substring(CUSTOM_DELIMITER_DECLARE_LEN), delimiter) } private fun extractCustomDelimiter(str: String): String? { diff --git a/src/main/kotlin/stringcalculator/core/Number.kt b/src/main/kotlin/stringcalculator/core/Number.kt index 8cb14c0b93..a684de2237 100644 --- a/src/main/kotlin/stringcalculator/core/Number.kt +++ b/src/main/kotlin/stringcalculator/core/Number.kt @@ -10,7 +10,7 @@ data class Number(val number: Int) { } operator fun plus(other: Number): Number { - return Number((number + other.number).toString()) + return Number(number + other.number) } companion object { diff --git a/src/main/kotlin/stringcalculator/core/StringSplitter.kt b/src/main/kotlin/stringcalculator/core/StringSplitter.kt index d55eff0105..5d2de8220f 100644 --- a/src/main/kotlin/stringcalculator/core/StringSplitter.kt +++ b/src/main/kotlin/stringcalculator/core/StringSplitter.kt @@ -6,6 +6,17 @@ class StringSplitter(private val token: String, private val customDelimiter: Str } private fun makeDelimiterRegex(): String { - return listOf(",", ";", customDelimiter).joinToString("", "[", "]") + return listOf(DEFAULT_DELIMITER_COMMA, DEFAULT_DELIMITER_SEMICOLON, customDelimiter) + .joinToString(DELIMITER_SEPARATOR, DELIMITER_PREFIX, DELIMITER_POSTFIX) + } + + companion object { + private const val DEFAULT_DELIMITER_COMMA = "," + private const val DEFAULT_DELIMITER_SEMICOLON = ";" + + private const val DELIMITER_PREFIX = "[" + private const val DELIMITER_POSTFIX = "]" + + private const val DELIMITER_SEPARATOR = "" } } diff --git a/src/test/kotlin/lotto/core/LottoMarketTest.kt b/src/test/kotlin/lotto/core/LottoMarketTest.kt new file mode 100644 index 0000000000..521d7c354f --- /dev/null +++ b/src/test/kotlin/lotto/core/LottoMarketTest.kt @@ -0,0 +1,28 @@ +package lotto.core + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource +import org.junit.jupiter.params.provider.ValueSource + +class LottoMarketTest { + @ParameterizedTest + @CsvSource( + "'500', 0", + "'1500', 1", + "'2000', 2", + ) + fun `로또 구매를 테스트한다`( + amount: String, + count: Int, + ) { + LottoMarket.purchase(amount).size shouldBe count + } + + @ParameterizedTest + @ValueSource(strings = ["", "-1000"]) + fun `잘못된 파라미터 입력 시 Exception을 테스트한다`(amount: String) { + shouldThrow { LottoMarket.purchase(amount) } + } +} diff --git a/src/test/kotlin/lotto/core/WinningNumbersTest.kt b/src/test/kotlin/lotto/core/WinningNumbersTest.kt new file mode 100644 index 0000000000..70629a4cea --- /dev/null +++ b/src/test/kotlin/lotto/core/WinningNumbersTest.kt @@ -0,0 +1,16 @@ +package lotto.core + +import io.kotest.assertions.throwables.shouldThrow +import org.junit.jupiter.api.Test + +class WinningNumbersTest { + @Test + fun `잘못된 문자열 입력 시 오류를 확인한다`() { + shouldThrow { + WinningNumbers(listOf(1)) + } + shouldThrow { + WinningNumbers(listOf(1, 2, 3, 4, 5, 6, 7)) + } + } +} diff --git a/src/test/kotlin/lotto/core/WinningRankTest.kt b/src/test/kotlin/lotto/core/WinningRankTest.kt new file mode 100644 index 0000000000..e70c48b5bb --- /dev/null +++ b/src/test/kotlin/lotto/core/WinningRankTest.kt @@ -0,0 +1,17 @@ +package lotto.core + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class WinningRankTest { + @Test + fun `WinningCount로 WinningRank를 정상적으로 얻어지는 것을 확인한다`() { + WinningRank.getWinningAmount(0) shouldBe WinningRank.RANK0 + WinningRank.getWinningAmount(1) shouldBe WinningRank.RANK0 + WinningRank.getWinningAmount(2) shouldBe WinningRank.RANK0 + WinningRank.getWinningAmount(3) shouldBe WinningRank.RANK4 + WinningRank.getWinningAmount(4) shouldBe WinningRank.RANK3 + WinningRank.getWinningAmount(5) shouldBe WinningRank.RANK2 + WinningRank.getWinningAmount(6) shouldBe WinningRank.RANK1 + } +} diff --git a/src/test/kotlin/lotto/core/YieldCalculatorTest.kt b/src/test/kotlin/lotto/core/YieldCalculatorTest.kt new file mode 100644 index 0000000000..804e9819a6 --- /dev/null +++ b/src/test/kotlin/lotto/core/YieldCalculatorTest.kt @@ -0,0 +1,11 @@ +package lotto.core + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class YieldCalculatorTest { + @Test + fun `수익률 계산을 검증한다`() { + YieldCalculator.calculate(mapOf(WinningRank.RANK4 to 2, WinningRank.RANK3 to 1), 5) shouldBe 12 + } +}