diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 522fcf66..fa8b50c2 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -114,7 +114,16 @@ jobs: - name: Install Android SDK uses: hannesa2/action-android/install-sdk@0.17.0 - name: Run tests - run: ./gradlew test + run: ./gradlew :chartLib:test + - name: Verify Roborazzi screenshots + run: ./gradlew :app:verifyRoborazziDebug + - name: Archive Roborazzi results + uses: actions/upload-artifact@v7 + if: ${{ always() }} + with: + name: Chart-Roborazzi-report + path: app/build/reports/roborazzi + if-no-files-found: ignore - name: Test jitpack publish command run: ./gradlew :chartLib:publishToMavenLocal :chartLibCompose:publishToMavenLocal -PRELEASE_SIGNING_ENABLED=false - name: Code checks diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2499120d..d8671e4e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" + id("io.github.takahirom.roborazzi") version "1.70.0" } android { @@ -45,6 +46,9 @@ android { // https://stackoverflow.com/a/67635863/1079990 testOptions { animationsDisabled = true + unitTests { + isIncludeAndroidResources = true + } } lint { lintConfig = file("lint.xml") @@ -58,6 +62,10 @@ android { } } +roborazzi { + outputDir.set(project.file("src/test/snapshots")) +} + dependencies { lintChecks(project(":lint")) @@ -91,4 +99,12 @@ dependencies { androidTestUtil("androidx.test.services:test-services:1.6.0") androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0") androidTestImplementation("androidx.test.espresso:espresso-intents:3.7.0") + + val roborazziVersion = "1.70.0" + testImplementation("io.github.takahirom.roborazzi:roborazzi:$roborazziVersion") + testImplementation("io.github.takahirom.roborazzi:roborazzi-compose:$roborazziVersion") + testImplementation("org.robolectric:robolectric:4.16.1") + testImplementation("androidx.test.ext:junit:1.3.0") + testImplementation("androidx.test.espresso:espresso-core:3.7.0") + testImplementation("androidx.compose.ui:ui-test-junit4") } diff --git a/app/src/test/kotlin/info/appdev/chartexample/RoborazziTest.kt b/app/src/test/kotlin/info/appdev/chartexample/RoborazziTest.kt new file mode 100644 index 00000000..df6211b6 --- /dev/null +++ b/app/src/test/kotlin/info/appdev/chartexample/RoborazziTest.kt @@ -0,0 +1,87 @@ +package info.appdev.chartexample + +import androidx.test.core.app.ActivityScenario +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.matcher.ViewMatchers.isRoot +import com.github.takahirom.roborazzi.RoborazziOptions +import com.github.takahirom.roborazzi.captureRoboImage +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(RobolectricTestRunner::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(sdk = [28], qualifiers = "w411dp-h891dp-420dpi") +class RoborazziTest { + + // Cubic bezier path rendering produces minor sub-pixel differences between + // macOS and Linux JVMs, so allow a small tolerance for all comparisons. + private val options = RoborazziOptions( + compareOptions = RoborazziOptions.CompareOptions(changeThreshold = 0.01f) + ) + + @Test + fun barChart() { + ActivityScenario.launch(BarChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun lineChart() { + ActivityScenario.launch(LineChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun pieChart() { + ActivityScenario.launch(PieChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun horizontalBarChart() { + ActivityScenario.launch(HorizontalBarChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun bubbleChart() { + ActivityScenario.launch(BubbleChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun scatterChart() { + ActivityScenario.launch(ScatterChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun candleStickChart() { + ActivityScenario.launch(CandleStickChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun combinedChart() { + ActivityScenario.launch(CombinedChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } + + @Test + fun radarChart() { + ActivityScenario.launch(RadarChartActivity::class.java).use { + onView(isRoot()).captureRoboImage(roborazziOptions = options) + } + } +} diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.barChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.barChart.png new file mode 100644 index 00000000..9cd3f7cb Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.barChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.bubbleChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.bubbleChart.png new file mode 100644 index 00000000..feb4193d Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.bubbleChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.candleStickChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.candleStickChart.png new file mode 100644 index 00000000..6e30ed02 Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.candleStickChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.combinedChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.combinedChart.png new file mode 100644 index 00000000..dece7107 Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.combinedChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.horizontalBarChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.horizontalBarChart.png new file mode 100644 index 00000000..3f96f5da Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.horizontalBarChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.lineChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.lineChart.png new file mode 100644 index 00000000..c616d06e Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.lineChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.pieChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.pieChart.png new file mode 100644 index 00000000..f2138247 Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.pieChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.radarChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.radarChart.png new file mode 100644 index 00000000..e33887a9 Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.radarChart.png differ diff --git a/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.scatterChart.png b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.scatterChart.png new file mode 100644 index 00000000..669150c2 Binary files /dev/null and b/app/src/test/snapshots/info.appdev.chartexample.RoborazziTest.scatterChart.png differ