Merge "Start using GoldenImagePathManager Test: ScreenshotTestRuleTest Bug: 232141755 Merged-In: I8680217cc62bd198e610e1c5e39b7835a48392f3 Change-Id: I2e8c13d12c975c920ca32d17b58aa46c8b1e1d74"
diff --git a/libraries/screenshot/src/androidTest/java/platform/test/screenshot/ScreenshotTestRuleTest.kt b/libraries/screenshot/src/androidTest/java/platform/test/screenshot/ScreenshotTestRuleTest.kt
index 1581048..6e2ef63 100644
--- a/libraries/screenshot/src/androidTest/java/platform/test/screenshot/ScreenshotTestRuleTest.kt
+++ b/libraries/screenshot/src/androidTest/java/platform/test/screenshot/ScreenshotTestRuleTest.kt
@@ -16,12 +16,14 @@
package platform.test.screenshot
+import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
+import java.io.File
import java.lang.AssertionError
import org.junit.After
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -34,19 +36,21 @@
import platform.test.screenshot.proto.ScreenshotResultProto
import platform.test.screenshot.utils.loadBitmap
+class CustomGoldenImagePathManager(appcontext: Context) : GoldenImagePathManager(appcontext) {
+ public override fun goldenIdentifierResolver(
+ testName: String,
+ relativePathOnly: Boolean,
+ localPath: Boolean
+ ): String = "$testName.png"
+}
+
@RunWith(AndroidJUnit4::class)
@MediumTest
class ScreenshotTestRuleTest {
@get:Rule
- val rule = ScreenshotTestRule()
-
- @Before
- fun setup() {
- rule.setCustomGoldenIdResolver { goldenId ->
- "$goldenId.png"
- }
- }
+ val rule = ScreenshotTestRule(
+ CustomGoldenImagePathManager(InstrumentationRegistry.getInstrumentation().getContext()))
@Test
fun performDiff_sameBitmaps() {
@@ -160,9 +164,8 @@
@After
fun after() {
- rule.clearCustomGoldenIdResolver()
// Clear all files we generated so we don't have dependencies between tests
- rule.deviceOutputDirectory.deleteRecursively()
+ File(rule.goldenImagePathManager.locationConfig.deviceLocalPath).deleteRecursively()
}
private fun expectErrorMessage(expectedErrorMessage: String, block: () -> Unit) {
diff --git a/libraries/screenshot/src/main/java/platform/test/screenshot/GoldenImagePathManager.kt b/libraries/screenshot/src/main/java/platform/test/screenshot/GoldenImagePathManager.kt
index 1f4e775..0d16d5c 100644
--- a/libraries/screenshot/src/main/java/platform/test/screenshot/GoldenImagePathManager.kt
+++ b/libraries/screenshot/src/main/java/platform/test/screenshot/GoldenImagePathManager.kt
@@ -63,14 +63,14 @@
val pathConfig: PathConfig = getDefaultPathConfig()
) {
- private val deviceLocalPath = locationConfig.deviceLocalPath
- private val repoRemotePath = locationConfig.repoRemotePath
- private val imageExtension = "png"
+ public val deviceLocalPath = locationConfig.deviceLocalPath
+ public val repoRemotePath = locationConfig.repoRemotePath
+ public val imageExtension = "png"
/*
* Uses [pathConfig] and [testName] to construct the full path to the golden image.
*/
- public fun goldenIdentifierResolver(
+ public open fun goldenIdentifierResolver(
testName: String,
relativePathOnly: Boolean = true,
localPath: Boolean = true
diff --git a/libraries/screenshot/src/main/java/platform/test/screenshot/PlatformScreenshotTestRule.kt b/libraries/screenshot/src/main/java/platform/test/screenshot/PlatformScreenshotTestRule.kt
index 891b98d..bb66c52 100644
--- a/libraries/screenshot/src/main/java/platform/test/screenshot/PlatformScreenshotTestRule.kt
+++ b/libraries/screenshot/src/main/java/platform/test/screenshot/PlatformScreenshotTestRule.kt
@@ -16,6 +16,8 @@
package platform.test.screenshot
+import android.content.Context
+
/**
* Rule to be used in platform project tests. Set's up the proper repository name and golden
* directory.
@@ -28,12 +30,9 @@
* @hide
*/
class PlatformScreenshotTestRule(
+ context: Context,
moduleDirectory: String,
outputRootDir: String? = null
) : ScreenshotTestRule(
- ScreenshotTestRuleConfig(
- "platform/frameworks/support-golden",
- moduleDirectory.trim('/')
- ),
- outputRootDir
+ GoldenImagePathManager(context)
)
diff --git a/libraries/screenshot/src/main/java/platform/test/screenshot/ScreenshotTestRule.kt b/libraries/screenshot/src/main/java/platform/test/screenshot/ScreenshotTestRule.kt
index 1dba78c..02571f8 100644
--- a/libraries/screenshot/src/main/java/platform/test/screenshot/ScreenshotTestRule.kt
+++ b/libraries/screenshot/src/main/java/platform/test/screenshot/ScreenshotTestRule.kt
@@ -19,7 +19,6 @@
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
-import android.os.Build
import android.os.Bundle
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.rules.TestRule
@@ -35,36 +34,6 @@
import java.io.FileOutputStream
import java.io.IOException
-// TODO(b/223901506): Replace this with the more advanced config class after the CL ag/17587688
-// is submitted.
-/**
- * Config for [ScreenshotTestRule].
- *
- * To be used to set up paths to golden images. These paths are not used to retrieve the goldens
- * during the test. They are just directly stored into the result proto file. The proto file can
- * then be used by CI to determined where to put the new approved goldens. Your tests assets
- * directory should be pointing to exactly the same path.
- *
- * @param repoRootPathForGoldens Path to the repo's root that contains the goldens. To be used by
- * CI.
- * @param pathToGoldensInRepo Relative path to goldens inside your [repoRootPathForGoldens].
- */
-class ScreenshotTestRuleConfig(
- val repoRootPathForGoldens: String = "",
- val pathToGoldensInRepo: String = ""
-)
-
-/**
- * Type of file that can be produced by the [ScreenshotTestRule].
- */
-internal enum class OutputFileType {
- IMAGE_ACTUAL,
- IMAGE_EXPECTED,
- IMAGE_DIFF,
- RESULT_PROTO,
- RESULT_BIN_PROTO
-}
-
/**
* Rule to be added to a test to facilitate screenshot testing.
*
@@ -79,29 +48,9 @@
*/
@SuppressLint("SyntheticAccessor")
open class ScreenshotTestRule(
- val config: ScreenshotTestRuleConfig = ScreenshotTestRuleConfig(),
- val outputRootDir: String? = null
+ val goldenImagePathManager: GoldenImagePathManager
) : TestRule {
- val deviceOutputRootDirectory: File? =
- if (outputRootDir != null) {
- File(outputRootDir)
- } else {
- InstrumentationRegistry.getInstrumentation().getContext().externalCacheDir
- }
-
- /**
- * Directory on the device that is used to store the output files.
- */
- val deviceOutputDirectory
- get() = File(
- deviceOutputRootDirectory,
- "platform_screenshots"
- )
-
- private val repoRootPathForGoldens = config.repoRootPathForGoldens.trim('/')
- private val pathToGoldensInRepo = config.pathToGoldensInRepo.trim('/')
- private val imageExtension = ".png"
private val resultBinaryProtoFileSuffix = ".pb"
// This is used in CI to identify the files.
private val resultProtoFileSuffix = "goldResult.textproto"
@@ -113,12 +62,9 @@
private lateinit var testIdentifier: String
private lateinit var deviceId: String
- private var goldenIdentifierResolver: ((String) -> String) = ::resolveGoldenName
-
private val testWatcher = object : TestWatcher() {
override fun starting(description: Description?) {
- deviceId = getDeviceModel()
- testIdentifier = "${description!!.className}_${description.methodName}_$deviceId"
+ testIdentifier = "${description!!.className}_${description.methodName}"
}
}
@@ -129,27 +75,10 @@
class ScreenshotTestStatement(private val base: Statement) : Statement() {
override fun evaluate() {
- // NOTE(ihcinihsdk@): My hunch is that we should not add these assumptions at all.
- // The reason is that this framework should be served for the general platform.
- // If a test is supposed to run on a specific type of device, it should be the
- // test authors' duty. What we need to do is to provide guidance on how to add
- // assumptions on type device and SDK version.
base.evaluate()
}
}
- internal fun setCustomGoldenIdResolver(resolver: ((String) -> String)) {
- goldenIdentifierResolver = resolver
- }
-
- internal fun clearCustomGoldenIdResolver() {
- goldenIdentifierResolver = ::resolveGoldenName
- }
-
- private fun resolveGoldenName(goldenIdentifier: String): String {
- return "${goldenIdentifier}_$deviceId$imageExtension"
- }
-
private fun fetchExpectedImage(goldenIdentifier: String): Bitmap? {
val instrument = InstrumentationRegistry.getInstrumentation()
return listOf(
@@ -157,7 +86,9 @@
instrument.context
).map {
try {
- it.assets.open(goldenIdentifierResolver(goldenIdentifier)).use {
+ it.assets.open(
+ goldenImagePathManager.goldenIdentifierResolver(goldenIdentifier)
+ ).use {
return@use BitmapFactory.decodeStream(it)
}
} catch (e: FileNotFoundException) {
@@ -205,7 +136,7 @@
)
throw AssertionError(
"Missing golden image " +
- "'${goldenIdentifierResolver(goldenIdentifier)}'. " +
+ "'${goldenImagePathManager.goldenIdentifierResolver(goldenIdentifier)}'. " +
"Did you mean to check in a new image?"
)
}
@@ -267,17 +198,13 @@
.addMetadata(
ScreenshotResultProto.Metadata.newBuilder()
.setKey("repoRootPath")
- .setValue(repoRootPathForGoldens))
+ .setValue(goldenImagePathManager.repoRemotePath))
if (comparisonStatistics != null) {
resultProto.comparisonStatistics = comparisonStatistics
}
resultProto.imageLocationGolden =
- if (pathToGoldensInRepo.isEmpty()) {
- goldenIdentifierResolver(goldenIdentifier)
- } else {
- "$pathToGoldensInRepo/${goldenIdentifierResolver(goldenIdentifier)}"
- }
+ goldenImagePathManager.goldenIdentifierResolver(goldenIdentifier)
val report = Bundle()
@@ -318,13 +245,16 @@
internal fun getPathOnDeviceFor(fileType: OutputFileType): File {
val fileName = when (fileType) {
- OutputFileType.IMAGE_ACTUAL -> "${testIdentifier}_actual$imageExtension"
- OutputFileType.IMAGE_EXPECTED -> "${testIdentifier}_expected$imageExtension"
- OutputFileType.IMAGE_DIFF -> "${testIdentifier}_diff$imageExtension"
+ OutputFileType.IMAGE_ACTUAL ->
+ "${testIdentifier}_actual$goldenImagePathManager.imageExtension"
+ OutputFileType.IMAGE_EXPECTED ->
+ "${testIdentifier}_expected$goldenImagePathManager.imageExtension"
+ OutputFileType.IMAGE_DIFF ->
+ "${testIdentifier}_diff$goldenImagePathManager.imageExtension"
OutputFileType.RESULT_PROTO -> "${testIdentifier}_$resultProtoFileSuffix"
OutputFileType.RESULT_BIN_PROTO -> "${testIdentifier}_$resultBinaryProtoFileSuffix"
}
- return File(deviceOutputDirectory, fileName)
+ return File(goldenImagePathManager.locationConfig.deviceLocalPath, fileName)
}
private fun Bitmap.writeToDevice(fileType: OutputFileType): File {
@@ -337,7 +267,8 @@
fileType: OutputFileType,
writeAction: (FileOutputStream) -> Unit
): File {
- if (!deviceOutputDirectory.exists() && !deviceOutputDirectory.mkdir()) {
+ val fileGolden = File(goldenImagePathManager.locationConfig.deviceLocalPath)
+ if (!fileGolden.exists() && !fileGolden.mkdir()) {
throw IOException("Could not create folder.")
}
@@ -354,14 +285,6 @@
}
return file
}
-
- private fun getDeviceModel(): String {
- var model = android.os.Build.MODEL.lowercase()
- arrayOf("phone", "x86", "x64", "gms").forEach {
- model = model.replace(it, "")
- }
- return model.trim().replace(" ", "_")
- }
}
internal fun Bitmap.toIntArray(): IntArray {
@@ -392,3 +315,14 @@
) {
rule.assertBitmapAgainstGolden(this, goldenIdentifier, matcher = matcher)
}
+
+/**
+ * Type of file that can be produced by the [ScreenshotTestRule].
+ */
+internal enum class OutputFileType {
+ IMAGE_ACTUAL,
+ IMAGE_EXPECTED,
+ IMAGE_DIFF,
+ RESULT_PROTO,
+ RESULT_BIN_PROTO
+}