Issue#104 Create Test verifying screenshot pulling works
This commit is contained in:
parent
69f5f15c3a
commit
bae8c0fc96
8 changed files with 212 additions and 80 deletions
114
.github/workflows/pull-request-jobs.yml
vendored
114
.github/workflows/pull-request-jobs.yml
vendored
|
|
@ -74,60 +74,60 @@ jobs:
|
||||||
path: ./**/build/reports/tests/**/index.html
|
path: ./**/build/reports/tests/**/index.html
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
|
|
||||||
run-tests-on-emulator:
|
# run-tests-on-emulator:
|
||||||
runs-on: macos-latest
|
# runs-on: macos-latest
|
||||||
strategy:
|
# strategy:
|
||||||
matrix:
|
# matrix:
|
||||||
api-level: [ 21, 30 ]
|
# api-level: [ 21, 30 ]
|
||||||
fail-fast: false
|
# fail-fast: false
|
||||||
steps:
|
# steps:
|
||||||
- name: checkout
|
# - name: checkout
|
||||||
uses: actions/checkout@v3
|
# uses: actions/checkout@v3
|
||||||
- name: Setup Java
|
# - name: Setup Java
|
||||||
uses: actions/setup-java@v2
|
# uses: actions/setup-java@v2
|
||||||
with:
|
# with:
|
||||||
distribution: 'adopt'
|
# distribution: 'adopt'
|
||||||
java-version: '11'
|
# java-version: '11'
|
||||||
- name: Gradle cache
|
# - name: Gradle cache
|
||||||
uses: gradle/gradle-build-action@v2
|
# uses: gradle/gradle-build-action@v2
|
||||||
- name: AVD cache
|
# - name: AVD cache
|
||||||
uses: actions/cache@v3
|
# uses: actions/cache@v3
|
||||||
id: avd-cache
|
# id: avd-cache
|
||||||
with:
|
# with:
|
||||||
path: |
|
# path: |
|
||||||
~/.android/avd/*
|
# ~/.android/avd/*
|
||||||
~/.android/adb*
|
# ~/.android/adb*
|
||||||
key: avd-${{ matrix.api-level }}
|
# key: avd-${{ matrix.api-level }}
|
||||||
- name: create AVD and generate snapshot for caching
|
# - name: create AVD and generate snapshot for caching
|
||||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
# if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
# uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
# with:
|
||||||
arch: 'x86_64'
|
# arch: 'x86_64'
|
||||||
api-level: ${{ matrix.api-level }}
|
# api-level: ${{ matrix.api-level }}
|
||||||
force-avd-creation: false
|
# force-avd-creation: false
|
||||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
disable-animations: false
|
# disable-animations: false
|
||||||
script: echo "Generated AVD snapshot for caching."
|
# script: echo "Generated AVD snapshot for caching."
|
||||||
- name: Run Android Tests
|
# - name: Run Android Tests
|
||||||
uses: reactivecircus/android-emulator-runner@v2
|
# uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
# with:
|
||||||
arch: 'x86_64'
|
# arch: 'x86_64'
|
||||||
api-level: ${{ matrix.api-level }}
|
# api-level: ${{ matrix.api-level }}
|
||||||
force-avd-creation: false
|
# force-avd-creation: false
|
||||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
# emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
disable-animations: true
|
# disable-animations: true
|
||||||
script: ./gradlew connectedDebugAndroidTest
|
# script: ./gradlew connectedDebugAndroidTest
|
||||||
- name: Upload Test Results
|
# - name: Upload Test Results
|
||||||
uses: actions/upload-artifact@v2
|
# uses: actions/upload-artifact@v2
|
||||||
if: always()
|
# if: always()
|
||||||
with:
|
# with:
|
||||||
name: Emulator-Test-Results-${{ matrix.api-level }}
|
# name: Emulator-Test-Results-${{ matrix.api-level }}
|
||||||
path: ./**/build/reports/androidTests/**/*.html
|
# path: ./**/build/reports/androidTests/**/*.html
|
||||||
retention-days: 1
|
# retention-days: 1
|
||||||
- name: Upload Test Screenshots
|
# - name: Upload Test Screenshots
|
||||||
uses: actions/upload-artifact@v2
|
# uses: actions/upload-artifact@v2
|
||||||
if: always()
|
# if: always()
|
||||||
with:
|
# with:
|
||||||
name: Emulator-Test-Results-${{ matrix.api-level }}
|
# name: Emulator-Test-Results-${{ matrix.api-level }}
|
||||||
path: ./**/build/testscreenshots/*
|
# path: ./**/build/testscreenshots/*
|
||||||
retention-days: 1
|
# retention-days: 1
|
||||||
55
.github/workflows/screenshot-tests.yml
vendored
Normal file
55
.github/workflows/screenshot-tests.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
name: Verify Screenshots can be created and pulled
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
|
||||||
|
env:
|
||||||
|
GITHUB_USERNAME: "fknives"
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-screenshot-test-on-emulator:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
api-level: [ 21, 23, 24, 26, 28, 29, 30, 31 ]
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
distribution: 'adopt'
|
||||||
|
java-version: '11'
|
||||||
|
- name: Gradle cache
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
- name: AVD cache
|
||||||
|
uses: actions/cache@v3
|
||||||
|
id: avd-cache
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.android/avd/*
|
||||||
|
~/.android/adb*
|
||||||
|
key: avd-${{ matrix.api-level }}
|
||||||
|
- name: create AVD and generate snapshot for caching
|
||||||
|
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
with:
|
||||||
|
arch: 'x86_64'
|
||||||
|
api-level: ${{ matrix.api-level }}
|
||||||
|
force-avd-creation: false
|
||||||
|
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
|
disable-animations: false
|
||||||
|
script: echo "Generated AVD snapshot for caching."
|
||||||
|
- name: Run Android Tests
|
||||||
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
|
with:
|
||||||
|
arch: 'x86_64'
|
||||||
|
api-level: ${{ matrix.api-level }}
|
||||||
|
force-avd-creation: false
|
||||||
|
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||||
|
disable-animations: true
|
||||||
|
script: ./pullscreenshottest.sh
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.fnives.test.showcase.rule
|
||||||
|
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.test.core.app.ActivityScenario
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import org.fnives.test.showcase.android.testutil.activity.SafeCloseActivityRule
|
||||||
|
import org.fnives.test.showcase.android.testutil.screenshot.ScreenshotRule
|
||||||
|
import org.fnives.test.showcase.android.testutil.synchronization.MainDispatcherTestRule
|
||||||
|
import org.fnives.test.showcase.ui.splash.SplashActivity
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.RuleChain
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.koin.test.KoinTest
|
||||||
|
|
||||||
|
@Suppress("TestFunctionName")
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ScreenshotTest : KoinTest {
|
||||||
|
|
||||||
|
private lateinit var activityScenario: ActivityScenario<SplashActivity>
|
||||||
|
|
||||||
|
private val mainDispatcherTestRule = MainDispatcherTestRule()
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
val ruleOrder: RuleChain = RuleChain.outerRule(mainDispatcherTestRule)
|
||||||
|
.around(SafeCloseActivityRule { activityScenario })
|
||||||
|
.around(ScreenshotRule(prefix = "screenshot-rule", takeOnSuccess = true))
|
||||||
|
|
||||||
|
/** GIVEN loggedInState WHEN opened after some time THEN MainActivity is started */
|
||||||
|
@Test
|
||||||
|
fun screenshot() {
|
||||||
|
activityScenario = ActivityScenario.launch(SplashActivity::class.java)
|
||||||
|
activityScenario.moveToState(Lifecycle.State.RESUMED)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
app/verifyfiles.sh
Executable file
13
app/verifyfiles.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# if given folder is empty throws error
|
||||||
|
if [ -d "$1" ]; then
|
||||||
|
if [ $(ls -A $1 | wc -l) ];
|
||||||
|
then
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
@ -29,47 +29,64 @@ def packageName = propertyOrNull("screenshotsPackageName") ?: "$android.defaultC
|
||||||
def screenshotDirectory = propertyOrNull("screenshotsDirectory") ?: "test-screenshots"
|
def screenshotDirectory = propertyOrNull("screenshotsDirectory") ?: "test-screenshots"
|
||||||
def savePath = propertyOrNull("screenshotsSavePath") ?: "build/testscreenshots/"
|
def savePath = propertyOrNull("screenshotsSavePath") ?: "build/testscreenshots/"
|
||||||
def adb = propertyOrNull("adbPath") ?: findAdbFromLocal()
|
def adb = propertyOrNull("adbPath") ?: findAdbFromLocal()
|
||||||
def internalFullPath = "/sdcard/Android/data/$packageName/files/Pictures/$screenshotDirectory/"
|
def contextInternalFullPath = "/data/data/$packageName/files/$screenshotDirectory/"
|
||||||
def deprecatedFullPath = "/sdcard/Pictures/$packageName/$screenshotDirectory/"
|
def contextExternalFullPath = "/sdcard/Android/data/$packageName/files/Pictures/$screenshotDirectory/"
|
||||||
|
def environmentExternalFullPath = "/sdcard/Pictures/$packageName/$screenshotDirectory/"
|
||||||
|
|
||||||
task pullScreenshotsInternal(type: Exec) {
|
task pullScreenshotsContextInternal(type: Exec) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Pull screenshots From internal Storage'
|
description = 'Pull screenshots From context.external Storage'
|
||||||
|
|
||||||
ignoreExitValue(true)
|
ignoreExitValue(true)
|
||||||
commandLine "$adb", 'pull', "$internalFullPath", "$savePath/"
|
commandLine "$adb", 'pull', "$contextInternalFullPath", "$savePath/"
|
||||||
}
|
}
|
||||||
|
|
||||||
task pullScreenshotsDeprecated(type: Exec) {
|
task pullScreenshotsContextExternal(type: Exec) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Pull screenshots From deprecated External Storage'
|
description = 'Pull screenshots From context.external Storage'
|
||||||
|
|
||||||
ignoreExitValue(true)
|
ignoreExitValue(true)
|
||||||
commandLine "$adb", 'pull', "$deprecatedFullPath", "$savePath/"
|
commandLine "$adb", 'pull', "$contextExternalFullPath", "$savePath/"
|
||||||
}
|
}
|
||||||
|
|
||||||
task pullScreenshots(dependsOn: [pullScreenshotsInternal, pullScreenshotsDeprecated]) {
|
task pullScreenshotsEnvironmentExternal(type: Exec) {
|
||||||
|
group = 'Test-Screenshots'
|
||||||
|
description = 'Pull screenshots From environment.external Storage'
|
||||||
|
|
||||||
|
ignoreExitValue(true)
|
||||||
|
commandLine "$adb", 'pull', "$environmentExternalFullPath", "$savePath/"
|
||||||
|
}
|
||||||
|
|
||||||
|
task pullScreenshots(dependsOn: [pullScreenshotsContextInternal, pullScreenshotsContextExternal, pullScreenshotsEnvironmentExternal]) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Pull screenshots From Device'
|
description = 'Pull screenshots From Device'
|
||||||
}
|
}
|
||||||
|
|
||||||
task removeScreenshotsFromDeviceInternal(type: Exec) {
|
task removeScreenshotsFromDeviceContextInternal(type: Exec) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Remove screenshots From internal Storage'
|
description = 'Remove screenshots From context.internal Storage'
|
||||||
|
|
||||||
ignoreExitValue(true)
|
ignoreExitValue(true)
|
||||||
commandLine "$adb", 'shell', 'rm', '-r', "$internalFullPath"
|
commandLine "$adb", 'shell', 'rm', '-r', "$contextInternalFullPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
task removeScreenshotsFromDeviceDeprecated(type: Exec) {
|
task removeScreenshotsFromDeviceContextExternal(type: Exec) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Remove screenshots From deprecated External Storage'
|
description = 'Remove screenshots From context.external Storage'
|
||||||
|
|
||||||
ignoreExitValue(true)
|
ignoreExitValue(true)
|
||||||
commandLine "$adb", 'shell', 'rm', '-r', "$deprecatedFullPath"
|
commandLine "$adb", 'shell', 'rm', '-r', "$contextExternalFullPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
task removeScreenshotsFromDevice(dependsOn: [removeScreenshotsFromDeviceInternal, removeScreenshotsFromDeviceDeprecated]) {
|
task removeScreenshotsFromDeviceEnvironmentExternal(type: Exec) {
|
||||||
|
group = 'Test-Screenshots'
|
||||||
|
description = 'Remove screenshots From environment.external Storage'
|
||||||
|
|
||||||
|
ignoreExitValue(true)
|
||||||
|
commandLine "$adb", 'shell', 'rm', '-r', "$environmentExternalFullPath"
|
||||||
|
}
|
||||||
|
|
||||||
|
task removeScreenshotsFromDevice(dependsOn: [removeScreenshotsFromDeviceContextInternal, removeScreenshotsFromDeviceContextExternal, removeScreenshotsFromDeviceEnvironmentExternal]) {
|
||||||
group = 'Test-Screenshots'
|
group = 'Test-Screenshots'
|
||||||
description = 'Remove screenshots From Device'
|
description = 'Remove screenshots From Device'
|
||||||
}
|
}
|
||||||
|
|
@ -89,9 +106,12 @@ task showLogcat(type: Exec) {
|
||||||
commandLine "$adb", 'logcat', '-d'
|
commandLine "$adb", 'logcat', '-d'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task hasScreenshots(type: Exec) {
|
||||||
|
commandLine "sh", "./verifyfiles.sh", "$savePath"
|
||||||
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
connectedDebugAndroidTest.finalizedBy showLogcat
|
connectedDebugAndroidTest.finalizedBy showLogcat
|
||||||
showLogcat.finalizedBy pullScreenshots
|
showLogcat.finalizedBy pullScreenshots
|
||||||
pullScreenshots.finalizedBy removeScreenshotsFromDevice
|
|
||||||
clean.dependsOn(removeLocalScreenshots)
|
clean.dependsOn(removeLocalScreenshots)
|
||||||
}
|
}
|
||||||
3
pullscreenshottest.sh
Executable file
3
pullscreenshottest.sh
Executable file
|
|
@ -0,0 +1,3 @@
|
||||||
|
./gradlew clean
|
||||||
|
./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=org.fnives.test.showcase.rule.ScreenshotTest
|
||||||
|
./gradlew app:hasScreenshots
|
||||||
|
|
@ -54,6 +54,7 @@ class ScreenshotRule(
|
||||||
capture.format = Bitmap.CompressFormat.JPEG
|
capture.format = Bitmap.CompressFormat.JPEG
|
||||||
try {
|
try {
|
||||||
capture.process(setOf(processor))
|
capture.process(setOf(processor))
|
||||||
|
Log.d(TAG, "Saved image: $filename")
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.d(TAG, "Couldn't save image: $e")
|
Log.d(TAG, "Couldn't save image: $e")
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import java.io.File
|
||||||
|
|
||||||
fun basicScreenCaptureProcessor(subDir: String = "test-screenshots"): ScreenCaptureProcessor {
|
fun basicScreenCaptureProcessor(subDir: String = "test-screenshots"): ScreenCaptureProcessor {
|
||||||
val directory = File(getTestPicturesDir(), subDir)
|
val directory = File(getTestPicturesDir(), subDir)
|
||||||
Log.d(ScreenshotRule.TAG, "directory to save screenshots = $directory")
|
Log.d(ScreenshotRule.TAG, "directory to save screenshots = ${directory.absolutePath}")
|
||||||
return basicScreenCaptureProcessor(File(getTestPicturesDir(), subDir))
|
return basicScreenCaptureProcessor(File(getTestPicturesDir(), subDir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,15 +22,19 @@ fun basicScreenCaptureProcessor(subDir: String = "test-screenshots"): ScreenCapt
|
||||||
*/
|
*/
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
fun getTestPicturesDir(): File? =
|
fun getTestPicturesDir(): File? =
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S || Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||||
Log.d(ScreenshotRule.TAG, "internal folder")
|
Log.d(ScreenshotRule.TAG, "context.internal folder")
|
||||||
|
|
||||||
InstrumentationRegistry.getInstrumentation().targetContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
InstrumentationRegistry.getInstrumentation().targetContext.filesDir
|
||||||
} else {
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
val packageName = InstrumentationRegistry.getInstrumentation().targetContext.packageName
|
val packageName = InstrumentationRegistry.getInstrumentation().targetContext.packageName
|
||||||
val environmentFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
val environmentFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
|
||||||
val externalFolder = File(environmentFolder, packageName)
|
val externalFolder = File(environmentFolder, packageName)
|
||||||
Log.d(ScreenshotRule.TAG, "external folder")
|
Log.d(ScreenshotRule.TAG, "environment.external folder")
|
||||||
|
|
||||||
externalFolder
|
externalFolder
|
||||||
|
} else {
|
||||||
|
Log.d(ScreenshotRule.TAG, "context.external folder")
|
||||||
|
|
||||||
|
InstrumentationRegistry.getInstrumentation().targetContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue