Skip to content

Commit f77263d

Browse files
committed
Switched to androidx testing
1 parent 4151c2a commit f77263d

File tree

1 file changed

+115
-71
lines changed

1 file changed

+115
-71
lines changed

scripts/build-android-app.sh

Lines changed: 115 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ xmlstarlet sel -N "$NS" -t -c "/mvn:project/mvn:build/mvn:plugins" -n "$ROOT_POM
201201
[ -f "$APP_DIR/build.sh" ] && chmod +x "$APP_DIR/build.sh"
202202

203203
SETTINGS_FILE="$APP_DIR/common/codenameone_settings.properties"
204+
echo "codename1.arg.android.useAndroidX=true" >> "$SETTINGS_FILE"
204205
[ -f "$SETTINGS_FILE" ] || { ba_log "codenameone_settings.properties not found at $SETTINGS_FILE" >&2; exit 1; }
205206

206207
# --- Read settings ---
@@ -266,112 +267,155 @@ if [ -z "$GRADLE_PROJECT_DIR" ]; then
266267
fi
267268

268269
ba_log "Configuring instrumentation test sources in $GRADLE_PROJECT_DIR"
270+
271+
# Make sure the generated project opts into AndroidX/Jetifier
272+
GRADLE_PROPS="$GRADLE_PROJECT_DIR/gradle.properties"
273+
mkdir -p "$(dirname "$GRADLE_PROPS")"
274+
grep -q '^android.useAndroidX=' "$GRADLE_PROPS" 2>/dev/null || echo 'android.useAndroidX=true' >> "$GRADLE_PROPS"
275+
grep -q '^android.enableJetifier=' "$GRADLE_PROPS" 2>/dev/null || echo 'android.enableJetifier=true' >> "$GRADLE_PROPS"
276+
269277
APP_BUILD_GRADLE="$GRADLE_PROJECT_DIR/app/build.gradle"
270-
if [ -f "$APP_BUILD_GRADLE" ]; then
271-
python3 - "$APP_BUILD_GRADLE" <<'PYTHON'
272-
import pathlib
273-
import re
274-
import sys
278+
ROOT_BUILD_GRADLE="$GRADLE_PROJECT_DIR/build.gradle"
279+
280+
ensure_repos_block() {
281+
local file="$1"
282+
if [ -f "$file" ]; then
283+
if ! grep -q 'google()' "$file"; then
284+
# add google() to the first repositories { } block, or create one at bottom
285+
if grep -q 'repositories[[:space:]]*{' "$file"; then
286+
sed -E -i '0,/repositories[[:space:]]*\{/s//repositories {\n google()\n mavenCentral()/' "$file"
287+
else
288+
printf '\nrepositories {\n google()\n mavenCentral()\n}\n' >> "$file"
289+
fi
290+
fi
291+
if ! grep -q 'mavenCentral()' "$file"; then
292+
sed -E -i '0,/repositories[[:space:]]*\{/s//repositories {\n google()\n mavenCentral()/' "$file"
293+
fi
294+
fi
295+
}
275296

276-
path = pathlib.Path(sys.argv[1])
277-
text = path.read_text()
297+
# Ensure repos in both root and app build.gradle
298+
ensure_repos_block "$ROOT_BUILD_GRADLE"
299+
ensure_repos_block "$APP_BUILD_GRADLE"
300+
301+
if [ -f "$APP_BUILD_GRADLE" ]; then
302+
python3 - "$APP_BUILD_GRADLE" <<'PY'
303+
import re, sys, pathlib
304+
p = pathlib.Path(sys.argv[1])
305+
t = p.read_text()
306+
orig = t
278307
modified = False
279308
280-
if "android.test.InstrumentationTestRunner" not in text:
281-
def add_runner(match):
282-
prefix = match.group(0)
283-
return prefix + "\n testInstrumentationRunner \"android.test.InstrumentationTestRunner\""
309+
# Runner -> AndroidX
310+
if "androidx.test.runner.AndroidJUnitRunner" not in t:
311+
t2, n = re.subn(r'testInstrumentationRunner\s*".*?"',
312+
'testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"', t)
313+
if n == 0:
314+
t2, n = re.subn(r'(defaultConfig\s*\{)',
315+
r'\1\n testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"', t, count=1)
316+
t = t2
317+
modified = True
284318
285-
new_text, count = re.subn(r"(defaultConfig\s*\{)", add_runner, text, count=1, flags=re.MULTILINE)
286-
if count:
287-
text = new_text
288-
modified = True
289-
else:
290-
raise SystemExit("defaultConfig block not found while adding instrumentation runner")
291-
292-
libraries = [
293-
"useLibrary 'android.test.base'",
294-
"useLibrary 'android.test.mock'",
295-
"useLibrary 'android.test.runner'",
296-
]
297-
298-
missing_libraries = [lib for lib in libraries if lib not in text]
299-
if missing_libraries:
300-
match = re.search(r"^(\s*android\s*\{)", text, flags=re.MULTILINE)
301-
if not match:
302-
raise SystemExit("android block not found while adding instrumentation libraries")
303-
line = match.group(1)
304-
indent = re.match(r"^(\s*)", line).group(1)
305-
insertion = "".join(f"\n{indent} {lib}" for lib in missing_libraries)
306-
text = text[: match.end()] + insertion + text[match.end():]
319+
# Remove legacy useLibrary lines
320+
t2, n = re.subn(r'^\s*useLibrary\s+\'android\.test\.(base|mock|runner)\'\s*\n?', '', t, flags=re.M)
321+
if n:
322+
t = t2
307323
modified = True
308324
309-
if modified:
310-
if not text.endswith("\n"):
311-
text += "\n"
312-
path.write_text(text)
313-
PYTHON
314-
ba_log "Ensured instrumentation runner and libraries are declared"
325+
# Decide config name: if file uses modern 'implementation/api', use androidTestImplementation; else androidTestCompile
326+
uses_modern = re.search(r'(?m)^\s*(implementation|api|testImplementation|androidTestImplementation)\b', t) is not None
327+
conf = "androidTestImplementation" if uses_modern else "androidTestCompile"
328+
329+
# Ensure dependencies block exists
330+
if not re.search(r'(?ms)^\s*dependencies\s*\{.*?\}', t):
331+
t += "\n\ndependencies {\n}\n"
332+
333+
# Inject deps if missing
334+
def add_dep(body, depcoord):
335+
if depcoord in body:
336+
return body
337+
return re.sub(r'(?ms)(^\s*dependencies\s*\{)', r'\1\n ' + conf + f' "{depcoord}"', body, count=1)
338+
339+
for dep in [
340+
"androidx.test:runner:1.5.2",
341+
"androidx.test:core:1.5.0",
342+
"androidx.test.services:storage:1.4.2",
343+
]:
344+
t2 = add_dep(t, dep)
345+
if t2 != t:
346+
t = t2
347+
modified = True
348+
349+
if modified and t != orig:
350+
if not t.endswith("\n"): t += "\n"
351+
p.write_text(t)
352+
print(f"Patched build.gradle (deps via {conf})")
353+
else:
354+
print("No build.gradle changes needed")
355+
PY
356+
ba_log "Ensured AndroidX test runner/deps and repositories are declared (legacy-safe)"
315357
else
316358
ba_log "Warning: Gradle build file not found at $APP_BUILD_GRADLE; skipping instrumentation dependency configuration" >&2
317359
fi
318360

319361
TEST_SRC_DIR="$GRADLE_PROJECT_DIR/app/src/androidTest/java/${PACKAGE_PATH}"
320362
mkdir -p "$TEST_SRC_DIR"
321363
TEST_CLASS="$TEST_SRC_DIR/HelloCodenameOneInstrumentedTest.java"
322-
cat >"$TEST_CLASS" <<EOF
323-
package $PACKAGE_NAME;
324-
325-
import android.content.Context;
326-
import android.test.InstrumentationTestCase;
364+
cat >"$TEST_CLASS" <<'EOF'
365+
package @PACKAGE@;
327366
328367
import android.app.Instrumentation;
329368
import android.os.ParcelFileDescriptor;
330-
import android.util.Base64;
331369
370+
import androidx.test.ext.junit.runners.AndroidJUnit4;
371+
import androidx.test.platform.app.InstrumentationRegistry;
372+
import androidx.test.services.storage.TestStorage;
373+
import androidx.test.core.app.ApplicationProvider;
374+
375+
import org.junit.Test;
376+
import org.junit.runner.RunWith;
377+
378+
import java.io.File;
332379
import java.io.FileInputStream;
333-
import java.io.IOException;
380+
import java.io.FileOutputStream;
334381
import java.io.InputStream;
382+
import java.io.ByteArrayOutputStream;
335383
336-
public class HelloCodenameOneInstrumentedTest extends InstrumentationTestCase {
384+
import static org.junit.Assert.assertEquals;
337385
338-
public void testUseAppContext() {
339-
Context appContext = getInstrumentation().getTargetContext();
340-
assertEquals("$PACKAGE_NAME", appContext.getPackageName());
341-
}
386+
@RunWith(AndroidJUnit4.class)
387+
public class HelloCodenameOneInstrumentedTest {
342388
343-
private static final int CHUNK = 200_000;
389+
@Test
390+
public void testUseAppContext_andSaveScreenshot() throws Exception {
391+
// Keep your assertion
392+
String expectedPkg = "@PACKAGE@";
393+
String actualPkg = ApplicationProvider.getApplicationContext().getPackageName();
394+
assertEquals(expectedPkg, actualPkg);
344395
345-
public static void printPngToStdout(Instrumentation inst) {
346-
try {
396+
// Capture a PNG from the emulator
397+
Instrumentation inst = InstrumentationRegistry.getInstrumentation();
347398
ParcelFileDescriptor pfd = inst.getUiAutomation().executeShellCommand("screencap -p");
348-
byte[] png;
349-
try (InputStream in = new FileInputStream(pfd.getFileDescriptor())) {
350-
png = readAll(in);
351-
}
352-
String b64 = Base64.encodeToString(png, Base64.NO_WRAP);
353-
System.out.println("<<CN1_SCREENSHOT_BEGIN>>");
354-
for (int i = 0; i < b64.length(); i += CHUNK) {
355-
int end = Math.min(i + CHUNK, b64.length());
356-
System.out.println(b64.substring(i, end));
399+
byte[] png = readAll(new FileInputStream(pfd.getFileDescriptor()));
400+
401+
// Write to AndroidX TestStorage (runner copies back to host)
402+
File out = new File(TestStorage.getInstance().getOutputDir(), "emulator-screenshot.png");
403+
try (FileOutputStream fos = new FileOutputStream(out)) {
404+
fos.write(png);
357405
}
358-
System.out.println("<<CN1_SCREENSHOT_END>>");
359-
System.out.flush();
360-
} catch (IOException err) {
361-
err.printStackTrace();
362-
throw new RuntimeException(err);
363-
}
406+
System.out.println("WROTE_TO_TEST_STORAGE:" + out.getAbsolutePath());
364407
}
365408
366-
private static byte[] readAll(InputStream in) throws IOException {
409+
private static byte[] readAll(InputStream in) throws Exception {
367410
byte[] buf = new byte[64 * 1024];
368411
int n;
369-
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
412+
ByteArrayOutputStream out = new ByteArrayOutputStream();
370413
while ((n = in.read(buf)) != -1) out.write(buf, 0, n);
371414
return out.toByteArray();
372415
}
373416
}
374417
EOF
418+
sed -i "s|@PACKAGE@|$PACKAGE_NAME|g" "$TEST_CLASS"
375419
ba_log "Created instrumentation test at $TEST_CLASS"
376420

377421
DEFAULT_ANDROID_TEST="$GRADLE_PROJECT_DIR/app/src/androidTest/java/com/example/myapplication2/ExampleInstrumentedTest.java"

0 commit comments

Comments
 (0)