Add unit tests for BlurParameters and LensController

First test coverage for the project: 17 tests covering BlurParameters
constraint clamping (size, blur, falloff, aspect ratio, position),
data class equality, field preservation across with* methods, and
LensController pre-initialization edge cases.

Adds JUnit 4.13.2 as a test dependency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-03-18 16:48:21 +01:00
commit aab1ff38a4
4 changed files with 196 additions and 0 deletions

View file

@ -112,6 +112,9 @@ dependencies {
// Location
implementation(libs.play.services.location)
// Test
testImplementation(libs.junit)
// Debug
debugImplementation(libs.androidx.ui.tooling)
}

View file

@ -0,0 +1,38 @@
package no.naiv.tiltshift.camera
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
class LensControllerTest {
@Test
fun `getCurrentLens returns null before initialization`() {
val controller = LensController()
assertNull(controller.getCurrentLens())
}
@Test
fun `getAvailableLenses returns empty before initialization`() {
val controller = LensController()
assertTrue(controller.getAvailableLenses().isEmpty())
}
@Test
fun `selectLens returns false for unknown lens`() {
val controller = LensController()
assertFalse(controller.selectLens("nonexistent"))
}
@Test
fun `cycleToNextLens returns null when no lenses`() {
val controller = LensController()
assertNull(controller.cycleToNextLens())
}
// Note: initialize() requires CameraInfo instances which need Android framework.
// Integration tests with Robolectric or on-device tests would cover that path.
}

View file

@ -0,0 +1,151 @@
package no.naiv.tiltshift.effect
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test
import kotlin.math.PI
class BlurParametersTest {
@Test
fun `DEFAULT has expected values`() {
val default = BlurParameters.DEFAULT
assertEquals(BlurMode.LINEAR, default.mode)
assertEquals(0f, default.angle, 0f)
assertEquals(0.5f, default.positionX, 0f)
assertEquals(0.5f, default.positionY, 0f)
assertEquals(0.3f, default.size, 0f)
assertEquals(0.8f, default.blurAmount, 0f)
assertEquals(0.5f, default.falloff, 0f)
assertEquals(1.0f, default.aspectRatio, 0f)
}
// --- withSize ---
@Test
fun `withSize clamps below minimum`() {
val params = BlurParameters.DEFAULT.withSize(0.01f)
assertEquals(BlurParameters.MIN_SIZE, params.size, 0f)
}
@Test
fun `withSize clamps above maximum`() {
val params = BlurParameters.DEFAULT.withSize(5.0f)
assertEquals(BlurParameters.MAX_SIZE, params.size, 0f)
}
@Test
fun `withSize accepts value in range`() {
val params = BlurParameters.DEFAULT.withSize(0.5f)
assertEquals(0.5f, params.size, 0f)
}
// --- withBlurAmount ---
@Test
fun `withBlurAmount clamps below minimum`() {
val params = BlurParameters.DEFAULT.withBlurAmount(-1f)
assertEquals(BlurParameters.MIN_BLUR, params.blurAmount, 0f)
}
@Test
fun `withBlurAmount clamps above maximum`() {
val params = BlurParameters.DEFAULT.withBlurAmount(2f)
assertEquals(BlurParameters.MAX_BLUR, params.blurAmount, 0f)
}
// --- withFalloff ---
@Test
fun `withFalloff clamps below minimum`() {
val params = BlurParameters.DEFAULT.withFalloff(0f)
assertEquals(BlurParameters.MIN_FALLOFF, params.falloff, 0f)
}
@Test
fun `withFalloff clamps above maximum`() {
val params = BlurParameters.DEFAULT.withFalloff(5f)
assertEquals(BlurParameters.MAX_FALLOFF, params.falloff, 0f)
}
// --- withAspectRatio ---
@Test
fun `withAspectRatio clamps below minimum`() {
val params = BlurParameters.DEFAULT.withAspectRatio(0.1f)
assertEquals(BlurParameters.MIN_ASPECT, params.aspectRatio, 0f)
}
@Test
fun `withAspectRatio clamps above maximum`() {
val params = BlurParameters.DEFAULT.withAspectRatio(10f)
assertEquals(BlurParameters.MAX_ASPECT, params.aspectRatio, 0f)
}
// --- withPosition ---
@Test
fun `withPosition clamps to 0-1 range`() {
val params = BlurParameters.DEFAULT.withPosition(-0.5f, 1.5f)
assertEquals(0f, params.positionX, 0f)
assertEquals(1f, params.positionY, 0f)
}
@Test
fun `withPosition accepts values in range`() {
val params = BlurParameters.DEFAULT.withPosition(0.3f, 0.7f)
assertEquals(0.3f, params.positionX, 0f)
assertEquals(0.7f, params.positionY, 0f)
}
// --- withAngle ---
@Test
fun `withAngle sets arbitrary angle`() {
val angle = PI.toFloat() / 4
val params = BlurParameters.DEFAULT.withAngle(angle)
assertEquals(angle, params.angle, 0f)
}
// --- copy preserves other fields ---
@Test
fun `with methods preserve other fields`() {
val custom = BlurParameters(
mode = BlurMode.RADIAL,
angle = 1.5f,
positionX = 0.2f,
positionY = 0.8f,
size = 0.4f,
blurAmount = 0.6f,
falloff = 0.7f,
aspectRatio = 2.0f
)
val updated = custom.withSize(0.5f)
assertEquals(BlurMode.RADIAL, updated.mode)
assertEquals(1.5f, updated.angle, 0f)
assertEquals(0.2f, updated.positionX, 0f)
assertEquals(0.8f, updated.positionY, 0f)
assertEquals(0.5f, updated.size, 0f)
assertEquals(0.6f, updated.blurAmount, 0f)
assertEquals(0.7f, updated.falloff, 0f)
assertEquals(2.0f, updated.aspectRatio, 0f)
}
// --- data class equality ---
@Test
fun `data class equality works`() {
val a = BlurParameters(mode = BlurMode.LINEAR, size = 0.5f)
val b = BlurParameters(mode = BlurMode.LINEAR, size = 0.5f)
assertEquals(a, b)
}
@Test
fun `different params are not equal`() {
val a = BlurParameters(mode = BlurMode.LINEAR)
val b = BlurParameters(mode = BlurMode.RADIAL)
assertNotEquals(a, b)
}
}

View file

@ -8,6 +8,7 @@ composeBom = "2024.12.01"
camerax = "1.4.1"
exifinterface = "1.3.7"
playServicesLocation = "21.3.0"
junit = "4.13.2"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -35,6 +36,9 @@ androidx-exifinterface = { group = "androidx.exifinterface", name = "exifinterfa
# Location
play-services-location = { group = "com.google.android.gms", name = "play-services-location", version.ref = "playServicesLocation" }
# Test
junit = { group = "junit", name = "junit", version.ref = "junit" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }