Skip to content

Commit 6211c76

Browse files
committed
Ensure emulator runner installs platform tools
1 parent 6df5ea6 commit 6211c76

File tree

3 files changed

+222
-1
lines changed

3 files changed

+222
-1
lines changed

.github/workflows/scripts-android.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,104 @@ name: Test Android build scripts
1515
jobs:
1616
build-android:
1717
runs-on: ubuntu-latest
18+
outputs:
19+
artifact_dir: ${{ steps.build-app.outputs.artifact_dir }}
20+
app_apk: ${{ steps.build-app.outputs.app_apk }}
21+
test_apk: ${{ steps.build-app.outputs.test_apk }}
22+
package_name: ${{ steps.build-app.outputs.package_name }}
1823
steps:
1924
- uses: actions/checkout@v4
2025
- name: Setup workspace
2126
run: ./scripts/setup-workspace.sh -q -DskipTests
2227
- name: Build Android port
2328
run: ./scripts/build-android-port.sh -q -DskipTests
2429
- name: Build Hello Codename One Android app
30+
id: build-app
2531
run: ./scripts/build-android-app.sh -q -DskipTests
32+
- name: Upload Android APK artifacts
33+
uses: actions/upload-artifact@v4
34+
with:
35+
name: hello-codenameone-apks
36+
path: ${{ steps.build-app.outputs.artifact_dir }}
37+
if-no-files-found: error
38+
39+
android-device-tests:
40+
needs: build-android
41+
runs-on: ubuntu-22.04-arm
42+
steps:
43+
- name: Download APK artifacts
44+
uses: actions/download-artifact@v4
45+
with:
46+
name: hello-codenameone-apks
47+
path: artifacts
48+
- name: Launch emulator and capture screenshots
49+
uses: reactivecircus/android-emulator-runner@v2
50+
with:
51+
api-level: 33
52+
arch: arm64-v8a
53+
profile: pixel_6
54+
pre-emulator-launch-script: |
55+
set -euxo pipefail
56+
if command -v sdkmanager >/dev/null 2>&1; then
57+
yes | sdkmanager --install "platform-tools" >/dev/null
58+
else
59+
echo "sdkmanager executable is required for installing platform-tools" >&2
60+
exit 1
61+
fi
62+
if [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}/platform-tools" ]; then
63+
echo "${ANDROID_HOME}/platform-tools" >> "$GITHUB_PATH"
64+
elif [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "${ANDROID_SDK_ROOT}/platform-tools" ]; then
65+
echo "${ANDROID_SDK_ROOT}/platform-tools" >> "$GITHUB_PATH"
66+
fi
67+
script: |
68+
set -euxo pipefail
69+
mkdir -p screenshots
70+
adb install -r artifacts/${{ needs.build-android.outputs.app_apk }}
71+
adb install -r artifacts/${{ needs.build-android.outputs.test_apk }}
72+
adb logcat -c
73+
AAPT_BIN=""
74+
if command -v aapt >/dev/null 2>&1; then
75+
AAPT_BIN="$(command -v aapt)"
76+
elif [ -n "${ANDROID_HOME:-}" ] && [ -d "${ANDROID_HOME}/build-tools" ]; then
77+
AAPT_BIN="$(find "${ANDROID_HOME}/build-tools" -maxdepth 2 -name aapt -type f | sort | tail -n1 || true)"
78+
elif [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -d "${ANDROID_SDK_ROOT}/build-tools" ]; then
79+
AAPT_BIN="$(find "${ANDROID_SDK_ROOT}/build-tools" -maxdepth 2 -name aapt -type f | sort | tail -n1 || true)"
80+
fi
81+
82+
TEST_PACKAGE=""
83+
INSTRUMENTATION_NAME=""
84+
if [ -n "$AAPT_BIN" ] && [ -x "$AAPT_BIN" ]; then
85+
BADGING_OUTPUT="$($AAPT_BIN dump badging artifacts/${{ needs.build-android.outputs.test_apk }} || true)"
86+
if [ -n "$BADGING_OUTPUT" ]; then
87+
TEST_PACKAGE="$(printf '%s\n' "$BADGING_OUTPUT" | awk -F"'" '/^package: /{print $2; exit}')"
88+
INSTRUMENTATION_NAME="$(printf '%s\n' "$BADGING_OUTPUT" | awk -F"'" '/^instrumentation: /{print $2; exit}')"
89+
fi
90+
fi
91+
92+
if [ -n "$INSTRUMENTATION_NAME" ]; then
93+
echo "Running instrumentation tests via $INSTRUMENTATION_NAME"
94+
adb shell am instrument -w "$INSTRUMENTATION_NAME"
95+
else
96+
if [ -z "$TEST_PACKAGE" ]; then
97+
TEST_PACKAGE="${{ needs.build-android.outputs.package_name }}.tests"
98+
fi
99+
echo "Instrumentation runner not found, launching $TEST_PACKAGE via monkey"
100+
adb shell monkey -p "$TEST_PACKAGE" 1
101+
fi
102+
103+
adb shell monkey -p ${{ needs.build-android.outputs.package_name }} 1 || true
104+
sleep 20
105+
if [ -f artifacts/tests.txt ]; then
106+
while IFS= read -r testName; do
107+
[ -n "$testName" ] || continue
108+
adb exec-out screencap -p > "screenshots/${testName}.png"
109+
done < artifacts/tests.txt
110+
else
111+
adb exec-out screencap -p > screenshots/test-suite.png
112+
fi
113+
- name: Upload emulator screenshots
114+
uses: actions/upload-artifact@v4
115+
with:
116+
name: hello-codenameone-test-screenshots
117+
path: screenshots
118+
if-no-files-found: error
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.codename1.samples;
2+
3+
import com.codename1.testing.AbstractTest;
4+
import com.codename1.ui.Component;
5+
import com.codename1.ui.Display;
6+
import com.codename1.ui.Form;
7+
import com.codename1.ui.Label;
8+
9+
/**
10+
* A simple Codename One unit test that verifies the "Hi World" label is displayed
11+
* when {@link SampleMain} starts.
12+
*/
13+
public class SampleHelloTest extends AbstractTest {
14+
@Override
15+
public boolean runTest() throws Exception {
16+
SampleMain app = new SampleMain();
17+
app.init(null);
18+
app.start();
19+
20+
Form current = Display.getInstance().getCurrent();
21+
assertNotNull(current, "The main form should be visible");
22+
23+
Label found = findLabelWithText(current, "Hi World");
24+
assertNotNull(found, "Expected to find the \"Hi World\" label on the form");
25+
return true;
26+
}
27+
28+
private Label findLabelWithText(Form form, String expected) {
29+
for (int i = 0; i < form.getContentPane().getComponentCount(); i++) {
30+
Component child = form.getContentPane().getComponentAt(i);
31+
if (child instanceof Label) {
32+
Label label = (Label) child;
33+
if (expected.equals(label.getText())) {
34+
return label;
35+
}
36+
}
37+
}
38+
return null;
39+
}
40+
41+
@Override
42+
public boolean shouldExecuteOnEDT() {
43+
return true;
44+
}
45+
46+
@Override
47+
public String toString() {
48+
return "SampleHelloTest";
49+
}
50+
}

scripts/build-android-app.sh

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ ba_log "Detected Codename One version $CN1_VERSION"
7979

8080
WORK_DIR="$TMPDIR/cn1-hello-android"
8181
rm -rf "$WORK_DIR"; mkdir -p "$WORK_DIR"
82+
ARTIFACTS_DIR="$WORK_DIR/artifacts"
83+
mkdir -p "$ARTIFACTS_DIR"
84+
TEST_LIST_FILE="$ARTIFACTS_DIR/tests.txt"
85+
> "$TEST_LIST_FILE"
8286

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

198+
# --- Record discovered unit tests ---
199+
while IFS= read -r -d '' TEST_FILE; do
200+
REL_PATH="${TEST_FILE#$APP_DIR/}"
201+
REL_PATH="${REL_PATH#*/src/test/java/}"
202+
CLASS_NAME="${REL_PATH%.java}"
203+
CLASS_NAME="${CLASS_NAME//\//.}"
204+
if [ -n "$CLASS_NAME" ]; then
205+
echo "$CLASS_NAME" >> "$TEST_LIST_FILE"
206+
fi
207+
done < <(find "$APP_DIR" -path "*/src/test/java/*.java" -print0)
208+
209+
if [ ! -s "$TEST_LIST_FILE" ]; then
210+
rm -f "$TEST_LIST_FILE"
211+
ba_log "Warning: no unit test sources were discovered"
212+
else
213+
ba_log "Recorded unit test classes:"
214+
sed 's/^/[build-android-app] /' "$TEST_LIST_FILE"
215+
fi
216+
194217
# (Optional) quick non-fatal checks
195218
xmlstarlet sel -N "$NS" -t -v "/mvn:project/mvn:properties/mvn:codenameone.version" -n "$ROOT_POM" || true
196219
xmlstarlet sel -N "$NS" -t -c "/mvn:project/mvn:build/mvn:plugins" -n "$ROOT_POM" | head -n 60 || true
@@ -282,4 +305,59 @@ export JAVA_HOME="$ORIGINAL_JAVA_HOME"
282305

283306
APK_PATH=$(find "$GRADLE_PROJECT_DIR" -path "*/outputs/apk/debug/*.apk" | head -n 1 || true)
284307
[ -n "$APK_PATH" ] || { ba_log "Gradle build completed but no APK was found" >&2; exit 1; }
285-
ba_log "Successfully built Android APK at $APK_PATH"
308+
FINAL_APP_APK="$ARTIFACTS_DIR/${ARTIFACT_ID}-debug.apk"
309+
cp "$APK_PATH" "$FINAL_APP_APK"
310+
ba_log "Successfully built Android APK at $APK_PATH"
311+
ba_log "Copied Android APK to $FINAL_APP_APK"
312+
313+
ba_log "Building Android unit test APK"
314+
rm -rf "$APP_DIR/android/target"
315+
xvfb-run -a "${MAVEN_CMD[@]}" -q -f "$APP_DIR/pom.xml" package \
316+
-DskipTests \
317+
-Dcodename1.platform=android \
318+
-Dcodename1.buildTarget=android-source \
319+
-Dcodename1.arg.build.unitTest=1 \
320+
-Dopen=false \
321+
"${EXTRA_MVN_ARGS[@]}"
322+
323+
GRADLE_PROJECT_DIR=$(find "$APP_DIR/android/target" -maxdepth 2 -type d -name "*-android-source" | head -n 1 || true)
324+
[ -n "$GRADLE_PROJECT_DIR" ] || { ba_log "Failed to locate generated Android project for unit tests" >&2; exit 1; }
325+
326+
ba_log "Invoking Gradle build for unit test project in $GRADLE_PROJECT_DIR"
327+
chmod +x "$GRADLE_PROJECT_DIR/gradlew"
328+
ORIGINAL_JAVA_HOME="$JAVA_HOME"
329+
export JAVA_HOME="$JAVA17_HOME"
330+
(
331+
cd "$GRADLE_PROJECT_DIR"
332+
if command -v sdkmanager >/dev/null 2>&1; then
333+
yes | sdkmanager --licenses >/dev/null 2>&1 || true
334+
elif [ -x "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]; then
335+
yes | "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null 2>&1 || true
336+
fi
337+
./gradlew --no-daemon assembleDebug
338+
)
339+
export JAVA_HOME="$ORIGINAL_JAVA_HOME"
340+
341+
UNIT_TEST_APK_PATH=$(find "$GRADLE_PROJECT_DIR" -path "*/outputs/apk/debug/*.apk" | head -n 1 || true)
342+
[ -n "$UNIT_TEST_APK_PATH" ] || { ba_log "Gradle unit test build completed but no APK was found" >&2; exit 1; }
343+
FINAL_TEST_APK="$ARTIFACTS_DIR/${ARTIFACT_ID}-tests-debug.apk"
344+
cp "$UNIT_TEST_APK_PATH" "$FINAL_TEST_APK"
345+
ba_log "Successfully built Android unit test APK at $UNIT_TEST_APK_PATH"
346+
ba_log "Copied Android unit test APK to $FINAL_TEST_APK"
347+
348+
TESTS_METADATA=$(find "$APP_DIR" -name tests.dat | head -n 1 || true)
349+
if [ -n "$TESTS_METADATA" ]; then
350+
cp "$TESTS_METADATA" "$ARTIFACTS_DIR/tests.dat"
351+
ba_log "Copied test metadata to $ARTIFACTS_DIR/tests.dat"
352+
else
353+
ba_log "Warning: tests.dat metadata file not found"
354+
fi
355+
356+
if [ -n "${GITHUB_OUTPUT:-}" ]; then
357+
{
358+
echo "artifact_dir=$ARTIFACTS_DIR"
359+
echo "app_apk=$(basename "$FINAL_APP_APK")"
360+
echo "test_apk=$(basename "$FINAL_TEST_APK")"
361+
echo "package_name=$PACKAGE_NAME"
362+
} >> "$GITHUB_OUTPUT"
363+
fi

0 commit comments

Comments
 (0)