summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChalard Jean <jchalard@google.com>2020-04-13 10:55:57 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-04-13 10:55:57 +0000
commit75de1de47130f91163f9c58e671c7b411684c5ff (patch)
treef899b6d7c1f8390689ce83cfc8b7c87c645c9452
parent027d39f27c385e78e5a954f68932d70cff9589ef (diff)
parent952c16bb24ebee8ff1b5e327845a80455a9aa6ba (diff)
Add a test runner to ignore tests on old SDKs am: 952c16bb24
Change-Id: Ic296279e50568cc9a2dddb2d053108efe11db170
-rw-r--r--tests/lib/Android.bp1
-rw-r--r--tests/lib/src/com/android/testutils/DevSdkIgnoreRule.kt31
-rw-r--r--tests/lib/src/com/android/testutils/DevSdkIgnoreRunner.kt72
3 files changed, 94 insertions, 10 deletions
diff --git a/tests/lib/Android.bp b/tests/lib/Android.bp
index d43243f..47b950d 100644
--- a/tests/lib/Android.bp
+++ b/tests/lib/Android.bp
@@ -39,6 +39,7 @@ java_library {
"androidx.annotation_annotation",
],
static_libs: [
+ "androidx.test.ext.junit",
"net-tests-utils-multivariant",
],
}
diff --git a/tests/lib/src/com/android/testutils/DevSdkIgnoreRule.kt b/tests/lib/src/com/android/testutils/DevSdkIgnoreRule.kt
index d30138d..4a83f6f 100644
--- a/tests/lib/src/com/android/testutils/DevSdkIgnoreRule.kt
+++ b/tests/lib/src/com/android/testutils/DevSdkIgnoreRule.kt
@@ -23,6 +23,23 @@ import org.junit.runner.Description
import org.junit.runners.model.Statement
/**
+ * Returns true if the development SDK version of the device is in the provided range.
+ *
+ * If the device is not using a release SDK, the development SDK is considered to be higher than
+ * [Build.VERSION.SDK_INT].
+ */
+fun isDevSdkInRange(minExclusive: Int?, maxInclusive: Int?): Boolean {
+ // In-development API n+1 will have SDK_INT == n and CODENAME != REL.
+ // Stable API n has SDK_INT == n and CODENAME == REL.
+ val release = "REL" == Build.VERSION.CODENAME
+ val sdkInt = Build.VERSION.SDK_INT
+ val devApiLevel = sdkInt + if (release) 0 else 1
+
+ return (minExclusive == null || devApiLevel > minExclusive) &&
+ (maxInclusive == null || devApiLevel <= maxInclusive)
+}
+
+/**
* A test rule to ignore tests based on the development SDK level.
*
* If the device is not using a release SDK, the development SDK is considered to be higher than
@@ -63,16 +80,10 @@ class DevSdkIgnoreRule @JvmOverloads constructor(
val ignoreAfter = description.getAnnotation(IgnoreAfter::class.java)
val ignoreUpTo = description.getAnnotation(IgnoreUpTo::class.java)
- // In-development API n+1 will have SDK_INT == n and CODENAME != REL.
- // Stable API n has SDK_INT == n and CODENAME == REL.
- val release = "REL" == Build.VERSION.CODENAME
- val sdkInt = Build.VERSION.SDK_INT
- val devApiLevel = sdkInt + if (release) 0 else 1
- val message = "Skipping test for ${if (!release) "non-" else ""}release SDK $sdkInt"
- assumeTrue(message, ignoreClassAfter == null || devApiLevel <= ignoreClassAfter)
- assumeTrue(message, ignoreClassUpTo == null || devApiLevel > ignoreClassUpTo)
- assumeTrue(message, ignoreAfter == null || devApiLevel <= ignoreAfter.value)
- assumeTrue(message, ignoreUpTo == null || devApiLevel > ignoreUpTo.value)
+ val message = "Skipping test for build ${Build.VERSION.CODENAME} " +
+ "with SDK ${Build.VERSION.SDK_INT}"
+ assumeTrue(message, isDevSdkInRange(ignoreClassUpTo, ignoreClassAfter))
+ assumeTrue(message, isDevSdkInRange(ignoreUpTo?.value, ignoreAfter?.value))
base.evaluate()
}
}
diff --git a/tests/lib/src/com/android/testutils/DevSdkIgnoreRunner.kt b/tests/lib/src/com/android/testutils/DevSdkIgnoreRunner.kt
new file mode 100644
index 0000000..73b2843
--- /dev/null
+++ b/tests/lib/src/com/android/testutils/DevSdkIgnoreRunner.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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 com.android.testutils
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import org.junit.runner.Description
+import org.junit.runner.Runner
+import org.junit.runner.notification.RunNotifier
+
+/**
+ * A runner that can skip tests based on the development SDK as defined in [DevSdkIgnoreRule].
+ *
+ * Generally [DevSdkIgnoreRule] should be used for that purpose (using rules is preferable over
+ * replacing the test runner), however JUnit runners inspect all methods in the test class before
+ * processing test rules. This may cause issues if the test methods are referencing classes that do
+ * not exist on the SDK of the device the test is run on.
+ *
+ * This runner inspects [IgnoreAfter] and [IgnoreUpTo] annotations on the test class, and will skip
+ * the whole class if they do not match the development SDK as defined in [DevSdkIgnoreRule].
+ * Otherwise, it will delegate to [AndroidJUnit4] to run the test as usual.
+ *
+ * Example usage:
+ *
+ * @RunWith(DevSdkIgnoreRunner::class)
+ * @IgnoreUpTo(Build.VERSION_CODES.Q)
+ * class MyTestClass { ... }
+ */
+class DevSdkIgnoreRunner(private val klass: Class<*>) : Runner() {
+ private val baseRunner = klass.let {
+ val ignoreAfter = it.getAnnotation(IgnoreAfter::class.java)
+ val ignoreUpTo = it.getAnnotation(IgnoreUpTo::class.java)
+
+ if (isDevSdkInRange(ignoreUpTo?.value, ignoreAfter?.value)) AndroidJUnit4(klass) else null
+ }
+
+ override fun run(notifier: RunNotifier) {
+ if (baseRunner != null) {
+ baseRunner.run(notifier)
+ return
+ }
+
+ // Report a single, skipped placeholder test for this class, so that the class is still
+ // visible as skipped in test results.
+ notifier.fireTestIgnored(
+ Description.createTestDescription(klass, "skippedClassForDevSdkMismatch"))
+ }
+
+ override fun getDescription(): Description {
+ return baseRunner?.description ?: Description.createSuiteDescription(klass)
+ }
+
+ override fun testCount(): Int {
+ // When ignoring the tests, a skipped placeholder test is reported, so test count is 1.
+ return baseRunner?.testCount() ?: 1
+ }
+} \ No newline at end of file