Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
b766025
Make the screenshot tests run in an off frame buffer and correct gamm…
richardTingle May 2, 2026
97dc3c2
Make the definition of "the same" a bit more flexible to avoid instab…
richardTingle May 2, 2026
4b84b7b
Restore gamma correction
richardTingle May 2, 2026
602d25f
Set the colourspace for the off renderTexture
richardTingle May 4, 2026
2a428bc
Set the Srgb for the off renderTexture
richardTingle May 4, 2026
59164b3
Rebake minor visual changes for off frame buffer
richardTingle May 4, 2026
ec05b0d
Rearrange for submodule screenshot structure
richardTingle May 8, 2026
625c35b
Add in dependencies for android
richardTingle May 8, 2026
e215ab4
Bring it closer to the android initialiser project
richardTingle May 8, 2026
93d159e
Temporarily use non local android jme
richardTingle May 8, 2026
77f8178
Simple screenshot test
richardTingle May 8, 2026
036ab76
Wait for emulator
richardTingle May 8, 2026
e0cad2a
Dont save a snapshot, use mesa
richardTingle May 8, 2026
9787b0b
Make the emulator logs less likely to hang
richardTingle May 8, 2026
dbf0b9c
Bit closer to the android-emulator-runner docs
richardTingle May 8, 2026
9f36591
Add logging in test
richardTingle May 8, 2026
0780c16
Try a more modern pixel copy
richardTingle May 8, 2026
b5ef700
Capture logcat
richardTingle May 8, 2026
e897546
Only get my applications logcat
richardTingle May 8, 2026
a938fea
Pull logs inside app step
richardTingle May 8, 2026
808be1c
Prevent snapshots (which are erroring)
richardTingle May 8, 2026
3b02dfc
Actually grab the logcat
richardTingle May 8, 2026
f6c13e4
Use the actual location of the file
richardTingle May 8, 2026
6b65fbb
Save file to public directory
richardTingle May 8, 2026
96173d6
The whole logcat isn't too long
richardTingle May 8, 2026
a0ca84e
Pull image from quoted location
richardTingle May 8, 2026
cf235a3
Whole log cat actually a bit much to put in github logs
richardTingle May 8, 2026
d5cdeaa
Use latch to wait explicitly for write to complete
richardTingle May 8, 2026
c35e44c
Clean up the test code
richardTingle May 8, 2026
a475397
Go back to scoped storage as permissions do not allow downloads folder
richardTingle May 8, 2026
b9d850c
Pull file from within test
richardTingle May 8, 2026
b0ed44d
Use explicit file location
richardTingle May 8, 2026
70f7c08
Revert "Use explicit file location"
richardTingle May 9, 2026
14368e6
Revert "Pull file from within test"
richardTingle May 9, 2026
76d288c
Avoid auto unistall (which means I can't get the file)
richardTingle May 9, 2026
5edfa73
Try to get JME to render into the test
richardTingle May 9, 2026
44f5e07
Fresh emulator every time
richardTingle May 9, 2026
7ed17c5
Take the screenshot from the glSurfaceView
richardTingle May 9, 2026
f0eff53
Move the screenshot framework to a shared environment
richardTingle May 9, 2026
36f5a99
Extract out one of the tests ready for reuse
richardTingle May 9, 2026
456e572
Merge remote-tracking branch 'official/master' into android-screensho…
richardTingle May 15, 2026
1e85933
Start introducing shared android screenshot functionality
richardTingle May 15, 2026
a2ff9bf
Allow for test scenarios to be booted to both android and desktop
richardTingle May 15, 2026
05096e8
Start splitting out android specific elements
richardTingle May 17, 2026
c23638a
Introduce androidx-storage to save the report persistently
richardTingle May 19, 2026
566b074
Change from BufferedImage to JME Image for android compatibility
richardTingle May 22, 2026
add9b04
Work towards allowing android to write a proto report
richardTingle May 24, 2026
925ecf4
Hook in workflow for android screenshots
richardTingle May 24, 2026
3ad9d8d
Hook in workflow for android screenshots
richardTingle May 24, 2026
f001e54
Clean up ExtentReportExtensionJunit4
richardTingle May 24, 2026
09dbf79
Avoid reuse of AssetManager (as we are registering random folders)
richardTingle May 24, 2026
7017297
Give gradle more heap for build (specifically for the android build)
richardTingle May 24, 2026
5331aa3
Remove redundant request to write to external storage
richardTingle May 24, 2026
38df11e
Run the adb pulls even if the gradle step fails
richardTingle May 24, 2026
4eff799
Add the upgrade step for the report
richardTingle May 24, 2026
3ac08d8
Use more modern android for jackson support
richardTingle May 24, 2026
3abe9ba
Use x86_64 android
richardTingle May 24, 2026
5d209f4
Use x86_64 android
richardTingle May 24, 2026
33ac90f
Even more modern android
richardTingle May 24, 2026
a9cca06
Try 35 as docs only go up to 35
richardTingle May 24, 2026
b7e1de8
Remove the matrix as we only run one
richardTingle May 24, 2026
aa2ac55
Install test services before running test
richardTingle May 24, 2026
4c4a80e
Debug error codes
richardTingle May 24, 2026
b1d2ef3
Create report directory before pulling to it
richardTingle May 24, 2026
8d7a7f6
Format the android screenshot tests readme
richardTingle May 24, 2026
1c4992f
Error if upgrade of report fails
richardTingle May 24, 2026
bd58967
Correct upgrade code to access the files with absolute paths
richardTingle May 24, 2026
05bf72f
Try to trap the error code better
richardTingle May 24, 2026
69f52e3
One giant line of doom
richardTingle May 24, 2026
b73e668
One giant line of doom 2
richardTingle May 24, 2026
665c36d
Just say -1 for a fail
richardTingle May 24, 2026
98aba20
Ensure report has a title
richardTingle May 24, 2026
7130677
Reinstate deserialisation constructor
richardTingle May 24, 2026
b53ed0c
Migrate all tests to be android & desktop tests
richardTingle May 24, 2026
b8a2cca
Ensure that we get a single test report
richardTingle May 24, 2026
73f8577
Run the whole thing in a single shell
richardTingle May 24, 2026
64ec98e
Include logcat
richardTingle May 24, 2026
a6542c8
Increase ram for emulator
richardTingle May 24, 2026
9f586f3
Allow app to have large heap
richardTingle May 24, 2026
08970e0
Even larger heap
richardTingle May 24, 2026
059f579
Remove some of the more memory intensive tests
richardTingle May 24, 2026
c5fae11
Remove some more of the more memory intensive tests
richardTingle May 24, 2026
7b0c650
Correct the calculateImageFilePrefix so it is flexible to thread dept…
richardTingle May 24, 2026
b8dc5bc
Remove more memory intensive tests
richardTingle May 24, 2026
0c0e209
Try for a wider device
richardTingle May 24, 2026
84a1254
Try to find available profiles
richardTingle May 24, 2026
6b3e00e
Try to find available profiles
richardTingle May 24, 2026
abd96e9
Initialise the reference images
richardTingle May 24, 2026
802669c
Load references images from resources (to make android happy)
richardTingle May 25, 2026
342cd25
Correct colours are ints, not bytes (as unsigned)
richardTingle May 25, 2026
89289eb
Use consistent pixel comparison
richardTingle May 25, 2026
da37de2
Log pixel errors
richardTingle May 25, 2026
ed163cd
Fix inverted "very similar" test
richardTingle May 25, 2026
d3f4b14
Set android tests to only run on push
richardTingle May 25, 2026
ba125f9
Restore android harness as it was
richardTingle May 25, 2026
2fc6913
Self review
richardTingle May 25, 2026
135a007
Single subshell to avoid EOF issues
richardTingle May 25, 2026
64fca29
Avoid richard actually being contacted by the message
richardTingle May 25, 2026
4147b76
Merge remote-tracking branch 'official/master' into android-screensho…
richardTingle May 25, 2026
758a225
Wrap whole shell in a >
richardTingle May 25, 2026
f1a9d83
Natives moved out of project
richardTingle May 25, 2026
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
80 changes: 80 additions & 0 deletions .github/workflows/android-screenshot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Android Screenshot Test

on:
push:
branches:
- master
- v3.7
- v3.6
- v3.5
- v3.4
- v3.3
- ios-2024_2
pull_request:

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: checkout
uses: actions/checkout@v6

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Gradle cache
uses: gradle/actions/setup-gradle@v5

- name: AVD cache
uses: actions/cache@v5
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-35
- name: Run Android Screenshot Test
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
avd-name: test_avd
target: google_apis
arch: x86_64
force-avd-creation: true
ram-size: 4096M
heap-size: 2048M
profile: pixel_tablet
emulator-options: -no-window -gpu mesa -noaudio -no-boot-anim -camera-back none -no-snapshot -no-snapshot-save -no-snapshot-load
disable-animations: false
script: >
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;
adb install -r -g test-services-1.6.0.apk;
adb uninstall org.jmonkeyengine.screenshottests.android || true;
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-android:connectedDebugAndroidTest;
exit_code=$?;
mkdir -p logcat;
adb logcat -d > logcat/logcat_full.txt || true;
adb logcat -d | grep org.jmonkeyengine.screenshottests.android > logcat/logcat.txt || true;
mkdir -p report;
adb pull /storage/emulated/0/googletest/test_outputfiles/report report/protoReport || true;
adb pull /storage/emulated/0/googletest/test_outputfiles/changed-images report/changed-images || true;
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-proto-report:upgradeProtoReport --args="$(pwd)/report/protoReport $(pwd)/report/extentReport" || true;
echo "GRADLE_EXIT_CODE=$exit_code" >> $GITHUB_ENV;
exit $exit_code
- name: Upload logcat
uses: actions/upload-artifact@v4
if: always()
with:
name: android-logcat
path: logcat
- name: Upload Screenshot
uses: actions/upload-artifact@v4
if: always()
with:
name: android-screenshot-report
path: report
if-no-files-found: error
2 changes: 1 addition & 1 deletion .github/workflows/screenshot-test-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@ jobs:

See https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-screenshot-tests/README.md for more information

Contact @richardTingle (aka richtea) for guidance if required
Contact %40richardTingle (aka richtea) for guidance if required
edit-mode: replace
comment-id: ${{ steps.existingCommentId.outputs.comment-id }}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ javadoc_deploy.pub
!.vscode/JME_style.xml
!.vscode/extensions.json
joysticks-*.txt
/jme3-screenshot-tests/jme3-screenshot-tests-desktop/build/
/jme3-screenshot-tests/jme3-screenshot-tests-android/build/
/jme3-screenshot-tests/jme3-screenshot-tests-shared/build/

/jme3-screenshot-tests/jme3-screenshot-tests-proto-report/build/
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ allprojects {

// This is applied to all sub projects
subprojects {
if(!project.name.equals('jme3-android-examples')) {
apply from: rootProject.file('common.gradle')
} else {
if(project.name.equals('jme3-android-examples') || project.name.equals('jme3-screenshot-tests-android')) {
apply from: rootProject.file('common-android-app.gradle')
} else {
apply from: rootProject.file('common.gradle')
}

def isAndroidApp = project.plugins.hasPlugin('com.android.application')
Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ POM_LICENSE_URL=http://opensource.org/licenses/BSD-3-Clause
POM_LICENSE_DISTRIBUTION=repo
POM_INCEPTION_YEAR=2009

systemProp.org.gradle.unsafe.repositories=true

org.gradle.jvmargs=-Xmx2048m
19 changes: 19 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ saferalloc = "0.0.8"
nifty = "1.4.3"
spotbugs = "4.9.8"
jmeAndroidNatives = "3.10.0-xt16kb"
googleMaterial = "1.4.0"
androidx-fragment-testing = "1.8.9"

[libraries]

Expand All @@ -19,9 +21,21 @@ androidx-fragment = "androidx.fragment:fragment:1.8.9"
androidx-lifecycle-common = "androidx.lifecycle:lifecycle-common:2.7.0"
android-build-gradle = "com.android.tools.build:gradle:9.1.0"
android-support-appcompat = "com.android.support:appcompat-v7:28.0.0"
androidx-test-services = { module = "androidx.test.services:test-services", version = "1.6.0" }
androidx-storage = { module = "androidx.test.services:storage" } # used for peristent android test result storage, file version from androidx-fragment-testing-manifest
androidxAppcompat = { module = "androidx.appcompat:appcompat", version = "1.4.0" }
androidxConstraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.1" }
androidx-test-core = "androidx.test:core:1.6.1"
androidx-test-rules = "androidx.test:rules:1.6.1"
androidx-test-ext-junit = "androidx.test.ext:junit:1.2.1"
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.6.1"
androidx-fragment-testing = { module ="androidx.fragment:fragment-testing", version.ref = "androidx-fragment-testing"}
androidx-fragment-testing-manifest = { module = "androidx.fragment:fragment-testing-manifest", version.ref = "androidx-fragment-testing"}
gradle-git = "org.ajoberstar:gradle-git:1.2.0"
androidx-test-runner = "androidx.test:runner:1.7.0"
groovy-test = "org.apache.groovy:groovy-test:4.0.31"
gson = "com.google.code.gson:gson:2.14.0"
googleMaterial = { module = "com.google.android.material:material", version.ref = "googleMaterial" }
j-ogg-vorbis = "com.github.stephengold:j-ogg-vorbis:1.0.6"
jme3-android-natives = { module = "org.jmonkeyengine:jme3-android-native", version.ref = "jmeAndroidNatives" }
jbullet = "com.github.stephengold:jbullet:1.0.3"
Expand Down Expand Up @@ -74,8 +88,13 @@ saferalloc-natives-macos-x8664 = { module = "org.ngengine:saferalloc-natives-mac
saferalloc-natives-macos-aarch64 = { module = "org.ngengine:saferalloc-natives-macos-aarch64", version.ref = "saferalloc" }
saferalloc-natives-android = { module = "org.ngengine:saferalloc-natives-android", version.ref = "saferalloc" }

extent-reports = { module = "com.aventstack:extentreports", version = "5.1.2"}

jackson = {module = "tools.jackson.core:jackson-databind", version ="3.1.3"}
Comment thread
richardTingle marked this conversation as resolved.

[bundles]
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"]

[plugins]
jacoco = { id = "jacoco", version.ref = "jacoco" }

42 changes: 0 additions & 42 deletions jme3-screenshot-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,3 @@ plugins {
repositories {
mavenCentral()
}

dependencies {
implementation project(':jme3-desktop')
implementation project(':jme3-core')
implementation project(':jme3-effects')
implementation project(':jme3-terrain')
implementation project(':jme3-lwjgl3')
implementation project(':jme3-plugins')

implementation 'com.aventstack:extentreports:5.1.2'
implementation platform('org.junit:junit-bom:5.9.1')
implementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testRuntimeOnly project(':jme3-testdata')
}

testing {
suites {
test {
useJUnitJupiter('5.9.1')
}
}
}

tasks.register("screenshotTest", Test) {
testClassesDirs = sourceSets.test.output.classesDirs
classpath = sourceSets.test.runtimeClasspath
useJUnitPlatform{
filter{
includeTags 'integration'
}
}
}


test {
useJUnitPlatform{
filter{
excludeTags 'integration'
}
}
}
68 changes: 68 additions & 0 deletions jme3-screenshot-tests/jme3-screenshot-tests-android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
plugins {
id "io.github.0ffz.github-packages" version "1.2.1" // Plugin for anonymous inclusion of artifacts hosted in github package registry
}

apply plugin: 'com.android.application'

android {
namespace "org.jmonkeyengine.screenshottests.android"
compileSdk 36

defaultConfig {
applicationId "org.jmonkeyengine.screenshottests.android"
minSdk 28
targetSdk 36
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
configurations.all {
exclude group:"org.jmonkeyengine",module:"jme3-desktop"
}

packagingOptions {
jniLibs {
useLegacyPackaging = true
}
resources {
merges += "META-INF/LICENSE.md"
merges += "META-INF/LICENSE-notice.md"
}
}
}

dependencies {
implementation libs.androidxAppcompat
implementation libs.googleMaterial
implementation libs.androidxConstraintlayout

implementation project(":jme3-android")
implementation libs.jme3.android.natives

implementation libs.androidx.test.core
implementation libs.androidx.test.ext.junit
implementation libs.androidx.test.rules
implementation libs.androidx.test.espresso.core
implementation libs.androidx.fragment.testing
implementation libs.jackson
debugImplementation libs.androidx.fragment.testing.manifest
androidTestImplementation libs.androidx.fragment.testing.manifest
debugImplementation libs.androidx.storage

implementation project(':jme3-screenshot-tests:jme3-screenshot-tests-shared')
implementation project(':jme3-screenshot-tests:jme3-screenshot-tests-proto-report')

implementation project(':jme3-testdata')

// Allows the test to communicate with the orchestrator storage
androidTestImplementation libs.androidx.test.services
debugImplementation libs.androidx.test.services
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
45 changes: 45 additions & 0 deletions jme3-screenshot-tests/jme3-screenshot-tests-android/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# JMonkeyEngine Android Screenshot Tests

This project contains screenshot tests specifically for Android.

## Prerequisites

To run these tests and collect the results, you need to install the Android Test Services APK on your device/emulator. This service allows the tests to write files (like screenshots and reports) to a persistent location that can be accessed via ADB.

1. Download the Test Services APK: [test-services-1.6.0.apk](https://maven.google.com/androidx/test/services/test-services/1.6.0/test-services-1.6.0.apk)
2. Install it with necessary permissions:
```bash
adb install -r -g test-services-1.6.0.apk
```

## Collecting Test Results

The tests are configured to use `androidx.test.services.storage.TestStorage` to save output files. After running the tests, you can pull the entire report folder (which includes the captured images and the proto-report JSON) using the following command:

```bash
adb pull /storage/emulated/0/googletest/test_outputfiles/report/
```

Individual files can also be pulled if needed:
```bash
adb pull /storage/emulated/0/googletest/test_outputfiles/report/screenshotProtoReport.json
```

## Generating Extent Reports

The raw report is saved in a "proto-report" format (`screenshotProtoReport.json`). To convert this into a human-readable Extent Report (HTML), use the `upgradeProtoReport` Gradle task located in the `jme3-screenshot-tests-proto-report` module.

### Usage

Run the task and provide the input directory (where the pulled report is) and the desired output directory:

```bash
./gradlew :jme3-screenshot-tests:jme3-screenshot-tests-proto-report:upgradeProtoReport --args="path/to/pulled/report path/to/output/extent-report"
```

## How it Works

1. **Capture**: When tests run on Android, `ExtentReportExtensionJunit4` captures test status, logs, and screenshots.
2. **Storage**: Screenshots are saved as PNG files and test metadata is collected into a `ProtoReport` object.
3. **Persistence**: At the end of each test, the report metadata is serialized to `screenshotProtoReport.json` and saved to the device's persistent storage via `TestStorage`.
4. **Post-Processing**: Once pulled from the device, the `UpgradeProtoReportToExtentReport` tool processes the JSON and images to create a standalone HTML report with embedded screenshots.
Loading
Loading