Skip to content

Commit d525bdd

Browse files
authored
Merge pull request #30 from android/screenshot-testing-roborazzi
Add screenshot testing
2 parents 59dc71c + 95f191f commit d525bdd

File tree

8 files changed

+90
-5
lines changed

8 files changed

+90
-5
lines changed
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build cahier
1+
name: Build and verify cahier
22

33
on:
44
workflow_dispatch:
@@ -11,7 +11,8 @@ jobs:
1111
build:
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/checkout@v4
14+
- name: Checkout codebase
15+
uses: actions/checkout@v4
1516

1617
- name: Set Up JDK
1718
uses: actions/setup-java@v4
@@ -31,7 +32,7 @@ jobs:
3132
test:
3233
runs-on: ubuntu-latest
3334
steps:
34-
- name: checkout
35+
- name: Checkout codebase
3536
uses: actions/checkout@v4
3637

3738
- name: Enable KVM
@@ -50,3 +51,9 @@ jobs:
5051
device: desktop_large
5152
arch: x86_64
5253
script: ./gradlew :app:connectedAndroidTest
54+
55+
- name: Run Roborazzi
56+
id: verify-test
57+
run: |
58+
# If there is a difference between the screenshots, the test will fail.
59+
./gradlew app:verifyRoborazziDebug --stacktrace

app/build.gradle.kts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ plugins {
1717
alias(libs.plugins.androidApplication)
1818
alias(libs.plugins.jetbrainsKotlinAndroid)
1919
alias(libs.plugins.ksp)
20+
alias(libs.plugins.roborazzi)
2021
id("org.jetbrains.kotlin.plugin.compose") version "2.2.20"
2122
id("kotlin-parcelize")
2223
kotlin("plugin.serialization")
@@ -61,6 +62,14 @@ android {
6162
excludes += "/META-INF/{AL2.0,LGPL2.1}"
6263
}
6364
}
65+
testOptions {
66+
unitTests {
67+
isIncludeAndroidResources = true
68+
}
69+
}
70+
roborazzi {
71+
outputDir.set(file("../screenshots"))
72+
}
6473
}
6574

6675
dependencies {
@@ -97,6 +106,12 @@ dependencies {
97106
testImplementation(libs.androidx.arch.core.testing)
98107
testImplementation(libs.kotlinx.coroutines.test)
99108
testImplementation(libs.turbine)
109+
testImplementation(libs.robolectric)
110+
testImplementation(libs.roborazzi)
111+
testImplementation(libs.roborazzi.compose)
112+
testImplementation(libs.roborazzi.rule)
113+
testImplementation(platform(libs.androidx.compose.bom))
114+
testImplementation(libs.androidx.ui.test.junit4)
100115

101116
// Android Testing - For instrumented tests
102117
androidTestImplementation(libs.androidx.junit)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.example.cahier
2+
3+
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.ui.test.junit4.createComposeRule
6+
import androidx.compose.ui.test.onRoot
7+
import com.example.cahier.data.FakeNotesRepository
8+
import com.example.cahier.ui.HomePane
9+
import com.example.cahier.ui.viewmodels.HomeScreenViewModel
10+
import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers
11+
import com.github.takahirom.roborazzi.captureRoboImage
12+
import org.junit.Rule
13+
import org.junit.Test
14+
import org.junit.runner.RunWith
15+
import org.robolectric.RobolectricTestRunner
16+
import org.robolectric.annotation.Config
17+
import org.robolectric.annotation.GraphicsMode
18+
19+
@GraphicsMode(GraphicsMode.Mode.NATIVE)
20+
@RunWith(RobolectricTestRunner::class)
21+
class ScreenshotTest {
22+
23+
@get:Rule
24+
val composeTestRule = createComposeRule()
25+
26+
private val fakeViewModel = HomeScreenViewModel(FakeNotesRepository())
27+
28+
@Composable
29+
private fun HomeContent() {
30+
HomePane(
31+
navigateToCanvas = { _ -> },
32+
navigateToDrawingCanvas = { _ -> },
33+
navigateUp = {},
34+
homeScreenViewModel = fakeViewModel
35+
)
36+
}
37+
38+
@Config(qualifiers = RobolectricDeviceQualifiers.MediumTablet)
39+
@Test
40+
fun globalNavigation_showNavRail() {
41+
composeTestRule.setContent { HomeContent() }
42+
43+
composeTestRule.onRoot().captureRoboImage("reference_screenshot_navrail.png")
44+
}
45+
46+
@Config(qualifiers = RobolectricDeviceQualifiers.Pixel7Pro)
47+
@Test
48+
fun globalNavigation_showBottomNavBar() {
49+
composeTestRule.setContent { HomeContent() }
50+
51+
composeTestRule.onRoot().captureRoboImage("reference_screenshot_bottomnavbar.png")
52+
}
53+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdk=34

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ kotlin.code.style=official
2121
# resources declared in the library itself and none from the library's dependencies,
2222
# thereby reducing the size of the R class for that library
2323
android.nonTransitiveRClass=true
24-
android.enableJetifier=false
24+
android.enableJetifier=false
25+
# Sets Roborazzi output folder to the one specified in the
26+
roborazzi.record.filePathStrategy=relativePathFromRoborazziContextOutputDirectory

gradle/libs.versions.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ coreTesting = "2.2.0"
3535
kotlinxCoroutinesTest = "1.10.2"
3636
turbine = "1.2.1"
3737
material3WindowSizeClass = "1.4.0"
38+
robolectric = "4.11.1"
39+
roborazzi = "1.51.0"
3840

3941
[libraries]
4042
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -92,9 +94,14 @@ hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", vers
9294
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
9395
mockito-android = { module = "org.mockito:mockito-android", version.ref = "mockito" }
9496
androidx-compose-material3-window-size-class1 = { group = "androidx.compose.material3", name = "material3-window-size-class", version.ref = "material3WindowSizeClass" }
97+
robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" }
98+
roborazzi = { group = "io.github.takahirom.roborazzi", name = "roborazzi", version.ref = "roborazzi" }
99+
roborazzi-compose = { group = "io.github.takahirom.roborazzi", name = "roborazzi-compose", version.ref = "roborazzi" }
100+
roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-junit-rule", version.ref = "roborazzi" }
95101

96102
[plugins]
97103
androidApplication = { id = "com.android.application", version.ref = "agp" }
98104
androidLibrary = { id = "com.android.library", version.ref = "agp" }
99105
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
100-
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
106+
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
107+
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
37.1 KB
Loading
33.6 KB
Loading

0 commit comments

Comments
 (0)