Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
93 changes: 93 additions & 0 deletions .github/workflows/scripts-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,104 @@ name: Test Android build scripts
jobs:
build-android:
runs-on: ubuntu-latest
outputs:
artifact_dir: ${{ steps.build-app.outputs.artifact_dir }}
app_apk: ${{ steps.build-app.outputs.app_apk }}
test_apk: ${{ steps.build-app.outputs.test_apk }}
package_name: ${{ steps.build-app.outputs.package_name }}
steps:
- uses: actions/checkout@v4
- name: Setup workspace
run: ./scripts/setup-workspace.sh -q -DskipTests
- name: Build Android port
run: ./scripts/build-android-port.sh -q -DskipTests
- name: Build Hello Codename One Android app
id: build-app
run: ./scripts/build-android-app.sh -q -DskipTests
- name: Upload Android APK artifacts
uses: actions/upload-artifact@v4
with:
name: hello-codenameone-apks
path: ${{ steps.build-app.outputs.artifact_dir }}
if-no-files-found: error

android-device-tests:
needs: build-android
runs-on: ubuntu-22.04-arm
steps:
- name: Download APK artifacts
uses: actions/download-artifact@v4
with:
name: hello-codenameone-apks
path: artifacts
- name: Launch emulator and capture screenshots
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 33
arch: arm64-v8a
profile: pixel_6
pre-emulator-launch-script: |
set -euxo pipefail
if command -v sdkmanager >/dev/null 2>&1; then
yes | sdkmanager --install "platform-tools" >/dev/null
else
echo "sdkmanager executable is required for installing platform-tools" >&2
exit 1
fi
if [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}/platform-tools" ]; then
echo "${ANDROID_HOME}/platform-tools" >> "$GITHUB_PATH"
elif [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "${ANDROID_SDK_ROOT}/platform-tools" ]; then
echo "${ANDROID_SDK_ROOT}/platform-tools" >> "$GITHUB_PATH"
fi
script: |
set -euxo pipefail
mkdir -p screenshots
adb install -r artifacts/${{ needs.build-android.outputs.app_apk }}
adb install -r artifacts/${{ needs.build-android.outputs.test_apk }}
adb logcat -c
AAPT_BIN=""
if command -v aapt >/dev/null 2>&1; then
AAPT_BIN="$(command -v aapt)"
elif [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}/build-tools" ]; then
AAPT_BIN="$(find "${ANDROID_HOME}/build-tools" -maxdepth 2 -name aapt -type f | sort | tail -n1 || true)"
elif [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "${ANDROID_SDK_ROOT}/build-tools" ]; then
AAPT_BIN="$(find "${ANDROID_SDK_ROOT}/build-tools" -maxdepth 2 -name aapt -type f | sort | tail -n1 || true)"
fi

TEST_PACKAGE=""
INSTRUMENTATION_NAME=""
if [ -n "$AAPT_BIN" ] && [ -x "$AAPT_BIN" ]; then
BADGING_OUTPUT="$($AAPT_BIN dump badging artifacts/${{ needs.build-android.outputs.test_apk }} || true)"
if [ -n "$BADGING_OUTPUT" ]; then
TEST_PACKAGE="$(printf '%s\n' "$BADGING_OUTPUT" | awk -F"'" '/^package: /{print $2; exit}')"
INSTRUMENTATION_NAME="$(printf '%s\n' "$BADGING_OUTPUT" | awk -F"'" '/^instrumentation: /{print $2; exit}')"
fi
fi

if [ -n "$INSTRUMENTATION_NAME" ]; then
echo "Running instrumentation tests via $INSTRUMENTATION_NAME"
adb shell am instrument -w "$INSTRUMENTATION_NAME"
else
if [ -z "$TEST_PACKAGE" ]; then
TEST_PACKAGE="${{ needs.build-android.outputs.package_name }}.tests"
fi
echo "Instrumentation runner not found, launching $TEST_PACKAGE via monkey"
adb shell monkey -p "$TEST_PACKAGE" 1
fi

adb shell monkey -p ${{ needs.build-android.outputs.package_name }} 1 || true
sleep 20
if [ -f artifacts/tests.txt ]; then
while IFS= read -r testName; do
[ -n "$testName" ] || continue
adb exec-out screencap -p > "screenshots/${testName}.png"
done < artifacts/tests.txt
else
adb exec-out screencap -p > screenshots/test-suite.png
fi
- name: Upload emulator screenshots
uses: actions/upload-artifact@v4
with:
name: hello-codenameone-test-screenshots
path: screenshots
if-no-files-found: error
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.codename1.samples;

import com.codename1.testing.AbstractTest;
import com.codename1.ui.Component;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Label;

/**
* A simple Codename One unit test that verifies the "Hi World" label is displayed
* when {@link SampleMain} starts.
*/
public class SampleHelloTest extends AbstractTest {
@Override
public boolean runTest() throws Exception {
SampleMain app = new SampleMain();
app.init(null);
app.start();

Form current = Display.getInstance().getCurrent();
assertNotNull(current, "The main form should be visible");

Label found = findLabelWithText(current, "Hi World");
assertNotNull(found, "Expected to find the \"Hi World\" label on the form");
return true;
}

private Label findLabelWithText(Form form, String expected) {
for (int i = 0; i < form.getContentPane().getComponentCount(); i++) {
Component child = form.getContentPane().getComponentAt(i);
if (child instanceof Label) {
Label label = (Label) child;
if (expected.equals(label.getText())) {
return label;
}
}
}
return null;
}

@Override
public boolean shouldExecuteOnEDT() {
return true;
}

@Override
public String toString() {
return "SampleHelloTest";
}
}
80 changes: 79 additions & 1 deletion scripts/build-android-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ ba_log "Detected Codename One version $CN1_VERSION"

WORK_DIR="$TMPDIR/cn1-hello-android"
rm -rf "$WORK_DIR"; mkdir -p "$WORK_DIR"
ARTIFACTS_DIR="$WORK_DIR/artifacts"
mkdir -p "$ARTIFACTS_DIR"
TEST_LIST_FILE="$ARTIFACTS_DIR/tests.txt"
> "$TEST_LIST_FILE"

GROUP_ID="com.codenameone.examples"
ARTIFACT_ID="hello-codenameone"
Expand Down Expand Up @@ -191,6 +195,25 @@ done < <(find "$APP_DIR" -type f -name pom.xml -print0)
# 5) Build with the property set so any lingering refs resolve to the local snapshot
EXTRA_MVN_ARGS+=("-Dcodenameone.version=${CN1_VERSION}")

# --- Record discovered unit tests ---
while IFS= read -r -d '' TEST_FILE; do
REL_PATH="${TEST_FILE#$APP_DIR/}"
REL_PATH="${REL_PATH#*/src/test/java/}"
CLASS_NAME="${REL_PATH%.java}"
CLASS_NAME="${CLASS_NAME//\//.}"
if [ -n "$CLASS_NAME" ]; then
echo "$CLASS_NAME" >> "$TEST_LIST_FILE"
fi
done < <(find "$APP_DIR" -path "*/src/test/java/*.java" -print0)

if [ ! -s "$TEST_LIST_FILE" ]; then
rm -f "$TEST_LIST_FILE"
ba_log "Warning: no unit test sources were discovered"
else
ba_log "Recorded unit test classes:"
sed 's/^/[build-android-app] /' "$TEST_LIST_FILE"
fi

# (Optional) quick non-fatal checks
xmlstarlet sel -N "$NS" -t -v "/mvn:project/mvn:properties/mvn:codenameone.version" -n "$ROOT_POM" || true
xmlstarlet sel -N "$NS" -t -c "/mvn:project/mvn:build/mvn:plugins" -n "$ROOT_POM" | head -n 60 || true
Expand Down Expand Up @@ -282,4 +305,59 @@ export JAVA_HOME="$ORIGINAL_JAVA_HOME"

APK_PATH=$(find "$GRADLE_PROJECT_DIR" -path "*/outputs/apk/debug/*.apk" | head -n 1 || true)
[ -n "$APK_PATH" ] || { ba_log "Gradle build completed but no APK was found" >&2; exit 1; }
ba_log "Successfully built Android APK at $APK_PATH"
FINAL_APP_APK="$ARTIFACTS_DIR/${ARTIFACT_ID}-debug.apk"
cp "$APK_PATH" "$FINAL_APP_APK"
ba_log "Successfully built Android APK at $APK_PATH"
ba_log "Copied Android APK to $FINAL_APP_APK"

ba_log "Building Android unit test APK"
rm -rf "$APP_DIR/android/target"
xvfb-run -a "${MAVEN_CMD[@]}" -q -f "$APP_DIR/pom.xml" package \
-DskipTests \
-Dcodename1.platform=android \
-Dcodename1.buildTarget=android-source \
-Dcodename1.arg.build.unitTest=1 \
-Dopen=false \
"${EXTRA_MVN_ARGS[@]}"

GRADLE_PROJECT_DIR=$(find "$APP_DIR/android/target" -maxdepth 2 -type d -name "*-android-source" | head -n 1 || true)
[ -n "$GRADLE_PROJECT_DIR" ] || { ba_log "Failed to locate generated Android project for unit tests" >&2; exit 1; }

ba_log "Invoking Gradle build for unit test project in $GRADLE_PROJECT_DIR"
chmod +x "$GRADLE_PROJECT_DIR/gradlew"
ORIGINAL_JAVA_HOME="$JAVA_HOME"
export JAVA_HOME="$JAVA17_HOME"
(
cd "$GRADLE_PROJECT_DIR"
if command -v sdkmanager >/dev/null 2>&1; then
yes | sdkmanager --licenses >/dev/null 2>&1 || true
elif [ -x "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]; then
yes | "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null 2>&1 || true
fi
./gradlew --no-daemon assembleDebug
)
export JAVA_HOME="$ORIGINAL_JAVA_HOME"

UNIT_TEST_APK_PATH=$(find "$GRADLE_PROJECT_DIR" -path "*/outputs/apk/debug/*.apk" | head -n 1 || true)
[ -n "$UNIT_TEST_APK_PATH" ] || { ba_log "Gradle unit test build completed but no APK was found" >&2; exit 1; }
FINAL_TEST_APK="$ARTIFACTS_DIR/${ARTIFACT_ID}-tests-debug.apk"
cp "$UNIT_TEST_APK_PATH" "$FINAL_TEST_APK"
ba_log "Successfully built Android unit test APK at $UNIT_TEST_APK_PATH"
ba_log "Copied Android unit test APK to $FINAL_TEST_APK"

TESTS_METADATA=$(find "$APP_DIR" -name tests.dat | head -n 1 || true)
if [ -n "$TESTS_METADATA" ]; then
cp "$TESTS_METADATA" "$ARTIFACTS_DIR/tests.dat"
ba_log "Copied test metadata to $ARTIFACTS_DIR/tests.dat"
else
ba_log "Warning: tests.dat metadata file not found"
fi

if [ -n "${GITHUB_OUTPUT:-}" ]; then
{
echo "artifact_dir=$ARTIFACTS_DIR"
echo "app_apk=$(basename "$FINAL_APP_APK")"
echo "test_apk=$(basename "$FINAL_TEST_APK")"
echo "package_name=$PACKAGE_NAME"
} >> "$GITHUB_OUTPUT"
fi
Loading