Added RepetitiveTest annotation and test runner support
Change-Id: I7bf0871ede6dd69512c6b6ea3484693ba5b78e89
This commit is contained in:
@@ -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;
|
||||
@@ -344,4 +360,4 @@ public class InstrumentationTestCase extends TestCase {
|
||||
Runtime.getRuntime().gc();
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
core/java/android/test/RepetitiveTest.java
Normal file
40
core/java/android/test/RepetitiveTest.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user