AndroidManifest.xml not found in RobolectricGradleTestRunner
davidschreiber opened this issue · comments
Android Studio: 1.2 Preview 4
Gradle Plugin: 1.1.0
Robolectric: 3.0-rc1
When trying to run Robolectric unit tests within Android Studio the test runner fails with following error message:
java.io.FileNotFoundException: build/intermediates/bundles/debug/AndroidManifest.xml (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
java.lang.UnsupportedOperationException: Robolectric does not support API level 1.
at org.robolectric.internal.SdkConfig.<init>(SdkConfig.java:28)
at org.robolectric.RobolectricTestRunner.pickSdkVersion(RobolectricTestRunner.java:439)
at org.robolectric.RobolectricTestRunner.getEnvironment(RobolectricTestRunner.java:274)
at org.robolectric.RobolectricTestRunner.access$300(RobolectricTestRunner.java:50)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:193)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:168)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
at org.robolectric.res.FileFsFile.getInputStream(FileFsFile.java:78)
at org.robolectric.manifest.AndroidManifest.parseAndroidManifest(AndroidManifest.java:132)
at org.robolectric.manifest.AndroidManifest.getTargetSdkVersion(AndroidManifest.java:485)
at org.robolectric.RobolectricTestRunner.pickSdkVersion(RobolectricTestRunner.java:439)
at org.robolectric.RobolectricTestRunner.getEnvironment(RobolectricTestRunner.java:274)
at org.robolectric.RobolectricTestRunner.access$300(RobolectricTestRunner.java:50)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:193)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:168)
This happens with my own test setup as well as with the robolectric-samples
.
As far as I understand the RobolectricGradleTestRunner
tries to read the merged manifest from <projectRoot>/build/intermediates/manifests/full/debug/AndroidManifest.xml
whereas the manifest resides within the modules build folder located under <projectRoot>/app/build/intermediates/manifests/full/debug/AndroidManifest.xml
(notice the app
in the path). Therefore, it is not able to find the correct manifest and used SDK version.
Also the RobolectricGradleTestRunner
seems to ignore the manifest defined within the @Config
annotation, making it impossible to start tests.
This should only be true for Mac user and is documented at https://github.com/robolectric/robolectric/wiki/Running-tests-in-Android-Studio
But I don't like to do "not necessary" customization which must be applied from each developer that the reason why I use a custom runner https://github.com/nenick/AndroidStudioAndRobolectric/blob/master/app/src/test/java/com/example/myapplication/CustomRobolectricRunner.java
Thanks, I am now also using a custom test runner which also works around problems with the applicationIdSuffix
for debug build types (Robolectric would fail to resolve resources because of this). Once the 3.0 release reaches a stable version I would recommend updating the documentation on the official site (if the Mac problem is not resolved till then).
Also the RobolectricGradleTestRunner seems to ignore the manifest defined within the @config annotation, making it impossible to start tests.
This is by design. The standard RobolectricTestRunner
still exists if you want to configure everything yourself. Note that you don't have to hard-code the 'working directory' value - you can set it to $MODULE_DIR$
which will do the same thing.
I believe I've found a related bug in this area: if you run gradle with -PbuildDir=foo to customize the build output directory, Robolectric fails with the error above (e.g. it's looking for literally the 'build' directory).
I am actually trying to resolve this for one of my customers, not my own app. If this has been fixed in a newer version of Robolectric or dependent library, please comment here and I'll pass the info along to my customer.
Alternatively, if this doesn't fail for you, it means there's something else wonky about my customer's configuration (and I'd like to know that I'm barking up the wrong tree here).
Thanks!
Has this been fixed yet? i get the same error where it cant find my manifest even if i declare it on the Config annotation
As long as you're not using a custom build dir like @stamhankar999, this has been fixed for awhile. You need to use RobolectricGradleTestRunner
and configure Android Studio as shown in http://robolectric.org/getting-started/ (read the Building with Android Studio section). Also, the robolectric-samples
project has a ton of examples that all work in AS.
hiya i am not using a custom build directory and i am using RobolectricGradleTestRunner. will test the samples and see if those work
@erd This issue should be opened again.
It does work from terminal with gradlew testDebug
but it doesn't work from Android Studio 1.3 (5.0, latest version) with android plugin 1.3.0-beta1
.
It ignores manifest path set in robolectric.properties
or using @Config
annotation. It always fails with the same error.
java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.manifest.AndroidManifest.validate(AndroidManifest.java:120)
at org.robolectric.manifest.AndroidManifest.getResourcePath(AndroidManifest.java:469)
at org.robolectric.manifest.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:475)
at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:479)
at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:471)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:73)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:421)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:185)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:149)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
java.lang.RuntimeException: java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:238)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:185)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:149)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.manifest.AndroidManifest.validate(AndroidManifest.java:120)
at org.robolectric.manifest.AndroidManifest.getResourcePath(AndroidManifest.java:469)
at org.robolectric.manifest.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:475)
at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:479)
at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:471)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:73)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:421)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
... 18 more
Agreed. This still doesn't work
On 19 Jun 2015 18:12, "Tomasz Rozbicki" notifications@github.com wrote:
@erd https://github.com/erd This issue should be opened again.
It does work from terminal with gradlew testDebug but it doesn't work
from Android Studio 1.3 (5.0, latest version) with android plugin
1.3.0-beta1.It ignores manifest path set in robolectric.properties or using @config
annotation. It always fails with the same error.java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.manifest.AndroidManifest.validate(AndroidManifest.java:120)
at org.robolectric.manifest.AndroidManifest.getResourcePath(AndroidManifest.java:469)
at org.robolectric.manifest.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:475)
at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:479)
at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:471)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:73)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:421)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:185)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:149)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)java.lang.RuntimeException: java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:238)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:185)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:149)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.manifest.AndroidManifest.validate(AndroidManifest.java:120)
at org.robolectric.manifest.AndroidManifest.getResourcePath(AndroidManifest.java:469)
at org.robolectric.manifest.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:475)
at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:479)
at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:471)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:73)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:421)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:234)
... 18 more—
Reply to this email directly or view it on GitHub
#1648 (comment)
.
Ok, there are two possible solutions:
- Edit "Working directory" in "Run/Debug configuration"
/home/toro/workspace/bb/priv/MODULE_NAME
or
$MODULE_DIR$
cons: you have to do it manually for every run configuration
- Create custom runner with different
BUILD_OUTPUT
. This value should be set toMODULE_NAME/build/intermediates
pros: always works, you can forget about changing working directory
public class MyRunner extends RobolectricTestRunner {
private static final String BUILD_OUTPUT = "app/build/intermediates";
public MyRunner(Class<?> klass) throws InitializationError {
super(klass);
}
@Override
protected AndroidManifest getAppManifest(Config config) {
if (config.constants() == Void.class) {
Logger.error("Field 'constants' not specified in @Config annotation");
Logger.error("This is required when using RobolectricGradleTestRunner!");
throw new RuntimeException("No 'constants' field in @Config annotation!");
}
final String type = getType(config);
final String flavor = getFlavor(config);
final String packageName = getPackageName(config);
final FileFsFile res;
final FileFsFile assets;
final FileFsFile manifest;
if (FileFsFile.from(BUILD_OUTPUT, "res").exists()) {
res = FileFsFile.from(BUILD_OUTPUT, "res", flavor, type);
} else {
res = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "res");
}
if (FileFsFile.from(BUILD_OUTPUT, "assets").exists()) {
assets = FileFsFile.from(BUILD_OUTPUT, "assets", flavor, type);
} else {
assets = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "assets");
}
if (FileFsFile.from(BUILD_OUTPUT, "manifests").exists()) {
manifest = FileFsFile.from(BUILD_OUTPUT, "manifests", "full", flavor, type, "AndroidManifest.xml");
} else {
manifest = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "AndroidManifest.xml");
}
Logger.debug("Robolectric assets directory: " + assets.getPath());
Logger.debug(" Robolectric res directory: " + res.getPath());
Logger.debug(" Robolectric manifest path: " + manifest.getPath());
Logger.debug(" Robolectric package name: " + packageName);
return new AndroidManifest(manifest, res, assets, packageName);
}
private String getType(Config config) {
try {
return ReflectionHelpers.getStaticField(config.constants(), "BUILD_TYPE");
} catch (Throwable e) {
return null;
}
}
private String getFlavor(Config config) {
try {
return ReflectionHelpers.getStaticField(config.constants(), "FLAVOR");
} catch (Throwable e) {
return null;
}
}
private String getPackageName(Config config) {
try {
final String packageName = config.packageName();
if (packageName != null && !packageName.isEmpty()) {
return packageName;
} else {
return ReflectionHelpers.getStaticField(config.constants(), "APPLICATION_ID");
}
} catch (Throwable e) {
return null;
}
}
}
Ok, there are two possible solutions:
Edit "Working directory" in "Run/Debug configuration"
FWIW: This is documented at http://robolectric.org/getting-started/
You're right, that's why I've added it.
If you create a lot of run configurations on the fly this is pain in the a*s.
You can edit the default run configuration so that all of the ones created on the fly already have the path set.
@sparkym3 Could you please provide information how to set it? I've not found any settings in AS. I'll stay with custom runner, because it works for every other team member without any additional actions, but it may be useful to other developers as well.
You have to set working directory to