Skip to content

Commit

Permalink
Merge pull request #65 from Malinskiy/feat/no-external-storage
Browse files Browse the repository at this point in the history
feat(android): write results to app data storage
  • Loading branch information
viclovsky authored Dec 16, 2021
2 parents 0a43698 + 849222f commit 0ef6017
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 61 deletions.
29 changes: 13 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,25 +105,22 @@ android {
```

##### Integration
As on-device instrumentation test run on an actual device, the results have to be saved there as well. To do so permissions for accessing external storage are needed. If your app doesn't have those permissions, you can include them only in your debug build type (or any other build type under which the tests are executed):

**src/debug/AndroidManifest.xml**
```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.qameta.allure.sample.junit4.android">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
</manifest>
```
As on-device instrumentation test run on an actual device, the results have to be saved there as well.
You don't need to add any permissions to manifest: results are saved in an app files directory, e.g.
`/data/data/com.example/files/allure-results`.

Moreover, Allure will grant itself those permissions at runtime, so you don't have to place any special logic for Android 6.0+ devices.

After the tests are finished you can pull the results from the external storage using an **adb** command like this one:
After the tests are finished you can move the results to the external storage and pull the files using an **adb** like this one:
```
adb pull /sdcard/allure-results
# Assuming your package is com.example
adb exec-out run-as com.example sh -c 'cd /data/data/com.example/files && tar cf - allure-results' > allure-results.tar
# Or using pull
$ adb shell
$ run-as com.example sh -c 'cd /data/data/com.example/files && tar cf - allure-results' | tar xvf - -C /data/local/tmp
# Ignore the permission errors
$ exit
$ adb pull /data/local/tmp/allure-results
```
Finally, you can generate the report via Allure CLI (see the [Allure Documentation][allure-cli]) or generate report with [allure-gradle][allure-gradle-plugin] plugin.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.qameta.allure.android

import android.os.Environment
import androidx.test.platform.app.InstrumentationRegistry
import io.qameta.allure.kotlin.AllureLifecycle
import io.qameta.allure.kotlin.FileSystemResultsWriter
import io.qameta.allure.kotlin.util.PropertiesUtils
Expand All @@ -14,5 +14,5 @@ object AllureAndroidLifecycle : AllureLifecycle(writer = FileSystemResultsWriter
*/
private fun obtainResultsDirectory(): File {
val defaultAllurePath = PropertiesUtils.resultsDirectoryPath
return File(Environment.getExternalStorageDirectory(), defaultAllurePath)
}
return File(InstrumentationRegistry.getInstrumentation().targetContext.filesDir, defaultAllurePath)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package io.qameta.allure.android.internal

import android.annotation.SuppressLint
import android.os.Build
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.permission.PermissionRequester
import androidx.test.uiautomator.UiDevice
import java.io.File

Expand All @@ -19,29 +17,6 @@ import java.io.File
internal fun isDeviceTest(): Boolean =
System.getProperty("java.runtime.name")?.lowercase()?.contains("android") ?: false

internal fun requestExternalStoragePermissions() {
when {
Build.VERSION.SDK_INT > Build.VERSION_CODES.M && Build.VERSION.SDK_INT <= Build.VERSION_CODES.P -> {
with(PermissionRequester()) {
addPermissions("android.permission.WRITE_EXTERNAL_STORAGE")
addPermissions("android.permission.READ_EXTERNAL_STORAGE")
requestPermissions()
}
}
Build.VERSION.SDK_INT == Build.VERSION_CODES.Q -> {
uiDevice?.let {
it.executeShellCommand("appops set --uid ${InstrumentationRegistry.getInstrumentation().targetContext.packageName} LEGACY_STORAGE allow")
}
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
uiDevice?.let {
it.executeShellCommand("appops set --uid ${InstrumentationRegistry.getInstrumentation().targetContext.packageName} MANAGE_EXTERNAL_STORAGE allow")
}
}
else -> return
}
}

/**
* Retrieves [UiDevice] if it's available, otherwise null is returned.
* In Robolectric tests [UiDevice] is inaccessible and this property serves as a safe way of accessing it.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.runner.AndroidJUnitRunner
import io.qameta.allure.android.AllureAndroidLifecycle
import io.qameta.allure.android.internal.isDeviceTest
import io.qameta.allure.android.internal.requestExternalStoragePermissions
import io.qameta.allure.android.listeners.ExternalStoragePermissionsListener
import io.qameta.allure.kotlin.Allure
import io.qameta.allure.kotlin.junit4.AllureJunit4
import org.junit.runner.*
import org.junit.runner.manipulation.*
import org.junit.runner.notification.*

/**
* Wrapper over [AndroidJUnit4] that attaches the [AllureJunit4] listener and
* grants external storage permissions for tests running on a device (required for the test results to be saved).
* Wrapper over [AndroidJUnit4] that attaches the [AllureJunit4] listener
*/
class AllureAndroidJUnit4(clazz: Class<*>) : Runner(), Filterable, Sortable {

Expand All @@ -31,7 +28,6 @@ class AllureAndroidJUnit4(clazz: Class<*>) : Runner(), Filterable, Sortable {

private fun createListener(): RunListener? =
if (isDeviceTest()) {
requestExternalStoragePermissions()
createDeviceListener()
} else {
createRobolectricListener()
Expand Down Expand Up @@ -77,7 +73,6 @@ open class AllureAndroidJUnitRunner : AndroidJUnitRunner() {
Allure.lifecycle = AllureAndroidLifecycle
val listenerArg = listOfNotNull(
arguments.getCharSequence("listener"),
ExternalStoragePermissionsListener::class.java.name,
AllureJunit4::class.java.name
).joinToString(separator = ",")
arguments.putCharSequence("listener", listenerArg)
Expand Down

0 comments on commit 0ef6017

Please sign in to comment.