Skip to content

Commit c3eb918

Browse files
Android screenshot tests (#2809)
* Make the screenshot tests run in an off frame buffer and correct gamma issues in screenshots * Make the definition of "the same" a bit more flexible to avoid instability in the pipelines * Restore gamma correction * Set the colourspace for the off renderTexture * Set the Srgb for the off renderTexture * Rebake minor visual changes for off frame buffer * Rearrange for submodule screenshot structure * Add in dependencies for android * Bring it closer to the android initialiser project * Temporarily use non local android jme * Simple screenshot test * Wait for emulator * Dont save a snapshot, use mesa * Make the emulator logs less likely to hang * Bit closer to the android-emulator-runner docs * Add logging in test * Try a more modern pixel copy * Capture logcat * Only get my applications logcat * Pull logs inside app step * Prevent snapshots (which are erroring) * Actually grab the logcat * Use the actual location of the file * Save file to public directory * The whole logcat isn't too long * Pull image from quoted location * Whole log cat actually a bit much to put in github logs * Use latch to wait explicitly for write to complete * Clean up the test code * Go back to scoped storage as permissions do not allow downloads folder * Pull file from within test * Use explicit file location * Revert "Use explicit file location" This reverts commit b0ed44d. * Revert "Pull file from within test" This reverts commit b9d850c. * Avoid auto unistall (which means I can't get the file) * Try to get JME to render into the test * Fresh emulator every time * Take the screenshot from the glSurfaceView * Move the screenshot framework to a shared environment * Extract out one of the tests ready for reuse * Start introducing shared android screenshot functionality * Allow for test scenarios to be booted to both android and desktop * Start splitting out android specific elements * Introduce androidx-storage to save the report persistently * Change from BufferedImage to JME Image for android compatibility * Work towards allowing android to write a proto report * Hook in workflow for android screenshots * Hook in workflow for android screenshots * Clean up ExtentReportExtensionJunit4 * Avoid reuse of AssetManager (as we are registering random folders) * Give gradle more heap for build (specifically for the android build) * Remove redundant request to write to external storage * Run the adb pulls even if the gradle step fails * Add the upgrade step for the report * Use more modern android for jackson support * Use x86_64 android * Use x86_64 android * Even more modern android * Try 35 as docs only go up to 35 * Remove the matrix as we only run one * Install test services before running test * Debug error codes * Create report directory before pulling to it * Format the android screenshot tests readme * Error if upgrade of report fails * Correct upgrade code to access the files with absolute paths * Try to trap the error code better * One giant line of doom * One giant line of doom 2 * Just say -1 for a fail * Ensure report has a title * Reinstate deserialisation constructor * Migrate all tests to be android & desktop tests * Ensure that we get a single test report * Run the whole thing in a single shell * Include logcat * Increase ram for emulator * Allow app to have large heap * Even larger heap * Remove some of the more memory intensive tests * Remove some more of the more memory intensive tests * Correct the calculateImageFilePrefix so it is flexible to thread depth which android can mess with) * Remove more memory intensive tests * Try for a wider device * Try to find available profiles * Try to find available profiles * Initialise the reference images * Load references images from resources (to make android happy) * Correct colours are ints, not bytes (as unsigned) * Use consistent pixel comparison * Log pixel errors * Fix inverted "very similar" test * Set android tests to only run on push * Restore android harness as it was * Self review * Single subshell to avoid EOF issues * Avoid richard actually being contacted by the message * Wrap whole shell in a > * Natives moved out of project * More recent java version * Update location of desktop screenshot tests * Fix AndroidTestHarness for change in AndroidHarnessFragment * Ensure file load still works for screenshot tests * Move reference files within normal resources * All desktop screenshot tests with their correct base * Use same layout as in the android example * Simpler layout * Correct javadoc * Correct attached image save location * Gen the generated images back from the android run if they are different sizes * .png suffix on changeed images * Restore accidentally changed ScenarioPostWater values * Rebake images at new size * Rebake images at new size * Add missing copywright notices * Add missing reference images * Don't prematurely fail test, allow all images to be collected * Add missing images * Replace ImagePixelWrapper with the Raster for more cross format pixel manipulation
1 parent 4f2fe11 commit c3eb918

162 files changed

Lines changed: 4906 additions & 1904 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Android Screenshot Test
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- v3.7
8+
- v3.6
9+
- v3.5
10+
- v3.4
11+
- v3.3
12+
- ios-2024_2
13+
pull_request:
14+
15+
jobs:
16+
screenshot-test-android:
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 20
19+
steps:
20+
- name: checkout
21+
uses: actions/checkout@v6
22+
- name: Setup the java environment
23+
uses: actions/setup-java@v5
24+
with:
25+
distribution: 'temurin'
26+
java-version: '25'
27+
- name: Enable KVM
28+
run: |
29+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
30+
sudo udevadm control --reload-rules
31+
sudo udevadm trigger --name-match=kvm
32+
33+
- name: Gradle cache
34+
uses: gradle/actions/setup-gradle@v5
35+
36+
- name: AVD cache
37+
uses: actions/cache@v5
38+
id: avd-cache
39+
with:
40+
path: |
41+
~/.android/avd/*
42+
~/.android/adb*
43+
key: avd-35
44+
- name: Run Android Screenshot Test
45+
uses: reactivecircus/android-emulator-runner@v2
46+
with:
47+
api-level: 35
48+
avd-name: test_avd
49+
target: google_apis
50+
arch: x86_64
51+
force-avd-creation: true
52+
ram-size: 4096M
53+
heap-size: 2048M
54+
profile: pixel_tablet
55+
emulator-options: -no-window -gpu mesa -noaudio -no-boot-anim -camera-back none -no-snapshot -no-snapshot-save -no-snapshot-load
56+
disable-animations: false
57+
script: >
58+
curl -L https://maven.google.com/androidx/test/services/test-services/1.6.0/test-services-1.6.0.apk --output test-services-1.6.0.apk;
59+
adb install -r -g test-services-1.6.0.apk;
60+
adb uninstall org.jmonkeyengine.screenshottests.android || true;
61+
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-android:connectedDebugAndroidTest;
62+
exit_code=$?;
63+
mkdir -p logcat;
64+
adb logcat -d > logcat/logcat_full.txt || true;
65+
adb logcat -d | grep org.jmonkeyengine.screenshottests.android > logcat/logcat.txt || true;
66+
mkdir -p report;
67+
adb pull /storage/emulated/0/googletest/test_outputfiles/report report/protoReport || true;
68+
adb pull /storage/emulated/0/googletest/test_outputfiles/changed-images report/changed-images || true;
69+
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-proto-report:upgradeProtoReport --args="$(pwd)/report/protoReport $(pwd)/report/extentReport" || true;
70+
echo "GRADLE_EXIT_CODE=$exit_code" >> $GITHUB_ENV;
71+
exit $exit_code
72+
- name: Upload logcat
73+
uses: actions/upload-artifact@v4
74+
if: always()
75+
with:
76+
name: android-logcat
77+
path: logcat
78+
- name: Upload Screenshot
79+
uses: actions/upload-artifact@v4
80+
if: always()
81+
with:
82+
name: android-screenshot-report
83+
path: report
84+
if-no-files-found: error

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ jobs:
162162
uses: gradle/actions/wrapper-validation@v6.1.0
163163
- name: Test with Gradle Wrapper
164164
run: |
165-
./gradlew :jme3-screenshot-test:screenshotTest
165+
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-desktop:screenshotTest
166166
- name: Upload Test Reports
167167
uses: actions/upload-artifact@v7.0.1
168168
if: always()

.github/workflows/screenshot-test-comment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,6 @@ jobs:
133133
134134
See https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-screenshot-tests/README.md for more information
135135
136-
Contact @richardTingle (aka richtea) for guidance if required
136+
Contact %40richardTingle (aka richtea) for guidance if required
137137
edit-mode: replace
138138
comment-id: ${{ steps.existingCommentId.outputs.comment-id }}

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,8 @@ javadoc_deploy.pub
4747
!.vscode/JME_style.xml
4848
!.vscode/extensions.json
4949
joysticks-*.txt
50+
/jme3-screenshot-tests/jme3-screenshot-tests-desktop/build/
51+
/jme3-screenshot-tests/jme3-screenshot-tests-android/build/
52+
/jme3-screenshot-tests/jme3-screenshot-tests-shared/build/
53+
54+
/jme3-screenshot-tests/jme3-screenshot-tests-proto-report/build/

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ allprojects {
5151

5252
// This is applied to all sub projects
5353
subprojects {
54-
if(!project.name.equals('jme3-android-examples')) {
55-
apply from: rootProject.file('common.gradle')
56-
} else {
54+
if(project.name.equals('jme3-android-examples') || project.name.equals('jme3-screenshot-tests-android')) {
5755
apply from: rootProject.file('common-android-app.gradle')
56+
} else {
57+
apply from: rootProject.file('common.gradle')
5858
}
5959

6060
def isAndroidApp = project.plugins.hasPlugin('com.android.application')

gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ POM_LICENSE_URL=http://opensource.org/licenses/BSD-3-Clause
3333
POM_LICENSE_DISTRIBUTION=repo
3434
POM_INCEPTION_YEAR=2009
3535

36+
systemProp.org.gradle.unsafe.repositories=true
37+
38+
org.gradle.jvmargs=-Xmx2048m

gradle/libs.versions.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ saferalloc = "0.0.10"
1111
nifty = "1.4.3"
1212
spotbugs = "4.9.8"
1313
jmeAndroidNatives = "3.10.0-xt16kb-alloc"
14+
googleMaterial = "1.4.0"
15+
androidx-fragment-testing = "1.8.9"
1416

1517
[libraries]
1618

@@ -19,9 +21,21 @@ androidx-fragment = "androidx.fragment:fragment:1.8.9"
1921
androidx-lifecycle-common = "androidx.lifecycle:lifecycle-common:2.7.0"
2022
android-build-gradle = "com.android.tools.build:gradle:9.1.0"
2123
android-support-appcompat = "com.android.support:appcompat-v7:28.0.0"
24+
androidx-test-services = { module = "androidx.test.services:test-services", version = "1.6.0" }
25+
androidx-storage = { module = "androidx.test.services:storage" } # used for peristent android test result storage, file version from androidx-fragment-testing-manifest
26+
androidxAppcompat = { module = "androidx.appcompat:appcompat", version = "1.4.0" }
27+
androidxConstraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.1" }
28+
androidx-test-core = "androidx.test:core:1.6.1"
29+
androidx-test-rules = "androidx.test:rules:1.6.1"
30+
androidx-test-ext-junit = "androidx.test.ext:junit:1.2.1"
31+
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.6.1"
32+
androidx-fragment-testing = { module ="androidx.fragment:fragment-testing", version.ref = "androidx-fragment-testing"}
33+
androidx-fragment-testing-manifest = { module = "androidx.fragment:fragment-testing-manifest", version.ref = "androidx-fragment-testing"}
34+
gradle-git = "org.ajoberstar:gradle-git:1.2.0"
2235
androidx-test-runner = "androidx.test:runner:1.7.0"
2336
groovy-test = "org.apache.groovy:groovy-test:4.0.31"
2437
gson = "com.google.code.gson:gson:2.14.0"
38+
googleMaterial = { module = "com.google.android.material:material", version.ref = "googleMaterial" }
2539
j-ogg-vorbis = "com.github.stephengold:j-ogg-vorbis:1.0.6"
2640
jme3-android-natives = { module = "org.jmonkeyengine:jme3-android-native", version.ref = "jmeAndroidNatives" }
2741
jbullet = "com.github.stephengold:jbullet:1.0.3"
@@ -75,8 +89,13 @@ saferalloc-natives-macos-aarch64 = { module = "org.ngengine:saferalloc-natives-m
7589
saferalloc-natives-android = { module = "org.ngengine:saferalloc-natives-android", version.ref = "saferalloc" }
7690
saferalloc-natives-ios = { module = "org.ngengine:saferalloc-natives-ios", version.ref = "saferalloc" }
7791

92+
extent-reports = { module = "com.aventstack:extentreports", version = "5.1.2"}
93+
94+
jackson = {module = "tools.jackson.core:jackson-databind", version ="3.1.3"}
95+
7896
[bundles]
7997
saferalloc = ["saferalloc", "saferalloc-natives-linux-x8664", "saferalloc-natives-linux-aarch64", "saferalloc-natives-windows-x8664", "saferalloc-natives-windows-aarch64", "saferalloc-natives-macos-x8664", "saferalloc-natives-macos-aarch64", "saferalloc-natives-android", "saferalloc-natives-ios"]
8098

8199
[plugins]
82100
jacoco = { id = "jacoco", version.ref = "jacoco" }
101+

jme3-screenshot-tests/build.gradle

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,3 @@ plugins {
55
repositories {
66
mavenCentral()
77
}
8-
9-
dependencies {
10-
implementation project(':jme3-desktop')
11-
implementation project(':jme3-core')
12-
implementation project(':jme3-effects')
13-
implementation project(':jme3-terrain')
14-
implementation project(':jme3-lwjgl3')
15-
implementation project(':jme3-plugins')
16-
implementation project(':jme3-saferallocator')
17-
18-
implementation 'com.aventstack:extentreports:5.1.2'
19-
implementation platform('org.junit:junit-bom:5.9.1')
20-
implementation 'org.junit.jupiter:junit-jupiter'
21-
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
22-
testRuntimeOnly project(':jme3-testdata')
23-
}
24-
25-
testing {
26-
suites {
27-
test {
28-
useJUnitJupiter('5.9.1')
29-
}
30-
}
31-
}
32-
33-
tasks.register("screenshotTest", Test) {
34-
testClassesDirs = sourceSets.test.output.classesDirs
35-
classpath = sourceSets.test.runtimeClasspath
36-
useJUnitPlatform{
37-
filter{
38-
includeTags 'integration'
39-
}
40-
}
41-
}
42-
43-
44-
test {
45-
useJUnitPlatform{
46-
filter{
47-
excludeTags 'integration'
48-
}
49-
}
50-
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
plugins {
2+
id "io.github.0ffz.github-packages" version "1.2.1" // Plugin for anonymous inclusion of artifacts hosted in github package registry
3+
}
4+
5+
apply plugin: 'com.android.application'
6+
7+
android {
8+
namespace "org.jmonkeyengine.screenshottests.android"
9+
compileSdk 36
10+
11+
defaultConfig {
12+
applicationId "org.jmonkeyengine.screenshottests.android"
13+
minSdk 28
14+
targetSdk 36
15+
versionCode 1
16+
versionName "1.0"
17+
18+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19+
}
20+
21+
buildTypes {
22+
release {
23+
minifyEnabled false
24+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25+
}
26+
}
27+
configurations.all {
28+
exclude group:"org.jmonkeyengine",module:"jme3-desktop"
29+
}
30+
31+
packagingOptions {
32+
jniLibs {
33+
useLegacyPackaging = true
34+
}
35+
resources {
36+
merges += "META-INF/LICENSE.md"
37+
merges += "META-INF/LICENSE-notice.md"
38+
}
39+
}
40+
}
41+
42+
dependencies {
43+
implementation libs.androidxAppcompat
44+
implementation libs.googleMaterial
45+
implementation libs.androidxConstraintlayout
46+
47+
implementation project(":jme3-android")
48+
implementation libs.jme3.android.natives
49+
50+
implementation libs.androidx.test.core
51+
implementation libs.androidx.test.ext.junit
52+
implementation libs.androidx.test.rules
53+
implementation libs.androidx.test.espresso.core
54+
implementation libs.androidx.fragment.testing
55+
implementation libs.jackson
56+
debugImplementation libs.androidx.fragment.testing.manifest
57+
androidTestImplementation libs.androidx.fragment.testing.manifest
58+
debugImplementation libs.androidx.storage
59+
60+
implementation project(':jme3-screenshot-tests:jme3-screenshot-tests-shared')
61+
implementation project(':jme3-screenshot-tests:jme3-screenshot-tests-proto-report')
62+
63+
implementation project(':jme3-testdata')
64+
65+
// Allows the test to communicate with the orchestrator storage
66+
androidTestImplementation libs.androidx.test.services
67+
debugImplementation libs.androidx.test.services
68+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile

0 commit comments

Comments
 (0)