Skip to content

Commit

Permalink
Fixes flakiness in app's screenshot tests (android#1395)
Browse files Browse the repository at this point in the history
* Disables WM init in app's screenshot tests

Change-Id: Ib0994e744f49b53f58c0eebd52f80c0eba67bbed

* Spotless

Change-Id: Ic0212889354481433ce45ec4292ae7be9bd24b2e

* [CI] Uploads roborazzi reports if they fail

Change-Id: I5a25a7e156d3fcb72a396d3b503e62068a20b417

* Uses unused test module and enables LocalInspection

Change-Id: Iac36347dc3d702248d7515a74823e0bc0cbf2a2b

* Fixes timezone in snackbar screenshot tests

Change-Id: Ic517e8822218abeaddd3f8d2740b03e651d72d31

* Fixes conflict

Change-Id: Ia42fb78781d2469a608183594fc25c7c69f7e76c

* 🤖 Updates screenshots
  • Loading branch information
JoseAlcerreca committed Apr 24, 2024
1 parent 1da560f commit ead3f49
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 48 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/Build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ jobs:
name: local-test-results
path: '**/build/test-results/test*UnitTest/**.xml'

- name: Upload screenshot results (PNG)
if: always()
uses: actions/upload-artifact@v4
with:
name: screenshot-test-results
path: '**/build/outputs/roborazzi/*_compare.png'

- name: Check lint
run: ./gradlew :app:lintProdRelease :app-nia-catalog:lintRelease :lint:lint

Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ dependencies {

testImplementation(projects.core.dataTest)
testImplementation(projects.core.testing)
testImplementation(projects.sync.syncTest)
testImplementation(libs.androidx.compose.ui.test)
testImplementation(libs.hilt.android.testing)
testImplementation(libs.work.testing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.samples.apps.nowinandroid.ui

import android.util.Log
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.CompositionLocalProvider
Expand All @@ -28,10 +27,6 @@ import androidx.compose.ui.test.onRoot
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.test.platform.app.InstrumentationRegistry
import androidx.work.Configuration
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import com.github.takahirom.roborazzi.captureRoboImage
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
Expand Down Expand Up @@ -109,17 +104,6 @@ class NiaAppScreenSizesScreenshotTests {

@Before
fun setup() {
val config = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setExecutor(SynchronousExecutor())
.build()

// Initialize WorkManager for instrumentation tests.
WorkManagerTestInitHelper.initializeTestWorkManager(
InstrumentationRegistry.getInstrumentation().context,
config,
)

hiltRule.inject()

// Configure user data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,21 @@

package com.google.samples.apps.nowinandroid.ui

import android.util.Log
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.material3.SnackbarDuration.Indefinite
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.ForcedSize
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.test.platform.app.InstrumentationRegistry
import androidx.work.Configuration
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import com.github.takahirom.roborazzi.captureRoboImage
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
Expand All @@ -60,6 +57,7 @@ import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.annotation.GraphicsMode
import org.robolectric.annotation.LooperMode
import java.util.TimeZone
import javax.inject.Inject

/**
Expand Down Expand Up @@ -112,17 +110,6 @@ class SnackbarScreenshotTests {

@Before
fun setup() {
val config = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setExecutor(SynchronousExecutor())
.build()

// Initialize WorkManager for instrumentation tests.
WorkManagerTestInitHelper.initializeTestWorkManager(
InstrumentationRegistry.getInstrumentation().context,
config,
)

hiltRule.inject()

// Configure user data
Expand All @@ -135,6 +122,12 @@ class SnackbarScreenshotTests {
}
}

@Before
fun setTimeZone() {
// Make time zone deterministic in tests
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
}

@Test
fun phone_noSnackbar() {
val snackbarHostState = SnackbarHostState()
Expand Down Expand Up @@ -207,22 +200,27 @@ class SnackbarScreenshotTests {
) {
lateinit var scope: CoroutineScope
composeTestRule.setContent {
scope = rememberCoroutineScope()

DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(width, height)),
CompositionLocalProvider(
// Replaces images with placeholders
LocalInspectionMode provides true,
) {
BoxWithConstraints {
val appState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight),
),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaTheme {
NiaApp(appState, snackbarHostState, false, {}, {})
scope = rememberCoroutineScope()

DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(width, height)),
) {
BoxWithConstraints {
val appState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight),
),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaTheme {
NiaApp(appState, snackbarHostState, false, {}, {})
}
}
}
}
Expand Down
Binary file modified app/src/testDemo/screenshots/snackbar_compact_medium.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/testDemo/screenshots/snackbar_expanded_expanded.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/src/testDemo/screenshots/snackbar_medium_medium.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package com.google.samples.apps.nowinandroid.core.sync.test

import com.google.samples.apps.nowinandroid.core.data.util.SyncManager
import com.google.samples.apps.nowinandroid.sync.di.SyncModule
import com.google.samples.apps.nowinandroid.sync.status.StubSyncSubscriber
import com.google.samples.apps.nowinandroid.sync.status.SyncSubscriber
import dagger.Binds
import dagger.Module
import dagger.hilt.components.SingletonComponent
Expand All @@ -33,4 +35,9 @@ internal interface TestSyncModule {
fun bindsSyncStatusMonitor(
syncStatusMonitor: NeverSyncingSyncManager,
): SyncManager

@Binds
fun bindsSyncSubscriber(
syncSubscriber: StubSyncSubscriber,
): SyncSubscriber
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private const val TAG = "StubSyncSubscriber"
/**
* Stub implementation of [SyncSubscriber]
*/
internal class StubSyncSubscriber @Inject constructor() : SyncSubscriber {
class StubSyncSubscriber @Inject constructor() : SyncSubscriber {
override suspend fun subscribe() {
Log.d(TAG, "Subscribing to sync")
}
Expand Down

0 comments on commit ead3f49

Please sign in to comment.