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

Commit 3fc03e61 authored by Jack Wang's avatar Jack Wang
Browse files

Added RepetitiveTest annotation and test runner support

Change-Id: I7bf0871ede6dd69512c6b6ea3484693ba5b78e89
parent 62f2ada6
Loading
Loading
Loading
Loading
+21 −5
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ public class InstrumentationTestCase extends TestCase {
     * @param instrumentation the instrumentation to use with this instance
     *
     * @deprecated Incorrect spelling,
     * use {@link #injectInstrumentation(android.app.Instrumentation) instead.
     * use {@link #injectInstrumentation(android.app.Instrumentation)} instead.
     */
    @Deprecated
    public void injectInsrumentation(Instrumentation instrumentation) {
@@ -170,18 +170,23 @@ public class InstrumentationTestCase extends TestCase {
        }

        int runCount = 1;
        boolean isRepetitive = false;
        if (method.isAnnotationPresent(FlakyTest.class)) {
            runCount = method.getAnnotation(FlakyTest.class).tolerance();
        } else if (method.isAnnotationPresent(RepetitiveTest.class)) {
            runCount = method.getAnnotation(RepetitiveTest.class).numIterations();
            isRepetitive = true;
        }

        if (method.isAnnotationPresent(UiThreadTest.class)) {
            final int tolerance = runCount;
            final boolean repetitive = isRepetitive;
            final Method testMethod = method;
            final Throwable[] exceptions = new Throwable[1];
            getInstrumentation().runOnMainSync(new Runnable() {
                public void run() {
                    try {
                        runMethod(testMethod, tolerance);
                        runMethod(testMethod, tolerance, repetitive);
                    } catch (Throwable throwable) {
                        exceptions[0] = throwable;
                    }
@@ -191,11 +196,16 @@ public class InstrumentationTestCase extends TestCase {
                throw exceptions[0];
            }
        } else {
            runMethod(method, runCount);
            runMethod(method, runCount, isRepetitive);
        }
    }

    // For backwards-compatibility after adding isRepetitive
    private void runMethod(Method runMethod, int tolerance) throws Throwable {
        runMethod(runMethod, tolerance, false);
    }

    private void runMethod(Method runMethod, int tolerance, boolean isRepetitive) throws Throwable {
        Throwable exception = null;

        int runCount = 0;
@@ -211,8 +221,14 @@ public class InstrumentationTestCase extends TestCase {
                exception = e;
            } finally {
                runCount++;
                // Report current iteration number, if test is repetitive
                if (isRepetitive) {
                    Bundle iterations = new Bundle();
                    iterations.putInt("currentiterations", runCount);
                    getInstrumentation().sendStatus(2, iterations);
                }
            }
        } while ((runCount < tolerance) && (exception != null));
        } while ((runCount < tolerance) && (isRepetitive || exception != null));

        if (exception != null) {
            throw exception;
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.test;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * This annotation can be used on an {@link android.test.InstrumentationTestCase}'s test methods.
 * When the annotation is present, the test method is executed the number of times specified by
 * numIterations and defaults to 1.
 *
 * {@hide} Not needed for public API.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepetitiveTest {
    /**
     * Indicates the number of times a test case should be run.
     *
     * @return The total number of iterations, the default is 1.
     */
    int numIterations() default 1;
}
 No newline at end of file
+21 −5
Original line number Diff line number Diff line
@@ -238,6 +238,11 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
     * reports the run time in seconds of the current test.
     */
    private static final String REPORT_KEY_RUN_TIME = "runtime";
    /**
     * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
     * reports the number of total iterations of the current test.
     */
    private static final String REPORT_KEY_NUM_ITERATIONS = "numiterations";
    /**
     * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
     * reports the guessed suite assignment for the current test.
@@ -748,6 +753,20 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
                mTestResult.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "");
            }

            Method testMethod = null;
            try {
                testMethod = test.getClass().getMethod(testName);
                // Report total number of iterations, if test is repetitive
                if (testMethod.isAnnotationPresent(RepetitiveTest.class)) {
                    int numIterations = testMethod.getAnnotation(
                        RepetitiveTest.class).numIterations();
                    mTestResult.putInt(REPORT_KEY_NUM_ITERATIONS, numIterations);
                }
            } catch (NoSuchMethodException e) {
                // ignore- the test with given name does not exist. Will be handled during test
                // execution
            }

            // The delay_msec parameter is normally used to provide buffers of idle time
            // for power measurement purposes. To make sure there is a delay before and after
            // every test in a suite, we delay *after* every test (see endTest below) and also
@@ -766,9 +785,9 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
            mIncludeDetailedStats = false;
            try {
                // Look for TimedTest annotation on both test class and test method
                if (test.getClass().getMethod(testName).isAnnotationPresent(TimedTest.class)) {
                if (testMethod.isAnnotationPresent(TimedTest.class)) {
                    mIsTimedTest = true;
                    mIncludeDetailedStats = test.getClass().getMethod(testName).getAnnotation(
                    mIncludeDetailedStats = testMethod.getAnnotation(
                            TimedTest.class).includeDetailedStats();
                } else if (test.getClass().isAnnotationPresent(TimedTest.class)) {
                    mIsTimedTest = true;
@@ -778,9 +797,6 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu
            } catch (SecurityException e) {
                // ignore - the test with given name cannot be accessed. Will be handled during
                // test execution
            } catch (NoSuchMethodException e) {
                // ignore- the test with given name does not exist. Will be handled during test
                // execution
            }

            if (mIsTimedTest && mIncludeDetailedStats) {