Adding more biometric screenshot tests

Test: atest FingerprintEnrollIntroScreenshotTest FingerprintEnrollFindSensorScreenshotTest FingerprintEnrollEnrollingScreenshotTest
Bug: 297083009
Change-Id: I11df6fbaefa9d333dcfe803577947a4be7af9882
This commit is contained in:
Joshua McCloskey
2024-02-13 18:56:07 +00:00
parent 98374376cc
commit d92faeb1cf
35 changed files with 805 additions and 554 deletions

View File

@@ -23,6 +23,8 @@
<application>
<activity android:name="com.android.settings.test.screenshot.ContainerActivity" android:exported="true" />
<activity android:name="platform.test.screenshot.FragmentScreenshotActivity" android:exported="true"
android:theme="@style/GlifTheme.Light" />
</application>
</manifest>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 146 KiB

View File

@@ -1,142 +0,0 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.tests.screenshot
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.os.Bundle
import android.view.View
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.settings.R
import com.android.settings.biometrics.fingerprint2.lib.model.Default
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import kotlinx.coroutines.test.StandardTestDispatcher
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.screenshot.GoldenImagePathManager
import platform.test.screenshot.ScreenshotTestRule
import platform.test.screenshot.matchers.MSSIMMatcher
@RunWith(AndroidJUnit4::class)
class BasicScreenshotTest {
@Rule
@JvmField
var rule: ScreenshotTestRule =
ScreenshotTestRule(
GoldenImagePathManager(
InstrumentationRegistry.getInstrumentation().getContext(),
InstrumentationRegistry.getInstrumentation()
.getTargetContext()
.getFilesDir()
.getAbsolutePath() + "/settings_screenshots",
)
)
private var context: Context = ApplicationProvider.getApplicationContext()
private var interactor = FakeFingerprintManagerInteractor()
private val gatekeeperViewModel =
FingerprintGatekeeperViewModel(
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
interactor,
)
private val backgroundDispatcher = StandardTestDispatcher()
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
private val fingerprintSensor =
FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
var enrollFlow = Default
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
private val navigationViewModel =
FingerprintNavigationViewModel(
FingerprintNavigationStep.Introduction,
false,
flowViewModel,
interactor,
)
private var fingerprintViewModel =
FingerprintEnrollIntroViewModel(navigationViewModel, flowViewModel, interactor)
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
@Before
fun setup() {
val factory =
object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return when (modelClass) {
FingerprintEnrollIntroViewModel::class.java -> fingerprintViewModel
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
FingerprintNavigationViewModel::class.java -> navigationViewModel
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
else -> null
}
as T
}
}
fragmentScenario =
launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
FingerprintEnrollIntroV2Fragment(factory)
}
}
/** Renders a [view] into a [Bitmap]. */
private fun viewToBitmap(view: View): Bitmap {
val bitmap =
Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
view.draw(canvas)
return bitmap
}
@Test
fun testEnrollIntro() {
fragmentScenario.onFragment { fragment ->
val view = fragment.requireView().findViewById<View>(R.id.enroll_intro_content_view)!!
view.setBackgroundColor(Color.BLACK)
}
fragmentScenario.onFragment { fragment ->
val view = fragment.requireView().findViewById<View>(R.id.enroll_intro_content_view)!!
rule.assertBitmapAgainstGolden(viewToBitmap(view), "fp_enroll_intro", MSSIMMatcher())
}
}
}

View File

@@ -0,0 +1,12 @@
# Background info about tests
1. This test is ran in postsubmits at andoid-settings/robo_tests.gcl
2. It is important that this module stays somewhat small, if the test size grows
too large, it will be likely that this suite breaks due to flakiness(which
tends to happen with screenshot tests). In this case investigate splitting
the module.
# Running and updating screenshots.
1. For FingerprintEnrollIntroScreenshotTest.kt#testEnrollIntro
2. atest SettingsScreenshotRNGTests
3. There should be a file like com.android.settings.tests.screenshot.biometrics.fingerprint.fragment.FingerprintEnrollIntroScreenshotTest_testEnrollIntro_actual_robolectric_fp_enroll_intro.png_6245562387930305138.png
4. Place this screenshot in packages/apps/Settings/tests/screenshot/assets/robolectric/fp_enroll_intro.png

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.tests.screenshot.biometrics.fingerprint
import android.content.res.Configuration
import android.view.Surface
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
import com.android.settings.biometrics.fingerprint2.lib.model.Default
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSIconTouchViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.SensorStrength
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.update
import platform.test.screenshot.DeviceEmulationSpec
import platform.test.screenshot.DisplaySpec
import platform.test.screenshot.FragmentScreenshotTestRule
import platform.test.screenshot.GoldenImagePathManager
import platform.test.screenshot.matchers.PixelPerfectMatcher
class Injector(step: FingerprintNavigationStep.UiStep) {
var enrollFlow = Default
var fingerprintSensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.REAR)
var accessibilityInteractor =
object : AccessibilityInteractor {
override val isAccessibilityEnabled: Flow<Boolean> = flowOf(true)
}
var foldStateInteractor =
object : FoldStateInteractor {
private val _foldState = MutableStateFlow(false)
override val isFolded: Flow<Boolean> = _foldState.asStateFlow()
override fun onConfigurationChange(newConfig: Configuration) {
_foldState.update { false }
}
}
var orientationInteractor =
object : OrientationInteractor {
override val orientation: Flow<Int> = flowOf(Configuration.ORIENTATION_LANDSCAPE)
override val rotation: Flow<Int> = flowOf(Surface.ROTATION_0)
override fun getRotationFromDefault(rotation: Int): Int = rotation
}
var gatekeeperViewModel =
FingerprintGatekeeperViewModel(
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
interactor,
)
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
var navigationViewModel = FingerprintNavigationViewModel(step, true, flowViewModel, interactor)
var fingerprintViewModel =
FingerprintEnrollIntroViewModel(navigationViewModel, flowViewModel, interactor)
var fingerprintScrollViewModel = FingerprintScrollViewModel()
var backgroundViewModel = BackgroundViewModel()
var fingerprintEnrollViewModel =
FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel)
var fingerprintEnrollEnrollingViewModel =
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
var rfpsIconTouchViewModel = RFPSIconTouchViewModel()
var rfpsViewModel =
RFPSViewModel(fingerprintEnrollEnrollingViewModel, navigationViewModel, orientationInteractor)
var fingerprintFindSensorViewModel =
FingerprintEnrollFindSensorViewModel(
navigationViewModel,
fingerprintEnrollViewModel,
gatekeeperViewModel,
backgroundViewModel,
accessibilityInteractor,
foldStateInteractor,
orientationInteractor,
flowViewModel,
interactor,
)
val factory =
object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return when (modelClass) {
FingerprintEnrollIntroViewModel::class.java -> fingerprintViewModel
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
FingerprintNavigationViewModel::class.java -> navigationViewModel
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
FingerprintEnrollFindSensorViewModel::class.java -> fingerprintFindSensorViewModel
FingerprintEnrollViewModel::class.java -> fingerprintEnrollViewModel
RFPSViewModel::class.java -> rfpsViewModel
BackgroundViewModel::class.java -> backgroundViewModel
RFPSIconTouchViewModel::class.java -> rfpsIconTouchViewModel
FingerprintEnrollEnrollingViewModel::class.java -> fingerprintEnrollEnrollingViewModel
else -> null
}
as T
}
}
init {
fingerprintEnrollViewModel.sensorTypeCached = fingerprintSensor.sensorType
}
companion object {
private val Phone = DisplaySpec("phone", width = 1080, height = 2340, densityDpi = 420)
private const val screenshotPath = "/settings_screenshots"
val interactor = FakeFingerprintManagerInteractor()
fun BiometricFragmentScreenShotRule() =
FragmentScreenshotTestRule(
DeviceEmulationSpec.forDisplays(Phone).first(),
GoldenImagePathManager(
InstrumentationRegistry.getInstrumentation().context,
InstrumentationRegistry.getInstrumentation().targetContext.filesDir.absolutePath +
screenshotPath,
),
PixelPerfectMatcher(),
true,
)
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.tests.screenshot.biometrics.fingerprint.fragment
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.fragment.RFPSEnrollFragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector.Companion.BiometricFragmentScreenShotRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.screenshot.FragmentScreenshotTestRule
import platform.test.screenshot.ViewScreenshotTestRule.Mode
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollEnrollingScreenshotTest {
private val injector: Injector =
Injector(FingerprintNavigationStep.Enrollment(Injector.interactor.sensorProp))
@Rule @JvmField var rule: FragmentScreenshotTestRule = BiometricFragmentScreenShotRule()
@Test
fun testEnrollEnrolling() {
rule.screenshotTest("fp_enroll_enrolling", Mode.MatchSize, RFPSEnrollFragment(injector.factory))
}
}

View File

@@ -0,0 +1,45 @@
package com.android.settings.tests.screenshot.biometrics.fingerprint.fragment
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector.Companion.BiometricFragmentScreenShotRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.screenshot.FragmentScreenshotTestRule
import platform.test.screenshot.ViewScreenshotTestRule.Mode
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollFindSensorScreenshotTest {
private val injector: Injector =
Injector(FingerprintNavigationStep.Education(Injector.interactor.sensorProp))
@Rule @JvmField var rule: FragmentScreenshotTestRule = BiometricFragmentScreenShotRule()
@Test
fun testEnrollFindSensor() {
rule.screenshotTest(
"fp_enroll_find_sensor",
Mode.MatchSize,
FingerprintEnrollFindSensorV2Fragment(injector.fingerprintSensor.sensorType, injector.factory),
)
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.tests.screenshot.biometrics.fingerprint.fragment
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import platform.test.screenshot.FragmentScreenshotTestRule
import platform.test.screenshot.ViewScreenshotTestRule.Mode
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollIntroScreenshotTest {
private val injector: Injector = Injector(FingerprintNavigationStep.Introduction)
@Rule
@JvmField
var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
@Test
fun testEnrollIntro() {
rule.screenshotTest(
"fp_enroll_intro",
Mode.MatchSize,
FingerprintEnrollIntroV2Fragment(injector.factory),
)
}
}