summaryrefslogtreecommitdiffhomepage
path: root/android/test/common/src
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2022-12-28 14:51:06 +0100
committerAlbin <albin@mullvad.net>2023-01-10 15:32:38 +0100
commit332ebf63b4dd6abd54e57043e287865cf81fe713 (patch)
tree4612eeff18d56b552f75944ea8f45743f498a2a2 /android/test/common/src
parent42610bc223085e23181af2e679fce538e4b4b5c8 (diff)
downloadmullvadvpn-332ebf63b4dd6abd54e57043e287865cf81fe713.tar.xz
mullvadvpn-332ebf63b4dd6abd54e57043e287865cf81fe713.zip
Improve test failure screenshot support
This commit improves the test failure auto screenshot on newer devices. It also removes the auto-download of screenshots via gradle as it's rarely used.
Diffstat (limited to 'android/test/common/src')
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt122
1 files changed, 103 insertions, 19 deletions
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
index 73d515c501..f5bbe5fa6b 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
@@ -1,30 +1,114 @@
package net.mullvad.mullvadvpn.test.common.rule
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.graphics.Bitmap
+import android.os.Build
+import android.os.Environment
+import android.os.Environment.DIRECTORY_PICTURES
+import android.provider.MediaStore
import android.util.Log
-import androidx.test.runner.screenshot.BasicScreenCaptureProcessor
-import androidx.test.runner.screenshot.ScreenCaptureProcessor
-import androidx.test.runner.screenshot.Screenshot
-import java.time.LocalDateTime
-import java.time.format.DateTimeFormatter
+import androidx.annotation.RequiresApi
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.nio.file.Paths
+import java.time.OffsetDateTime
+import java.time.temporal.ChronoUnit
import org.junit.rules.TestWatcher
import org.junit.runner.Description
-class CaptureScreenshotOnFailedTestRule(private val logTag: String) : TestWatcher() {
- override fun failed(e: Throwable?, description: Description?) {
- Log.d(logTag, "Capturing screenshot of failed test: " + description?.methodName)
- val timestamp = DateTimeFormatter.ISO_DATE_TIME.format(LocalDateTime.now()).replace(":", "")
- val screenshotName = "$timestamp-${description?.methodName}"
- captureScreenshot(screenshotName)
+class CaptureScreenshotOnFailedTestRule(private val testTag: String) : TestWatcher() {
+
+ override fun failed(e: Throwable?, description: Description) {
+ Log.d(testTag, "Capturing screenshot of failed test: " + description.methodName)
+ val timestamp = OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)
+ val screenshotName = "$timestamp-${description.methodName}.jpeg"
+ captureScreenshot(testTag, screenshotName)
+ }
+
+ private fun captureScreenshot(baseDir: String, filename: String) {
+ val contentResolver = getInstrumentation().targetContext.applicationContext.contentResolver
+ val contentValues = createBaseScreenshotContentValues()
+
+ getInstrumentation().uiAutomation.takeScreenshot().apply {
+ if (Build.VERSION.SDK_INT >= 29) {
+ writeToMediaStore(
+ contentValues = contentValues,
+ contentResolver = contentResolver,
+ baseDir = baseDir,
+ filename = filename
+ )
+ } else {
+ writeToExternalStorage(
+ contentValues = contentValues,
+ contentResolver = contentResolver,
+ baseDir = baseDir,
+ filename = filename
+ )
+ }
+ }
+ }
+
+ @RequiresApi(29)
+ private fun Bitmap.writeToMediaStore(
+ contentValues: ContentValues,
+ contentResolver: ContentResolver,
+ baseDir: String,
+ filename: String
+ ) {
+ contentValues.apply {
+ put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
+ put(
+ MediaStore.Images.Media.RELATIVE_PATH,
+ "$DIRECTORY_PICTURES/$baseDir"
+ )
+ }
+
+ val uri =
+ contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
+
+ if (uri != null) {
+ contentResolver.openOutputStream(uri).use {
+ try {
+ this.compress(Bitmap.CompressFormat.JPEG, 50, it)
+ } catch (e: IOException) {
+ Log.e(testTag, "Unable to store screenshot: ${e.message}")
+ }
+ }
+ contentResolver.update(uri, contentValues, null, null)
+ } else {
+ Log.e(testTag, "Unable to store screenshot")
+ }
}
- private fun captureScreenshot(screenShotName: String) {
- try {
- val screenCapture = Screenshot.capture().apply { name = screenShotName }
- val processorSet: MutableSet<ScreenCaptureProcessor> = HashSet()
- processorSet.add(BasicScreenCaptureProcessor())
- screenCapture.process(processorSet)
- } catch (ex: Exception) {
- Log.d(logTag, "Error capturing screenshot: " + ex.message)
+ private fun Bitmap.writeToExternalStorage(
+ contentValues: ContentValues,
+ contentResolver: ContentResolver,
+ baseDir: String,
+ filename: String
+ ) {
+ val screenshotBaseDirectory = Paths.get(
+ Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES).path,
+ baseDir,
+ ).toFile().apply {
+ if (exists().not()) {
+ mkdirs()
+ }
}
+ FileOutputStream(File(screenshotBaseDirectory, filename)).use { outputStream ->
+ try {
+ this.compress(Bitmap.CompressFormat.JPEG, 50, outputStream)
+ } catch (e: IOException) {
+ Log.e(testTag, "Unable to store screenshot: ${e.message}")
+ }
+ }
+ contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
+ }
+
+ private fun createBaseScreenshotContentValues() = ContentValues().apply {
+ put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
+ put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
}
}