Skip to content

Commit

Permalink
Add tests to qr-code module
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Scholz committed Oct 15, 2023
1 parent 8a4f897 commit 5e92261
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
3 changes: 3 additions & 0 deletions qr-code/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ dependencies {

detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.1")

testImplementation("com.google.zxing:javase:3.5.2")
testImplementation("com.willowtreeapps.assertk:assertk:0.27.0")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.9.10")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0")
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.github.simonscholz.qrcode

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.io.TempDir
import java.awt.Color
import java.nio.file.Path
import java.util.Objects
import javax.imageio.ImageIO

class CreateQrCodeTest {

private val qrCodeApi = QrCodeFactory.createQrCodeApi()

@Test
fun `qr code can be written to file system without errors`(@TempDir tempDir: Path) {
assertDoesNotThrow {
val qrCodeConfig = QrCodeConfig.Builder("Testing").build()
val qrCodeImage = qrCodeApi.createQrCodeImage(qrCodeConfig)
val qrCodeFile = tempDir.resolve("qr-code.png")
ImageIO.write(qrCodeImage, "png", qrCodeFile.toFile())
}
}

@Test
fun `complex qr code can be written to file system without errors`(@TempDir tempDir: Path) {
assertDoesNotThrow {
val resource = Objects.requireNonNull(
CreateQrCodeTest::class.java.getClassLoader()
.getResource("rainbow.png"),
)
val logo = ImageIO.read(resource)

val positionalSquaresConfig = QrPositionalSquaresConfig.Builder()
.relativeSquareBorderRound(0.2)
.innerSquareColor(Color.RED)
.centerColor(Color.GREEN)
.outerSquareColor(Color.BLUE)
.outerBorderColor(Color.YELLOW)
.build()
val qrCodeConfig = QrCodeConfig.Builder("Testing")
.qrCodeSize(1000)
.qrCodeColorConfig(Color.RED, Color.BLUE)
.qrPositionalSquaresConfig(positionalSquaresConfig)
.qrBorderConfig(Color.BLACK, 0.05, 0.2)
.qrLogoConfig(logo, 0.2, Color.WHITE)
.build()
val qrCodeImage = qrCodeApi.createQrCodeImage(qrCodeConfig)
val qrCodeFile = tempDir.resolve("qr-code.png")
ImageIO.write(qrCodeImage, "png", qrCodeFile.toFile())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package io.github.simonscholz.qrcode

import assertk.assertThat
import assertk.assertions.isEqualTo
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.client.j2se.BufferedImageLuminanceSource
import com.google.zxing.common.HybridBinarizer
import com.google.zxing.multi.qrcode.QRCodeMultiReader
import io.github.simonscholz.qrcode.types.SimpleTypes
import io.github.simonscholz.qrcode.types.VCard
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import java.awt.Color
import java.awt.image.BufferedImage
import java.net.URL
import java.util.Objects
import javax.imageio.ImageIO
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.MethodSource

class ReadCreatedQrCodeTest {

private val qrCodeApi = QrCodeFactory.createQrCodeApi()

@ParameterizedTest
@MethodSource("provideDifferentQrCodeTypeTexts")
fun `Writing different QrCode type texts to BufferedImage and reading it should produce the same outcome`(
qrCodeInputText : String
) {
val qrCodeImage = qrCodeApi.createQrCodeImage(QrCodeConfig(qrCodeInputText, DEFAULT_IMG_SIZE))

val readQRCode = readQRCode(qrCodeImage)
assertThat(readQRCode).isEqualTo(qrCodeInputText)
}

@Test
fun `Creating qr code with logo, circle positional squares and border should still be readable`() {
val qrCodeText = SimpleTypes.url("https://simonscholz.github.io/")

val resource = logoUrl()
val qrCodeImage = logoAndCirclePositionalSquares(resource, qrCodeApi)

val readQRCode = readQRCode(qrCodeImage)
assertThat(readQRCode).isEqualTo(qrCodeText)
}

@Test
@Disabled("It seems that the zxing reader cannot deal with colors :-(")
fun `Creating colorful qr code with logo and different shapes should still be readable`() {
val qrCodeText = SimpleTypes.url("https://simonscholz.github.io/")

val resource = logoUrl()

val qrCodeImage = colorful(resource, qrCodeApi)

val readQRCode = readQRCode(qrCodeImage)
assertThat(readQRCode).isEqualTo(qrCodeText)
}

private fun logoUrl(): URL =
Objects.requireNonNull(
CreateQrCodeTest::class.java.getClassLoader()
.getResource("rainbow.png"),
)

private fun logoAndCirclePositionalSquares(resource: URL, qrCodeApi: QrCodeApi): BufferedImage {
val logo = ImageIO.read(resource)
val positionalSquaresConfig = QrPositionalSquaresConfig.Builder()
.circleShaped(true)
.build()
val qrCodeConfig = QrCodeConfig.Builder("https://simonscholz.github.io/")
.qrBorderConfig(Color.RED)
.qrLogoConfig(logo)
.qrPositionalSquaresConfig(positionalSquaresConfig)
.build()
return qrCodeApi.createQrCodeImage(qrCodeConfig)
}

private fun colorful(resource: URL, qrCodeApi: QrCodeApi): BufferedImage {
val logo = ImageIO.read(resource)
val bgColor = Color.RED
val fillColor = Color.BLUE
val positionalSquaresConfig = QrPositionalSquaresConfig.Builder()
.circleShaped(true)
.centerColor(fillColor)
.innerSquareColor(bgColor)
.outerSquareColor(fillColor)
.outerBorderColor(bgColor)
.build()
val qrCodeConfig = QrCodeConfig.Builder("https://simonscholz.github.io/")
.qrBorderConfig(Color.WHITE)
.qrLogoConfig(logo)
.qrCodeColorConfig(bgColor, fillColor)
.qrPositionalSquaresConfig(positionalSquaresConfig)
.build()
return qrCodeApi.createQrCodeImage(qrCodeConfig)
}

private fun readQRCode(bufferedImage: BufferedImage, hintMap: Map<DecodeHintType, *>? = null): String {
val binaryBitmap = BinaryBitmap(
HybridBinarizer(
BufferedImageLuminanceSource(
bufferedImage,
),
),
)
val qrCodeResult = QRCodeMultiReader().decode(binaryBitmap, hintMap)
return qrCodeResult.text
}

companion object {
@JvmStatic
fun provideDifferentQrCodeTypeTexts(): List<Arguments> {
val vCard = VCard.Builder("Simon Scholz")
.email("simon@example.com")
.organization("Self Employed")
.phoneNumber("+49 176 12345678")
.website("https://simonscholz.github.io/")
.build()
return listOf(Arguments.of(vCard.toVCardQrCodeText()))
}
}
}
Binary file added qr-code/src/test/resources/rainbow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5e92261

Please sign in to comment.