Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d35e6a11 authored by Hieu Dang's avatar Hieu Dang
Browse files

Add retry mechanism for flaky activity tests

Bug: 292004801
Test: atest BluetoothInstrumentationTests
Tag: #refactor
Change-Id: Idae0c05f41d8cd1ed159826b0214f2006ed0428a
parent 47b1e39a
Loading
Loading
Loading
Loading
+57 −7
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
 */
package com.android.bluetooth;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.mockito.ArgumentMatchers.eq;
@@ -31,6 +30,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.service.media.MediaBrowserService;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ServiceTestRule;
@@ -41,6 +41,9 @@ import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;

import org.junit.Assert;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.util.MockUtil;

@@ -63,6 +66,8 @@ public class TestUtils {

    private static String sSystemScreenOffTimeout = "10000";

    private static final String TAG = "BluetoothTestUtils";

    /**
     * Utility method to replace obj.fieldName with newValue where obj is of type c
     *
@@ -397,19 +402,22 @@ public class TestUtils {
    public static void setUpUiTest() throws Exception {
        final UiDevice device = UiDevice.getInstance(
                androidx.test.platform.app.InstrumentationRegistry.getInstrumentation());
        // Turn on screen and unlock
        device.wakeUp();
        device.executeShellCommand("wm dismiss-keyguard");

        // Disable animation
        device.executeShellCommand("settings put global window_animation_scale 0.0");
        device.executeShellCommand("settings put global transition_animation_scale 0.0");
        device.executeShellCommand("settings put global animator_duration_scale 0.0");

        // change device screen_off_timeout
        // change device screen_off_timeout to 5 minutes
        sSystemScreenOffTimeout =
                device.executeShellCommand("settings get system screen_off_timeout");
        device.executeShellCommand("settings put system screen_off_timeout 30000");
        device.executeShellCommand("settings put system screen_off_timeout 300000");

        // Turn on screen and unlock
        device.wakeUp();
        device.executeShellCommand("wm dismiss-keyguard");

        // Back to home screen, in case some dialog/activity is in front
        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressHome();
    }

    public static void tearDownUiTest() throws Exception {
@@ -427,6 +435,48 @@ public class TestUtils {
                + sSystemScreenOffTimeout);
    }

    public static class RetryTestRule implements TestRule {
        private int retryCount = 5;

        public RetryTestRule() {
            this(5);
        }

        public RetryTestRule(int retryCount) {
            this.retryCount = retryCount;
        }

        public Statement apply(Statement base, Description description) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    Throwable caughtThrowable = null;

                    // implement retry logic here
                    for (int i = 0; i < retryCount; i++) {
                        try {
                            base.evaluate();
                            return;
                        } catch (Throwable t) {
                            caughtThrowable = t;
                            Log.e(
                                    TAG,
                                    description.getDisplayName() + ": run " + (i + 1) + " failed",
                                    t);
                        }
                    }
                    Log.e(
                            TAG,
                            description.getDisplayName()
                                    + ": giving up after "
                                    + retryCount
                                    + " failures");
                    throw caughtThrowable;
                }
            };
        }
    }

    /**
     * Helper class used to run synchronously a runnable action on a looper.
     */
+6 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.bluetooth.TestUtils;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.MockitoAnnotations;

@@ -47,6 +48,11 @@ public class BluetoothOppBtEnableActivityTest {
    Intent mIntent;
    Context mTargetContext;

    // Activity tests can sometimes flaky because of external factors like system dialog, etc.
    // making the expected Espresso's root not focused or the activity doesn't show up.
    // Add retry rule to resolve this problem.
    @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
+6 −1
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ import com.android.bluetooth.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import java.io.IOException;

@RunWith(AndroidJUnit4.class)
public class BluetoothOppBtEnablingActivityTest {
@@ -62,6 +62,11 @@ public class BluetoothOppBtEnablingActivityTest {

    int mRealTimeoutValue;

    // Activity tests can sometimes flaky because of external factors like system dialog, etc.
    // making the expected Espresso's root not focused or the activity doesn't show up.
    // Add retry rule to resolve this problem.
    @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
+6 −4
Original line number Diff line number Diff line
@@ -20,11 +20,9 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.DONT_KILL_APP;

import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import static com.google.common.truth.Truth.assertThat;

@@ -49,12 +47,12 @@ import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.BluetoothMethodProxy;
import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -62,7 +60,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.File;
import java.io.IOException;

@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -74,6 +71,11 @@ public class BluetoothOppLauncherActivityTest {
    @Mock
    BluetoothOppManager mBluetoothOppManager;

    // Activity tests can sometimes flaky because of external factors like system dialog, etc.
    // making the expected Espresso's root not focused or the activity doesn't show up.
    // Add retry rule to resolve this problem.
    @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
+7 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.bluetooth.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -69,6 +70,12 @@ public class BluetoothOppNotificationTest {

    ComponentName mReceiverName;
    int mPreviousState;

    // Activity tests can sometimes flaky because of external factors like system dialog, etc.
    // making the expected Espresso's root not focused or the activity doesn't show up.
    // Add retry rule to resolve this problem.
    @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
Loading