Add links, parameterized tests and cleanup

This commit is contained in:
Harsh Shandilya 2022-06-29 02:12:40 +05:30
parent 0713469376
commit 19b77317c9
1 changed files with 54 additions and 9 deletions

View File

@ -8,15 +8,19 @@ tags = ["jetpack-compose", "kotlin-multiplatform"]
title = "Writing Paparazzi tests for your Kotlin Multiplatform projects"
+++
## Introduction
[Paparazzi] is a Gradle plugin and library that enables writing UI tests for Android screens that run entirely on the JVM, without needing a physical device or emulator. This is massive, since it significantly increases the speed of UI tests as well as allows them to run on any CI system, not just ones using macOS or Linux with KVM enabled.
Unfortunately, Paparazzi does not directly work with Kotlin Multiplatform projects so you cannot apply it to a KMP + Android module and start putting your tests in the `androidTest` source set (not to be confused with `androidAndroidTest`. Yes, I know). Why would you want to do this in the first place? Like everything cool and new in Android land, [Compose]! Specifically, [compose-jb], JetBrains' redistribution of Jetpack Compose with full desktop support via the JVM.
Unfortunately, Paparazzi does not directly work with Kotlin Multiplatform projects so you cannot apply it to a KMP + Android module and start putting your tests in the `androidTest` source set (not to be confused with `androidAndroidTest`. Yes, I know). Why would you want to do this in the first place? Like everything cool and new in Android land, [Compose]! Specifically, [compose-jb], JetBrains' redistribution of Jetpack Compose optimised for Kotlin Multiplatform.
I've [sent a PR] to Paparazzi that will resolve this issue, and in the mean time we can workaround this limitation.
To begin, we'll need a new Gradle module for our Paparazzi tests. Since Paparazzi doesn't understand Kotlin Multiplatform, we're gonna hide that aspect of our project and present it a pure Android library project. Set up the module like so:
## Setting things up
```kotlin
To begin, we'll need a new Gradle module for our Paparazzi tests. Since Paparazzi doesn't understand Kotlin Multiplatform yet, we're gonna hide that aspect of our project and present it a pure Android library project. Set up the module like so:
```plain
// paparazzi-tests/build.gradle.kts
plugins {
id("com.android.library")
@ -28,9 +32,9 @@ android {
}
```
Now, add dependencies in this module to the modules that contain the composables you'd like to test. As you might have guessed, this approach currently limits you to only being able to test public composables. However, if you're trying to test the UI exposed by a "common" module that might not be such a big deal, as it wasn't for me.
Now, add dependencies in this module to the modules that contain the composables you'd like to test. As you might have guessed, this approach currently limits you to only being able to test public composables. However, if you're trying to test the UI exposed by a "common" module like I am, that might not be such a big deal.
```kotlin
```plain
// paparazzi-tests/build.gradle.kts
dependencies {
testImplementation(projects.common)
@ -39,7 +43,7 @@ dependencies {
And that's pretty much it! You can now be off to the races and start writing your tests:
```kotlin
```plain
// paparazzi-tests/src/test/kotlin/UserProfileTest.kt
class UserProfileTest {
@get:Rule val paparazzi = Paparazzi()
@ -62,11 +66,13 @@ class UserProfileTest {
Consult the [Paparazzi documentation] for the Gradle tasks reference and customization options.
## Additional tips
## Recipes
### Disable release build type for test module
If you use `./gradlew check` in your CI, our new module will be tested in both release and debug build types. This is fairly redundant, so you can disable the release build type altogether:
```kotlin
```plain
// paparazzi-tests/build.gradle.kts
androidComponents {
beforeVariants { variant ->
@ -75,9 +81,11 @@ androidComponents {
}
```
### Running with JDK 12+
You will run into [this issue] if you use JDK 12 or above to run Paparazzi-backed tests. I've [started working] on a fix for it upstream, in the mean time it can be worked around by forcing the test tasks to run with JDK 11.
```kotlin
```plain
// paparazzi-tests/build.gradle.kts
tasks.withType<Test>().configureEach {
javaLauncher.set(javaToolchains.launcherFor {
@ -85,3 +93,40 @@ tasks.withType<Test>().configureEach {
})
}
```
### Testing with multiple themes easily
Using an enum and Google's [TestParameterInjector] you can write a single test and have it run against all your themes.
```plain
// paparazzi-tests/src/test/kotlin/Theme.kt
import androidx.compose.material3.ColorScheme
enum class Theme(val colors: ColorScheme) {
Light(LightThemeColors),
Dark(DarkThemeColors),
}
```
```plain
// paparazzi-tests/src/test/kotlin/UserProfileTest.kt
@RunWith(TestParameterInjector::class)
class UserProfileTest {
@get:Rule val paparazzi = Paparazzi()
@Test
fun verify(@TestParameter theme: Theme) {
paparazzi.snapshot(name = theme.name) {
MaterialTheme(colorScheme = theme.colors) { UserProfile() }
}
}
```
[paparazzi]: https://github.com/cashapp/paparazzi
[compose]: https://d.android.com/jetpack/compose
[compose-jb]: https://github.com/jetbrains/compose-jb
[sent a pr]: https://github.com/cashapp/paparazzi/pull/450
[paparazzi documentation]: https://cashapp.github.io/paparazzi
[this issue]: https://github.com/cashapp/paparazzi/issues/409
[started working]: https://github.com/cashapp/paparazzi/pull/474
[testparameterinjector]: https://github.com/google/TestParameterInjector