Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

148: Refactor output path into Destination #162

Merged
merged 6 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@

### Library

#### Changed

- Internal file management is now abstracted through the new `Destination` interface.
This interface allows for extensibility and customization of the file handling. It is backwards compatible with
the existing SDCard and app data/data directory options.

#### Bug fixes

- Fix https://github.com/ndtp/android-testify/issues/81: `reportShow` and `reportPull` now support Gradle 7+.
- Exceptions now correctly report the gradle module name of the source of the error.

#### Added

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ import dev.testify.internal.DeviceStringFormatter
import dev.testify.internal.formatDeviceString
import dev.testify.internal.getDeviceDescription
import dev.testify.internal.helpers.loadAsset
import dev.testify.internal.output.getFileRelativeToRoot
import dev.testify.internal.output.getOutputFilePath
import dev.testify.output.getDestination
import dev.testify.output.getFileRelativeToRoot
import dev.testify.testDescription
import java.io.File
import java.io.InputStreamReader
Expand Down Expand Up @@ -74,8 +74,12 @@ private fun getOutputFile(context: Context, description: TestDescription): File
),
DEFAULT_NAME_FORMAT
)
val outputPath = getOutputFilePath(context, fileName, JSON_EXTENSION)
return File(outputPath)
val destination = getDestination(
context = context,
fileName = fileName,
extension = JSON_EXTENSION
)
return destination.file
}

private const val JSON_EXTENSION = ".a11y.json"
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,19 @@ import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.view.View
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.uiautomator.UiDevice
import dev.testify.ScreenshotRule
import dev.testify.exception.FailedToCaptureFullscreenBitmapException
import dev.testify.exception.FailedToLoadCapturedBitmapException
import dev.testify.internal.DEFAULT_NAME_FORMAT
import dev.testify.internal.DeviceStringFormatter
import dev.testify.internal.exception.ScreenshotDirectoryNotFoundException
import dev.testify.internal.formatDeviceString
import dev.testify.internal.output.getOutputDirectoryPath
import dev.testify.internal.output.getOutputFilePath
import dev.testify.internal.output.useSdCard
import dev.testify.testDescription
import java.io.File
import dev.testify.assureScreenshotDirectory
import dev.testify.loadBitmapFromFile
import dev.testify.output.Destination
import dev.testify.output.getDestination
import dev.testify.preferredBitmapOptions
import dev.testify.testDescription

/**
* Use the UiAutomator's built-in screenshotting capability to capture a [Bitmap] of the entire device.
Expand All @@ -69,12 +64,14 @@ import dev.testify.preferredBitmapOptions
*/
@Suppress("UNUSED_PARAMETER")
fun fullscreenCapture(activity: Activity, targetView: View?): Bitmap {
activity.assureScreenshotDirectory()

val instrumentation = InstrumentationRegistry.getInstrumentation()
val instrumentation = getInstrumentation()
val fileName = getFileName(instrumentation.context)
val outputPath = getOutputFilePath(activity, fileName)
val file = File(outputPath)
val destination = getDestination(activity, fileName)

destination.assureScreenshotDirectory(activity)

val file = destination.file

// Use UiAutomator to take a screenshot
val device = UiDevice.getInstance(instrumentation)
Expand All @@ -85,22 +82,19 @@ fun fullscreenCapture(activity: Activity, targetView: View?): Bitmap {
* The screenshot is written as a PNG to [file] on the emulator. We can use [loadBitmapFromFile]
* to load it from a file into memory as a [Bitmap].
*/
return loadBitmapFromFile(outputPath, preferredBitmapOptions)

return destination.loadBitmap(preferredBitmapOptions)
?: throw FailedToLoadCapturedBitmapException()
}

/**
* Make sure the directory used to save Bitmaps on the device is valid and available.
*
* @throws ScreenshotDirectoryNotFoundException
* @throws Exception
*/
private fun Context.assureScreenshotDirectory() {
if (assureScreenshotDirectory(this)) return

throw ScreenshotDirectoryNotFoundException(
useSdCard = useSdCard(InstrumentationRegistry.getArguments()),
path = getOutputDirectoryPath(this).absolutePath
)
private fun Destination.assureScreenshotDirectory(context: Context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this method be part of Destination class? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a convenience wrapper around Destination.assureDestination() which checks the return value of assureDestination() and throws an exception if it's false.

if (this.assureDestination(context)) return
throw this.getScreenshotDestinationNotFoundException()
}

/**
Expand Down
75 changes: 0 additions & 75 deletions Library/src/androidTest/java/dev/testify/OutputFilePathTest.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@ package dev.testify
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.rule.ActivityTestRule
import dev.testify.internal.output.getOutputFilePath
import dev.testify.internal.processor.capture.createBitmapFromDrawingCache
import dev.testify.output.getDestination
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File

@RunWith(AndroidJUnit4::class)
class ScreenshotUtilityTest {
Expand All @@ -57,8 +56,8 @@ class ScreenshotUtilityTest {
fun createBitmapFromActivity() {
val activity = testActivityRule.activity
val rootView = activity.findViewById<View>(R.id.test_root_view)
val outputFilePath = getOutputFilePath(activity, "testing")
val bitmapFile = File(outputFilePath)
val destination = getDestination(context = activity, fileName = "testing")
val bitmapFile = destination.file

val capturedBitmap = createBitmapFromActivity(
activity = activity,
Expand All @@ -77,10 +76,10 @@ class ScreenshotUtilityTest {
createBitmapFromActivity()

val fileName = "testing"
val outputFilePath = getOutputFilePath(activity, fileName)
val destination = getDestination(context = activity, fileName = fileName)

deleteBitmap(activity, fileName)
val fileThatShouldBeDeleted = File(outputFilePath)
deleteBitmap(destination)
val fileThatShouldBeDeleted = destination.file
assertFalse(fileThatShouldBeDeleted.exists())
}
}
10 changes: 9 additions & 1 deletion Library/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application />
<application>
<meta-data
android:name="dev.testify.destination"
android:value="@string/testifyDestination" />

<meta-data
android:name="dev.testify.module"
android:value="@string/testifyModule" />
</application>

</manifest>
9 changes: 4 additions & 5 deletions Library/src/main/java/dev/testify/ScreenshotRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

package dev.testify

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -73,13 +74,13 @@ import dev.testify.internal.helpers.EspressoActions
import dev.testify.internal.helpers.EspressoHelper
import dev.testify.internal.helpers.ResourceWrapper
import dev.testify.internal.helpers.registerActivityProvider
import dev.testify.internal.output.doesOutputFileExist
import dev.testify.internal.processor.capture.canvasCapture
import dev.testify.internal.processor.capture.createBitmapFromDrawingCache
import dev.testify.internal.processor.capture.pixelCopyCapture
import dev.testify.internal.processor.compare.FuzzyCompare
import dev.testify.internal.processor.compare.sameAsCompare
import dev.testify.internal.processor.diff.HighContrastDiff
import dev.testify.output.getDestination
import dev.testify.report.ReportSession
import dev.testify.report.Reporter
import org.junit.Assert.assertTrue
Expand Down Expand Up @@ -154,9 +155,6 @@ open class ScreenshotRule<T : Activity> @JvmOverloads constructor(
}
}

val outputFileExists: Boolean
get() = doesOutputFileExist(activity, outputFileName)

private fun isRunningOnUiThread(): Boolean {
return Looper.getMainLooper().thread == Thread.currentThread()
}
Expand Down Expand Up @@ -298,6 +296,7 @@ open class ScreenshotRule<T : Activity> @JvmOverloads constructor(

@get:LayoutRes
private val TestifyLayout.resolvedLayoutId: Int
@SuppressLint("DiscouragedApi")
get() {
if (this.layoutResName.isNotEmpty()) {
return getInstrumentation().targetContext.resources?.getIdentifier(layoutResName, null, null)
Expand Down Expand Up @@ -562,7 +561,7 @@ open class ScreenshotRule<T : Activity> @JvmOverloads constructor(
if (compareBitmaps(baselineBitmap, currentBitmap)) {
assertTrue(
"Could not delete cached bitmap ${description.name}",
deleteBitmap(activity, outputFileName)
deleteBitmap(getDestination(activity, outputFileName))
)
} else {
if (TestifyFeatures.GenerateDiffs.isEnabled(activity)) {
Expand Down
Loading