summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Lam <yukl@google.com>2017-02-10 20:59:06 -0800
committerMaurice Lam <yukl@google.com>2017-02-17 11:06:21 -0800
commitb2ff57b17efb727c24b096ac7b1d7f8870bf1bde (patch)
treecf13152d27ea0a0f4205a23bebff4c0d8a35c2ab
parent0093ffd929d0f3336ab08127d174ab9b822b8e4b (diff)
downloadsetupwizard-b2ff57b17efb727c24b096ac7b1d7f8870bf1bde.tar.gz
Use constants=BuildConfig.class for robolectric
In robolectric tests, use @Config(constants=BuildConfig.class), which is the "gradle way" to configure Robolectric. Added the hacks that are needed to make that happen in our setup, like PatchedGradleManifestFactory and the custom build directory lookup. Having this change allows Robolectric tests to run against merged resources, which means different build variants will now resolve resources correctly. Previously a test would fail in, say, resolving @style/SuwThemeGlif. Also migrated GlifDimensionTest to run on Robolectric. Test: ./gradlew test Change-Id: Ia7231f95818891a649678a0a6da0220a44031bf7
-rw-r--r--library/test/instrumentation/src/com/android/setupwizardlib/test/GlifDimensionTest.java115
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/BaseRobolectricTest.java26
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/robolectric/PatchedGradleManifestFactory.java126
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/robolectric/SuwLibRobolectricTestRunner.java64
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java10
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/util/GlifDimensionTest.java77
-rw-r--r--library/test/robotest/src/com/android/setupwizardlib/util/PartnerTest.java10
7 files changed, 279 insertions, 149 deletions
diff --git a/library/test/instrumentation/src/com/android/setupwizardlib/test/GlifDimensionTest.java b/library/test/instrumentation/src/com/android/setupwizardlib/test/GlifDimensionTest.java
deleted file mode 100644
index 4e93166..0000000
--- a/library/test/instrumentation/src/com/android/setupwizardlib/test/GlifDimensionTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2015 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.setupwizardlib.test;
-
-import static org.junit.Assert.assertEquals;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.os.Build;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.ContextThemeWrapper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class GlifDimensionTest {
-
- private static final String TAG = "GlifDimensionTest";
-
- private Context mContext;
-
- @Before
- public void setUp() {
- mContext = new ContextThemeWrapper(InstrumentationRegistry.getTargetContext(),
- R.style.SuwThemeGlif_Light);
- }
-
- @Test
- public void testDividerInsetPhone() {
- // The screen width APIs needed for this this were introduced in Honeycomb MR2
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
- setConfigurationScreenSize(480, 640);
- final TypedArray a = mContext.obtainStyledAttributes(new int[]{R.attr.suwMarginSides});
- final int marginSides = a.getDimensionPixelSize(0, 0);
- assertEquals("Margin sides for phones should be 24dp", dp2Px(24), marginSides);
- a.recycle();
-
- final Resources res = mContext.getResources();
- final int dividerTextInset = res.getDimensionPixelSize(
- R.dimen.suw_items_glif_text_divider_inset);
- assertEquals(marginSides, dividerTextInset);
- final int dividerIconInset = res.getDimensionPixelSize(
- R.dimen.suw_items_glif_icon_divider_inset);
- final int iconWidth = res.getDimensionPixelSize(R.dimen.suw_items_icon_container_width);
- assertEquals(marginSides + iconWidth, dividerIconInset);
- } else {
- Log.d(TAG, "Cannot test divider inset because SDK version < 13");
- }
- }
-
- @Test
- public void testDividerInsetSw600dp() {
- // The screen width APIs needed for this this were introduced in Honeycomb MR2
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
- setConfigurationScreenSize(800, 1024);
- final TypedArray a = mContext.obtainStyledAttributes(new int[]{R.attr.suwMarginSides});
- final int marginSides = a.getDimensionPixelSize(0, 0);
- assertEquals("Margin sides for sw600dp should be 40dp", dp2Px(40), marginSides);
- a.recycle();
-
- final Resources res = mContext.getResources();
- final int dividerTextInset = res.getDimensionPixelSize(
- R.dimen.suw_items_glif_text_divider_inset);
- assertEquals(marginSides, dividerTextInset);
-
- final int dividerIconInset = res.getDimensionPixelSize(
- R.dimen.suw_items_glif_icon_divider_inset);
- final int iconWidth = res.getDimensionPixelSize(R.dimen.suw_items_icon_container_width);
- assertEquals(marginSides + iconWidth, dividerIconInset);
- } else {
- Log.d(TAG, "Cannot test divider inset because SDK version < 13");
- }
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
- private void setConfigurationScreenSize(int width, int height) {
- final Resources res = mContext.getResources();
- final Configuration config = res.getConfiguration();
- config.screenWidthDp = width;
- config.screenHeightDp = height;
- config.smallestScreenWidthDp = Math.min(width, height);
-
- res.updateConfiguration(config, res.getDisplayMetrics());
- }
-
- private int dp2Px(float dp) {
- DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
- return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
- }
-}
diff --git a/library/test/robotest/src/com/android/setupwizardlib/BaseRobolectricTest.java b/library/test/robotest/src/com/android/setupwizardlib/BaseRobolectricTest.java
deleted file mode 100644
index 50250d9..0000000
--- a/library/test/robotest/src/com/android/setupwizardlib/BaseRobolectricTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 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.setupwizardlib;
-
-import org.robolectric.annotation.Config;
-
-@Config(
- manifest = "main/AndroidManifest.xml",
- sdk = 23
-)
-public class BaseRobolectricTest {
-}
diff --git a/library/test/robotest/src/com/android/setupwizardlib/robolectric/PatchedGradleManifestFactory.java b/library/test/robotest/src/com/android/setupwizardlib/robolectric/PatchedGradleManifestFactory.java
new file mode 100644
index 0000000..64c63e7
--- /dev/null
+++ b/library/test/robotest/src/com/android/setupwizardlib/robolectric/PatchedGradleManifestFactory.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2017 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.setupwizardlib.robolectric;
+
+import org.robolectric.annotation.Config;
+import org.robolectric.internal.GradleManifestFactory;
+import org.robolectric.internal.ManifestIdentifier;
+import org.robolectric.res.FileFsFile;
+import org.robolectric.util.Logger;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * Modified GradleManifestFactory to patch an issue where some build variants have merged
+ * resources under res/merged/variant/type while others have it under bundles/variant/type/res.
+ *
+ * The change is that in the .exists() checks below we check for specific folders for the build
+ * variant rather than checking existence at the parent directory.
+ */
+class PatchedGradleManifestFactory extends GradleManifestFactory {
+
+ @Override
+ public ManifestIdentifier identify(Config config) {
+ if (config.constants() == Void.class) {
+ Logger.error("Field 'constants' not specified in @Config annotation");
+ Logger.error("This is required when using Robolectric with Gradle!");
+ throw new RuntimeException("No 'constants' field in @Config annotation!");
+ }
+
+ final String buildOutputDir = getBuildOutputDir(config);
+ final String type = getType(config);
+ final String flavor = getFlavor(config);
+ final String abiSplit = getAbiSplit(config);
+ final String packageName = config.packageName().isEmpty()
+ ? config.constants().getPackage().getName()
+ : config.packageName();
+
+ final FileFsFile res;
+ final FileFsFile assets;
+ final FileFsFile manifest;
+
+ if (FileFsFile.from(buildOutputDir, "data-binding-layout-out", flavor, type).exists()) {
+ // Android gradle plugin 1.5.0+ puts the merged layouts in data-binding-layout-out.
+ // https://github.com/robolectric/robolectric/issues/2143
+ res = FileFsFile.from(buildOutputDir, "data-binding-layout-out", flavor, type);
+ } else if (FileFsFile.from(buildOutputDir, "res", "merged", flavor, type).exists()) {
+ // res/merged added in Android Gradle plugin 1.3-beta1
+ res = FileFsFile.from(buildOutputDir, "res", "merged", flavor, type);
+ } else if (FileFsFile.from(buildOutputDir, "res", flavor, type).exists()) {
+ res = FileFsFile.from(buildOutputDir, "res", flavor, type);
+ } else {
+ res = FileFsFile.from(buildOutputDir, "bundles", flavor, type, "res");
+ }
+
+ if (FileFsFile.from(buildOutputDir, "assets", flavor, type).exists()) {
+ assets = FileFsFile.from(buildOutputDir, "assets", flavor, type);
+ } else {
+ assets = FileFsFile.from(buildOutputDir, "bundles", flavor, type, "assets");
+ }
+
+ String manifestName = config.manifest();
+ URL manifestUrl = getClass().getClassLoader().getResource(manifestName);
+ if (manifestUrl != null && manifestUrl.getProtocol().equals("file")) {
+ manifest = FileFsFile.from(manifestUrl.getPath());
+ } else if (FileFsFile.from(buildOutputDir, "manifests", "full", flavor, abiSplit, type,
+ manifestName).exists()) {
+ manifest = FileFsFile.from(
+ buildOutputDir, "manifests", "full", flavor, abiSplit, type, manifestName);
+ } else if (FileFsFile.from(buildOutputDir, "manifests", "aapt", flavor, abiSplit, type,
+ manifestName).exists()) {
+ // Android gradle plugin 2.2.0+ can put library manifest files inside of "aapt"
+ // instead of "full"
+ manifest = FileFsFile.from(buildOutputDir, "manifests", "aapt", flavor, abiSplit,
+ type, manifestName);
+ } else {
+ manifest = FileFsFile.from(buildOutputDir, "bundles", flavor, abiSplit, type,
+ manifestName);
+ }
+
+ return new ManifestIdentifier(manifest, res, assets, packageName, null);
+ }
+
+ private static String getBuildOutputDir(Config config) {
+ return config.buildDir() + File.separator + "intermediates";
+ }
+
+ private static String getType(Config config) {
+ try {
+ return ReflectionHelpers.getStaticField(config.constants(), "BUILD_TYPE");
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ private static String getFlavor(Config config) {
+ try {
+ return ReflectionHelpers.getStaticField(config.constants(), "FLAVOR");
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ private static String getAbiSplit(Config config) {
+ try {
+ return config.abiSplit();
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+}
diff --git a/library/test/robotest/src/com/android/setupwizardlib/robolectric/SuwLibRobolectricTestRunner.java b/library/test/robotest/src/com/android/setupwizardlib/robolectric/SuwLibRobolectricTestRunner.java
new file mode 100644
index 0000000..509201a
--- /dev/null
+++ b/library/test/robotest/src/com/android/setupwizardlib/robolectric/SuwLibRobolectricTestRunner.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 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.setupwizardlib.robolectric;
+
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.internal.ManifestFactory;
+
+public class SuwLibRobolectricTestRunner extends RobolectricTestRunner {
+
+ private String mModuleRootPath;
+
+ public SuwLibRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ // Hack to determine the module root path in the build folder (e.g. out/gradle/setup-wizard-lib)
+ private void updateModuleRootPath(Config config) {
+ String moduleRoot = config.constants().getResource("").toString()
+ .replace("file:", "").replace("jar:", "");
+ mModuleRootPath =
+ moduleRoot.substring(0, moduleRoot.lastIndexOf("/build")) + "/setup-wizard-lib";
+ }
+
+ /**
+ * Return the default config used to run Robolectric tests.
+ */
+ @Override
+ protected Config buildGlobalConfig() {
+ Config parent = super.buildGlobalConfig();
+ updateModuleRootPath(parent);
+ return new Config.Builder(parent)
+ .setBuildDir(mModuleRootPath + "/build")
+ .build();
+ }
+
+ @Override
+ protected ManifestFactory getManifestFactory(Config config) {
+ return new PatchedGradleManifestFactory();
+ }
+
+ @Override
+ protected void runChild(FrameworkMethod method, RunNotifier notifier) {
+ System.out.println("===== Running " + method + " =====");
+ super.runChild(method, notifier);
+ }
+}
diff --git a/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java b/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java
index 9909460..7dd0a6f 100644
--- a/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java
+++ b/library/test/robotest/src/com/android/setupwizardlib/span/LinkSpanTest.java
@@ -23,14 +23,16 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.widget.TextView;
-import com.android.setupwizardlib.BaseRobolectricTest;
+import com.android.setupwizardlib.BuildConfig;
+import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
-@RunWith(RobolectricTestRunner.class)
-public class LinkSpanTest extends BaseRobolectricTest {
+@RunWith(SuwLibRobolectricTestRunner.class)
+@Config(constants = BuildConfig.class)
+public class LinkSpanTest {
@Test
public void testOnClick() {
diff --git a/library/test/robotest/src/com/android/setupwizardlib/util/GlifDimensionTest.java b/library/test/robotest/src/com/android/setupwizardlib/util/GlifDimensionTest.java
new file mode 100644
index 0000000..3cc4893
--- /dev/null
+++ b/library/test/robotest/src/com/android/setupwizardlib/util/GlifDimensionTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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.setupwizardlib.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.view.ContextThemeWrapper;
+
+import com.android.setupwizardlib.BuildConfig;
+import com.android.setupwizardlib.R;
+import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SuwLibRobolectricTestRunner.class)
+@Config(constants = BuildConfig.class, sdk = Config.ALL_SDKS)
+public class GlifDimensionTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = new ContextThemeWrapper(application, R.style.SuwThemeGlif_Light);
+ }
+
+ @Test
+ public void testDividerInsetPhone() {
+ assertDividerInset();
+ }
+
+ @Config(qualifiers = "sw600dp")
+ @Test
+ public void testDividerInsetSw600dp() {
+ assertDividerInset();
+ }
+
+ private void assertDividerInset() {
+ final Resources res = mContext.getResources();
+
+ final TypedArray a = mContext.obtainStyledAttributes(new int[]{R.attr.suwMarginSides});
+ final int marginSides = a.getDimensionPixelSize(0, 0);
+ a.recycle();
+
+ assertEquals(
+ "Dimensions should satisfy constraint: "
+ + "?attr/suwMarginSides = suw_items_glif_text_divider_inset",
+ marginSides,
+ res.getDimensionPixelSize(R.dimen.suw_items_glif_text_divider_inset));
+
+ assertEquals(
+ "Dimensions should satisfy constraint: ?attr/suwMarginSides + "
+ + "suw_items_icon_container_width = suw_items_glif_icon_divider_inset",
+ marginSides + res.getDimensionPixelSize(R.dimen.suw_items_icon_container_width),
+ res.getDimensionPixelSize(R.dimen.suw_items_glif_icon_divider_inset));
+ }
+}
diff --git a/library/test/robotest/src/com/android/setupwizardlib/util/PartnerTest.java b/library/test/robotest/src/com/android/setupwizardlib/util/PartnerTest.java
index 61dd65d..8133b6a 100644
--- a/library/test/robotest/src/com/android/setupwizardlib/util/PartnerTest.java
+++ b/library/test/robotest/src/com/android/setupwizardlib/util/PartnerTest.java
@@ -34,22 +34,24 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import com.android.setupwizardlib.BaseRobolectricTest;
+import com.android.setupwizardlib.BuildConfig;
import com.android.setupwizardlib.R;
+import com.android.setupwizardlib.robolectric.SuwLibRobolectricTestRunner;
import com.android.setupwizardlib.util.Partner.ResourceEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.res.builder.DefaultPackageManager;
import org.robolectric.shadows.ShadowResources;
import java.util.Arrays;
-@RunWith(RobolectricTestRunner.class)
-public class PartnerTest extends BaseRobolectricTest {
+@RunWith(SuwLibRobolectricTestRunner.class)
+@Config(constants = BuildConfig.class)
+public class PartnerTest {
private static final String ACTION_PARTNER_CUSTOMIZATION =
"com.android.setupwizard.action.PARTNER_CUSTOMIZATION";