Skip to content

Commit

Permalink
feat: introduced retry rules for flaky android push tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ttypic committed Oct 5, 2024
1 parent 1d04fc4 commit c450b20
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/emulate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ jobs:
api-level: ${{ matrix.android-api-level }}
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew :android:connectedAndroidTest
# Print emulator logs if tests fail
script: ./gradlew :android:connectedAndroidTest || (adb logcat -d System.out:I && exit 1)

- uses: actions/upload-artifact@v3
if: always()
Expand Down
4 changes: 2 additions & 2 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ android {
namespace = "io.ably.lib"
defaultConfig {
minSdk = 19
compileSdk = 30
compileSdk = 34
buildConfigField("String", "LIBRARY_NAME", "\"android\"")
buildConfigField("String", "VERSION", "\"${property("VERSION_NAME")}\"")
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -35,7 +35,7 @@ android {
abortOnError = false
}

testOptions.targetSdk = 30
testOptions.targetSdk = 34

sourceSets {
getByName("main") {
Expand Down
49 changes: 49 additions & 0 deletions android/src/androidTest/java/io/ably/lib/test/RetryTestRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package io.ably.lib.test;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;


public class RetryTestRule implements TestRule {

private final int timesToRunTestCount;

/**
* If `times` is 0, then we should run the test once.
*/
public RetryTestRule(int times) {
this.timesToRunTestCount = times + 1;
}

@Override
public Statement apply(Statement base, Description description) {
return statement(base, description);
}

private Statement statement(Statement base, Description description) {
return new Statement() {

@Override
public void evaluate() throws Throwable {
Throwable latestException = null;

for (int runCount = 0; runCount < timesToRunTestCount; runCount++) {
try {
base.evaluate();
return;
} catch (Throwable t) {
latestException = t;
System.err.printf("%s: test failed on run: `%d`. Will run a maximum of `%d` times.%n", description.getDisplayName(), runCount, timesToRunTestCount);
t.printStackTrace();
}
}

if (latestException != null) {
System.err.printf("%s: giving up after `%d` failures%n", description.getDisplayName(), timesToRunTestCount);
throw latestException;
}
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.content.IntentFilter;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.test.filters.SdkSuppress;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
Expand Down Expand Up @@ -41,6 +42,7 @@
import io.ably.lib.rest.Auth;
import io.ably.lib.rest.Channel;
import io.ably.lib.rest.DeviceDetails;
import io.ably.lib.test.RetryTestRule;
import io.ably.lib.test.common.Helpers;
import io.ably.lib.test.common.Helpers.AsyncWaiter;
import io.ably.lib.test.common.Helpers.CompletionWaiter;
Expand All @@ -59,7 +61,9 @@
import java9.util.stream.StreamSupport;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

Expand All @@ -86,6 +90,9 @@
public class AndroidPushTest {
private static final int TIMEOUT_SECONDS = 30;

@Rule
public RetryTestRule retryRule = new RetryTestRule(2);

private class TestActivation {
private Helpers.RawHttpTracker httpTracker;
private AblyRest rest;
Expand Down Expand Up @@ -936,7 +943,7 @@ public void WaitingForDeviceRegistration_on_CalledActivate() {
State state = new WaitingForDeviceRegistration(activation.machine);
State to = state.transition(new CalledActivate());

assertSize(0, activation.machine.pendingEvents);
assertSize(1, activation.machine.pendingEvents);

// RSH3c1a
assertInstanceOf(WaitingForDeviceRegistration.class, to);
Expand Down Expand Up @@ -975,8 +982,8 @@ protected void setUpMachineState(TestCase testCase) throws AblyException {

// RSH3d3
@Test
@SdkSuppress(minSdkVersion = 21)
public void WaitingForNewPushDeviceDetails_on_GotPushDeviceDetails() throws Exception {
assumeTrue("Can only run on API Level 21 or newer because HttpURLConnection does not support PATCH", Build.VERSION.SDK_INT >= 21);
new UpdateRegistrationTest() {
@Override
protected void setUpMachineState(TestCase testCase) throws AblyException {
Expand Down Expand Up @@ -1435,6 +1442,7 @@ public void run() throws Exception {
}

@Test
@SdkSuppress(minSdkVersion = 21)
public void Realtime_push_interface() throws Exception {
AblyRealtime realtime = new AblyRealtime(new ClientOptions() {{
autoConnect = false;
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrentunit = "0.4.2"
slf4j = "1.7.30"
build-config = "5.4.0"
firebase-messaging = "22.0.0"
android-test = "0.5"
android-test = "1.0.2"
dexmaker = "1.4"
android-retrostreams = "1.7.4"
maven-publish = "0.29.0"
Expand Down

0 comments on commit c450b20

Please sign in to comment.