Skip to content

Commit bb21435

Browse files
committed
feat: introduced retry rules for flaky android push tests
1 parent 1d04fc4 commit bb21435

File tree

5 files changed

+62
-6
lines changed

5 files changed

+62
-6
lines changed

.github/workflows/emulate.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ jobs:
3535
api-level: ${{ matrix.android-api-level }}
3636
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
3737
disable-animations: true
38-
script: ./gradlew :android:connectedAndroidTest
38+
# Print emulator logs if tests fail
39+
script: ./gradlew :android:connectedAndroidTest || (adb logcat -d System.out:I && exit 1)
3940

4041
- uses: actions/upload-artifact@v3
4142
if: always()

android/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ android {
77
namespace = "io.ably.lib"
88
defaultConfig {
99
minSdk = 19
10-
compileSdk = 30
10+
compileSdk = 34
1111
buildConfigField("String", "LIBRARY_NAME", "\"android\"")
1212
buildConfigField("String", "VERSION", "\"${property("VERSION_NAME")}\"")
1313
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
@@ -35,7 +35,7 @@ android {
3535
abortOnError = false
3636
}
3737

38-
testOptions.targetSdk = 30
38+
testOptions.targetSdk = 34
3939

4040
sourceSets {
4141
getByName("main") {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.ably.lib.test;
2+
3+
import org.junit.rules.TestRule;
4+
import org.junit.runner.Description;
5+
import org.junit.runners.model.Statement;
6+
7+
8+
public class RetryTestRule implements TestRule {
9+
10+
private final int timesToRunTestCount;
11+
12+
/**
13+
* If `times` is 0, then we should run the test once.
14+
*/
15+
public RetryTestRule(int times) {
16+
this.timesToRunTestCount = times + 1;
17+
}
18+
19+
@Override
20+
public Statement apply(Statement base, Description description) {
21+
return statement(base, description);
22+
}
23+
24+
private Statement statement(Statement base, Description description) {
25+
return new Statement() {
26+
27+
@Override
28+
public void evaluate() throws Throwable {
29+
Throwable latestException = null;
30+
31+
for (int runCount = 0; runCount < timesToRunTestCount; runCount++) {
32+
try {
33+
base.evaluate();
34+
return;
35+
} catch (Throwable t) {
36+
latestException = t;
37+
System.err.printf("%s: test failed on run: `%d`. Will run a maximum of `%d` times.%n", description.getDisplayName(), runCount, timesToRunTestCount);
38+
t.printStackTrace();
39+
}
40+
}
41+
42+
if (latestException != null) {
43+
System.err.printf("%s: giving up after `%d` failures%n", description.getDisplayName(), timesToRunTestCount);
44+
throw latestException;
45+
}
46+
}
47+
};
48+
}
49+
}

android/src/androidTest/java/io/ably/lib/test/android/AndroidPushTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import android.content.IntentFilter;
77
import android.os.Build;
88
import android.preference.PreferenceManager;
9+
import android.support.test.filters.SdkSuppress;
910
import android.support.test.runner.AndroidJUnit4;
1011
import android.util.Log;
1112
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@@ -41,6 +42,7 @@
4142
import io.ably.lib.rest.Auth;
4243
import io.ably.lib.rest.Channel;
4344
import io.ably.lib.rest.DeviceDetails;
45+
import io.ably.lib.test.RetryTestRule;
4446
import io.ably.lib.test.common.Helpers;
4547
import io.ably.lib.test.common.Helpers.AsyncWaiter;
4648
import io.ably.lib.test.common.Helpers.CompletionWaiter;
@@ -60,6 +62,7 @@
6062

6163
import org.junit.AfterClass;
6264
import org.junit.BeforeClass;
65+
import org.junit.Rule;
6366
import org.junit.Test;
6467
import org.junit.runner.RunWith;
6568

@@ -80,12 +83,14 @@
8083
import static org.junit.Assert.assertNull;
8184
import static org.junit.Assert.assertTrue;
8285
import static org.junit.Assert.fail;
83-
import static org.junit.Assume.assumeTrue;
8486

8587
@RunWith(AndroidJUnit4.class)
8688
public class AndroidPushTest {
8789
private static final int TIMEOUT_SECONDS = 30;
8890

91+
@Rule
92+
public RetryTestRule retryRule = new RetryTestRule(2);
93+
8994
private class TestActivation {
9095
private Helpers.RawHttpTracker httpTracker;
9196
private AblyRest rest;
@@ -975,8 +980,8 @@ protected void setUpMachineState(TestCase testCase) throws AblyException {
975980

976981
// RSH3d3
977982
@Test
983+
@SdkSuppress(minSdkVersion = 21)
978984
public void WaitingForNewPushDeviceDetails_on_GotPushDeviceDetails() throws Exception {
979-
assumeTrue("Can only run on API Level 21 or newer because HttpURLConnection does not support PATCH", Build.VERSION.SDK_INT >= 21);
980985
new UpdateRegistrationTest() {
981986
@Override
982987
protected void setUpMachineState(TestCase testCase) throws AblyException {
@@ -1435,6 +1440,7 @@ public void run() throws Exception {
14351440
}
14361441

14371442
@Test
1443+
@SdkSuppress(minSdkVersion = 21)
14381444
public void Realtime_push_interface() throws Exception {
14391445
AblyRealtime realtime = new AblyRealtime(new ClientOptions() {{
14401446
autoConnect = false;

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ concurrentunit = "0.4.2"
1212
slf4j = "1.7.30"
1313
build-config = "5.4.0"
1414
firebase-messaging = "22.0.0"
15-
android-test = "0.5"
15+
android-test = "1.0.2"
1616
dexmaker = "1.4"
1717
android-retrostreams = "1.7.4"
1818
maven-publish = "0.29.0"

0 commit comments

Comments
 (0)