diff --git a/core-kotlin-modules/core-kotlin-12/pom.xml b/core-kotlin-modules/core-kotlin-12/pom.xml index e1572ace7..3202e2166 100644 --- a/core-kotlin-modules/core-kotlin-12/pom.xml +++ b/core-kotlin-modules/core-kotlin-12/pom.xml @@ -14,6 +14,21 @@ 1.0.0-SNAPSHOT + + + io.kotest + kotest-runner-junit5 + ${kotest.version} + test + + + io.kotest + kotest-property-jvm + ${kotest.version} + test + + + src/main/kotlin src/test/kotlin @@ -34,4 +49,10 @@ + + + 5.9.0 + 2.22.2 + + diff --git a/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/formatting/NumberFormat.kt b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/formatting/NumberFormat.kt new file mode 100644 index 000000000..b06711c01 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/main/kotlin/com/baeldung/formatting/NumberFormat.kt @@ -0,0 +1,43 @@ +package com.baeldung.formatting + +import java.text.DecimalFormat +import java.text.DecimalFormatSymbols +import java.util.* + +/** + * Interface for the different formatting implementation. + */ +interface NumberFormat { + + /** + * Returns provided number as string with thousands separator. + */ + fun formatted(number: Int): String +} + +object FormatByDecimalFormat : NumberFormat { + override fun formatted(number: Int): String = + DecimalFormat("#,###") + .format(number) + .replace(",", ".") +} + +object FormatByDecimalFormatGermany : NumberFormat { + override fun formatted(number: Int): String = + DecimalFormat("#,###", DecimalFormatSymbols(Locale.GERMANY)) + .format(number) +} + +object FormatByStringFormat : NumberFormat { + override fun formatted(number: Int): String = + String.format(Locale.GERMANY, "%,d", number) +} + +object FormatByChunking : NumberFormat { + override fun formatted(number: Int): String = + number.toString() + .reversed() // 15000 -> 00051 + .chunked(3) // [000] [51] + .joinToString(".") // 000.51 + .reversed() // 15.000 +} diff --git a/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/formatting/NumberFormatUnitTest.kt b/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/formatting/NumberFormatUnitTest.kt new file mode 100644 index 000000000..c99970104 --- /dev/null +++ b/core-kotlin-modules/core-kotlin-12/src/test/kotlin/com/baeldung/formatting/NumberFormatUnitTest.kt @@ -0,0 +1,50 @@ +package com.baeldung.formatting + +import io.kotest.core.spec.style.ShouldSpec +import io.kotest.property.Arb +import io.kotest.property.arbitrary.positiveInt +import io.kotest.property.checkAll +import org.assertj.core.api.Assertions.assertThat + +class NumberFormatUnitTest : ShouldSpec({ + + // Dynamic generation of tests for each implementation + nameToImplementationPairs.forEach { (name, function) -> + + // Property based test (for each implementation) + should("return correctly formatted string with $name implementation") { + checkAll(Arb.positiveInt()) { number -> + var result = function(number) + + assertThat(result).containsPattern("^(\\d{1,3}(\\.\\d{3})*|\\d+)$") + assertThat(number.toString()).isEqualTo(result.replace(".", "")) + } + } + + givenToExpectedPairs.forEach { (givenNumber, expectedString) -> + + // Parameterised; Example based test + should("return '$expectedString' for $givenNumber with $name implementation") { + assertThat(function(givenNumber)).isEqualTo(expectedString) + } + } + + } +}) + +// Examples to check against, with given number and expected string +private val givenToExpectedPairs = listOf( + 0 to "0", + 12 to "12", + 456 to "456", + 100_000 to "100.000", + 1_234_567 to "1.234.567" +) + +// Different implementations of the formatting feature with the display name +private val nameToImplementationPairs = listOf( + "FormatByChunking" to { it: Int -> FormatByChunking.formatted(it) }, + "FormatByStringFormat" to { it: Int -> FormatByStringFormat.formatted(it) }, + "FormatByDecimalFormatGermany" to { it: Int -> FormatByDecimalFormatGermany.formatted(it) }, + "FormatByDecimalFormat" to { it: Int -> FormatByDecimalFormat.formatted(it) } +)