Robolectric cannot find AndroidManifest.xml - android

This test originally ran fine. Checked out a new branch several days later (with commits from many other developers) and it no longer works.
Test class in the mylibrary library module:
import com.company.mylibrary.BuildConfig;
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, manifest = "src/main/AndroidManifest.xml", sdk = 21)
public class MyTest {
I have also tried:
#Config(constants = BuildConfig.class, sdk = 21)
#Config(constants = BuildConfig.class, manifest = Config.NONE, sdk = 21)
In the library module's build.gradle
dependencies {
.
.
testCompile 'org.robolectric:robolectric:3.0'
Error message when running inside AS is:
java.lang.RuntimeException: build/intermediates/manifests/full/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
Error message when running from command line is:
com.company.mylibrary.framework1.feature1.MyTest > testMethod STANDARD_ERROR
java.lang.RuntimeException: build/intermediates/manifests/full/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
A) Don't know why it is looking there for the manifest
B) That file/directory does not exist
C) src/main/AndroidManifest.xml does exist
Things I have tried:
- deleted the build directory in that library module
- restarted Android Studio
- Build/Clean
- Build/Rebuild Project
- run the test (both inside AS and from command line)
- and tried different versions of the #Config notation
Seems to be in a wonky state that I cannot clear.
I am working on a MacBook Pro. Android Studio 2.0 beta5

You need to set the working directory within the test's run configuration to the module directory.

Well, I've tackled the issue you're facing right now several times and found solution suitable for myself.
Generally, if your test logic does not require access to the application's resources, it's worth using usual RobolectricTestRunner as the time of the test execution is relatively shorter comparing it to the test execution time under RobolectricGradleTestRunner.
If, for some reason, you need access to the specific AndroidManifest.xml file, IMO it's better to come up with test file rather than to operate on the project's one.
By saying 'test file' I mean the following:
Let's start by defining what are the methods that can help us to obtain path to the resources files. The goal is to be able execute tests under Android Studio and, what's more relevant, via CLI (gradle :project:testBuildTypeUnitTest)
Java's System class: System.getProperty('user.dir') returns User's current working directory. Obtaining current directory we are in may help us to obtain paths to the resources we need to run our test having them provided.
Overriding RobolectricGradleTestRunner. To create our customized test runner we need the AndroidManifest.xml, the res directory and the assets directory paths:
public class CompassApplicationRobolectricTestRunner extends RobolectricGradleTestRunner {
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.LOLLIPOP;
private static final int MIN_SDK_VERSION = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
public CompassApplicationRobolectricTestRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
protected AndroidManifest getAppManifest(Config config) {
final String manifestPath = PathResolver.resolveAndroidManifestPath();
final String resourcesPath = PathResolver.resolveResPath();
final String assetsPath = PathResolver.resolveAssetsPath();
AndroidManifest manifest = new AndroidManifest(
Fs.fileFromPath(manifestPath),
Fs.fileFromPath(resourcesPath),
Fs.fileFromPath(assetsPath)) {
#Override
public int getTargetSdkVersion() {
return TARGET_SDK_VERSION;
}
#Override
public int getMinSdkVersion() {
return MIN_SDK_VERSION;
}
};
return manifest;
}
}
Below, is the link to the example that worked for me. It was developed, however, some time ago and from the time perspective I see it can be done more elegant way so if you decide to apply this solution to your project, organize your path constants to be static and immutable:
https://github.com/dawidgdanski/android-compass-api/blob/master/app-tests/src/test/java/pl/dawidgdanski/compass/PathResolver.java
It's worth remembering that File.separator returns system's default directories separator. It's extremely useful when it comes to provide system-independent paths separated with default separation symbol.
Eventually, if the solution described above is not the one you want to follow, read decent article about setting up testing environment available here:
http://artemzin.com/blog/how-to-mock-dependencies-in-unit-integration-and-functional-tests-dagger-robolectric-instrumentation/
Hope that solves your problem.

In my case, I was running a single test manually (Right click and run) from inside Android Studio and Roboelectric wanted a RELEASE version. The question above was about debug but my test runs for some reason wanted a release version of the manifiest.
java.lang.RuntimeException: build/intermediates/manifests/release/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
I had never done a production build in this project so that build directory had never been created.
After wrestling for a bit with no success (setting the path in configuration, trying to get the path in my CustomRoboelectric file), I just generated a production build so that I had the release path created with a manifest and everything worked.
So my solution was to just run the build to create what Roboelectric wanted.

Related

Testing inconvenience: Android Studio JUnit vs Gradle based: testOptions ignored by Android Studio

The following was done with Android Studio 3.4, Android Gradle Plugin 3.3.2 and Gradle 4.10.3.
In the build.gradle file, I have configured some unit test options like this:
android {
testOptions {
unitTests.all {
systemProperty "debug","true"
}
}
}
I do have a test function that tries to read this property:
package com.demo;
public class SysPropTestDemo {
#Test
public static void dumpSysProps() {
System.out.println("sysprop(debug)=" + System.getProperty("debug"));
}
}
When run via command line gradlew test --test com.demo.SysPropTestDemo I will get the property debug set correctly to true. If I run the same test via Android Studio without setting any options, the value shown will be null.
In order to get the same result from Android Studio, I explicitly have to enter some values in the "Run/Debug Configurations" panel, i.e something like -Ddebug=true in the VM options.
Now this is a trivial example, but what I really want to do, is to add some path to the java.library.path property in order to be able to load a JNI library compiled within the project. (I do need to write some tests that make use a modified SQLite lib, so not using JNI is not an option here)
It does work when setting additional options, but I think this is very inconvenient, since I can't enter a variable based value in the configuration options (or at least, I don't know how to). To sum it up: when setting or changing values, I do have to go through a bunch of config screens where I would really prefer to have one place in a config file.
Shouldn't Android Studio somehow make use of the values specified in the build.gradle file? If not, the docs don't make it clear that the testOptions.unitTests.all settings can only be used via gradlew invocation.
Skybow,
I feel you have two questions
1. How to load jni lib for androidTest(not for 'test[non instrumented unit tests])
- copy your jni library in corresponding folder [JNI libraries: [app/src/androidTestFLAVORNAMEDebug/jniLibs]
- load your jni library
static {
try {
System.loadLibrary("xyzjni");
} catch (Exception e) {
Logger.error("Exception on loading the jni library : " + e.getMessage());
}
}
2. How to make android studio use your config variables defined for unitTests.
- It would have great if some text file is there which has all configs.
- Or it is part of build.gradle
- I don't have any detail on this.

Error google-play-services_lib\AndroidManifest.xml not found or not a file with Robolectric 2 and Google Play Services (maps V2)

I have an Android application with Google Maps V2 configured with maven in Eclipse. So I have a "mavenised" Google Play Services lib in the worspace, and the app pom has two maven dependencies to google-play-services jar and apklib.
I implemented a dummy test which only checks if a map fragment is not null:
#RunWith(RobolectricTestRunner.class)
public class MapsTest {
private GoogleMap map;
private ElementMapActivity activity;
#Before
public void setUp() throws Exception {
activity = new ElementMapActivity();
activity.onCreate(null);
}
#Test
public void mapExists() {
// Try to obtain the map from the SupportMapFragment.
map = ((SupportMapFragment) activity.getSupportFragmentManager()
.findFragmentById(R.id.elementMap)).getMap();
Assert.assertNotNull(map);
}
}
Note: a similar code is used in the real application activity to show the map, and it runs OK.
I don't implement any custom testrunners.
I run the test with maven: mvn test.
With Robolectric 1.2 the test builds and executes, but the assertNotNull fails, as the map instance is null. The fragment is not correctly recovered.
With Robolectric 2.1.1 the test builds but fails to execute. I get an exception for each test in the project (not only for the one that tests the maps):
WARNING: no system properties value for ro.build.date.utc
java.lang.RuntimeException: .\..\google-play-services_lib\AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml
at org.robolectric.AndroidManifest.validate(AndroidManifest.java:108)
at org.robolectric.AndroidManifest.getResourcePath(AndroidManifest.java:274)
at org.robolectric.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:280)
at org.robolectric.AndroidManifest.getIncludedResourcePaths(AndroidManifest.java:282)
at org.robolectric.RobolectricTestRunner.createAppResourceLoader(RobolectricTestRunner.java:576)
at org.robolectric.RobolectricTestRunner.getAppResourceLoader(RobolectricTestRunner.java:568)
at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:89)
at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:387)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:227)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
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:177)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:120)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:103)
at org.apache.maven.surefire.Surefire.run(Surefire.java:169)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
It seems that Robolectric tries to use the google-play-services library manifest instead of the main application manifest, which is in the default location: the app root folder. The library manifest is in it's own root folder as well.
Am I missing some configuration for the tests? Should I use a custom testrunner? Or is it that Google Maps V2 are not supported with Robolectric 2?
Edit: I can do without the maps tests. The problem is that with Robolectric 2 all the other tests get this error too, just by having the google-play-library dependency, so I can not use Robolectric 2 by now. I would like to know if this is a known bug in order to decide to go back to Robolectric 1 or not. I checked Robolectric bug reports and didn't find anything about this.
I have recently encountered the same problem with ActionBarSherlock when running my Robolectric tests under my Maven build plan.
The problem was not evident when I was completing builds on a Windows machine and only became apparent after I switched my laptop for a OSX power device.
I found that the problem was that the library name "google-play-services_lib" doesn't (exactly) match that of the folder name in the directory structure. In my case, my Eclipse project was called "ActionBarSherlock-4.3.1" whereas the folder itself was called "actionbarsherlock" under the file system.
I recommend that you synchronise the two names (Eclipse project and file system) and re-run your tests. Hope that helps.
Testing Android Apps, with Robolectric 2.1.1, that use google-play-services_lib (Google Maps) produces AndroidManifest.xml not found RuntimeException.
The short answer is here in bold. The long answer is below it.
Look in your project for a file named project.properties
Create a new file called test-project.properties
Override any or all of the android.library.reference.$
For example in my project.properties it had this library reference:
**android.library.reference.1=../../../ADK/adt-bundle-windows-x86_64-20130522/sdk/extras/google/google_play_services/libproject/google-play-services_lib**
I overrode it in the test-project.properties file
android.library.reference.1=res
Put the AndroidManifest.xml from the google-play-services_lib into the res(or any folder in the project) folder of the project you are testing
The long answer:
I was having the same issue and was thinking the problem was the same as described above "google-play-services library manifest instead of the main application manifest" So I removed all my references to the google-place-services_lib and still received the error. I downloaded the 2.1.1 Robolectric code from github and started debugging through it. I found that org.robolectric.AndroidManifest class has a method called getLibraryManifests which calls createLibraryManifests and that calls findLibraries. One of the things it does is loads the project.properties file in your project. In my case my project.properties file at this content:
android.library.reference.1=../../../ADK/adt-bundle-windows-x86_64-20130522/sdk/extras/google/google_play_services/libproject/google-play-services_lib
This was created when I used the Android Tools for the google play services install per Google's documentation. If you comment out that line from project.properties file then the error goes away. A better solution is to leave it and then create your own file called test-project.properties and put in the correct directory for android.library.reference.1 and the AndroidManifest will override the original value.
Here is the relevant code from AndroidManifest.java
protected List<FsFile> findLibraries() {
FsFile baseDir = getBaseDir();
List<FsFile> libraryBaseDirs = new ArrayList<FsFile>();
Properties properties = getProperties(baseDir.join("project.properties"));
// get the project.properties overrides and apply them (if any)
Properties overrideProperties = getProperties(baseDir.join("test-project.properties"));
if (overrideProperties!=null) properties.putAll(overrideProperties);
if (properties != null) {
int libRef = 1;
String lib;
while ((lib = properties.getProperty("android.library.reference." + libRef)) != null) {
FsFile libraryBaseDir = baseDir.join(lib);
libraryBaseDirs.add(libraryBaseDir);
libRef++;
}
}
return libraryBaseDirs;
}

Resource.Layout.filename is returning the wrong layout file

I have a MonoDroid application project (let's call it mainApp). This references app.Screen project, which is a MFA library project. Initially, my activities were in the mainApp project. Everything was working fine. I needed to put some Activities (and resource, drawables, etc) in the app.Screen project.
I have moved all the resources I need to the app.Screen project. It builds fine and in my activities (which are sitting in app.screens) I can access Resource.Layout.filename and even Layout.Id.name.
However, when I run the application, in SetContentView(Resource.Layout.filename) I get the wrong layout file . This causes FindById<Button>() to return null obviously because it does not have these buttons in this layout file.
I found that same Layout file has different Id in my MFA library project than what is in the mainApp project like this:
// In the mainApp project
public partial class Layout
{
// aapt resource value: 0x7f030001
public const int DeliveryScreenLayout = 2130903041;
// aapt resource value: 0x7f03000a
public const int splash_screen_layout = 2130903050;
private Layout()
{
}
}
// in app.screen library project
public partial class Layout
{
// aapt resource value: 0x7f030000
public static int has_hello_layout = 2130903040;
// aapt resource value: 0x7f030001
public static int splash_screen_layout = 2130903041;
private Layout()
{
}
}
I am using VS 2010 with MFA 4.0 and my projects are targeting Android 4.0. I have tried Clean & Build, Removing /Bin and /Obj folder, with no luck.
Any help would be much appreciated.
This appeared to be a bug in MonoDroid, here is the link to the bug in Xamarin bugzilla
This is caused by the Resource.Designer.cs in the MFA library project has a different ID (int) values than what the main project has in its Resource.Designer.cs file.
I have worked out a workaround for it. In my mainApp I manually call mainApp.Resources.UpdateIdValues(); and that would update the Resources id values in the other MFA library projects
Xamarin said that this bug was resolved in 4.6.4. I have not tested this fix though

Unable to run Bitmap sample code for Android

I am trying to run the sample from :
http://developer.android.com/training/displaying-bitmaps/display-bitmap.html
However I encountered lots of errors like:
Description Resource Path Location Type
BuildConfig cannot be resolved to a variable ImageGridFragment.java /ImageGridActivity/src/com/example/android/bitmapfun/ui line 124 Java Problem
Description Resource Path Location Type
SuppressLint cannot be resolved to a type Utils.java /ImageGridActivity/src/com/example/android/bitmapfun/util line 99 Java Problem
I ran thru Google but could get nothing. Adjusted the android build target to 4.0.3 (15) but still no clue. Anyone ran this sample successfully?
Thanks.
Here is my solution:
1.Create a new class:
package com.example.android.bitmapfun;
public class BuildConfig {
public static final boolean DEBUG = true;
}
2.Comment the lines that contain "SuppressLint":
//import android.annotation.SuppressLint;
// #SuppressLint("NewApi")
Android developer tools r17 brings a feature to Eclipse where a class is auto built at build-time, called BuildConfig, which contains a constant that can be used by the app developer to sense whether the build is a dev build or a production build. This feature appears to be in the Eclipse integration support, so when using IntelliJ, this useful feature is not available
In gen folder with R.java there should be BuildConfig.java if your program compiled successfully.
/** Automatically generated file. DO NOT MODIFY */
package com.example.android.bitmapfun;
public final class BuildConfig {
public final static boolean DEBUG = true;
}
Clean your project and try to launch it again.
It worked for me.
For me also it is not running directly import to eclipse. Just i put comments which lines is showing errors then it is working fine for me. May be it is not a right answer but we can see the application functionality by running the code so i did like that.

Android Annotations framework doesn't seem to generate anything

I'm trying to use Android annotations framework because it seems quite powerful. I'm quite stuck to configuring my first project based on it.
I followed every step of the wiki but it doesn't generate any file after a build.
So when I ask for a generated class from the manifest:
<activity android:name=".MyActivity_"
android:label="#string/app_name">
I get an exception:
java.lang.ClassNotFoundException
My activity is exactly the same one as in the wiki:
#EActivity(R.layout.main)
public class MyActivity extends Activity {
#ViewById
EditText myInput;
#ViewById(R.id.myTextView)
TextView textView;
#Click
void myButton() {
String name = myInput.getText().toString();
textView.setText("Hello "+name);
}
}
Any ideas?
EDIT: Just found out a directory ".apt_generated" is made but it's empty after the build.
This seems to be an AndroidAnnotations bug, and should be reported on the dedicated bug tracker, here : http://code.google.com/p/androidannotations/issues/entry . You could also use the AndroidAnnotations mailing list, http://groups.google.com/group/androidannotations
First, I have a few questions :
Which IDE do you use : Eclipse, Netbeans, IntelliJ ? Which version ?
Do you use Maven, Ant, or only your IDE to build the project ?
Your problem may be due to a few things : annotation processing not triggered, a bug in AA, or the files generated in a folder not part of the classpath.
In Eclipse, you may get more information from the "Window > Show View > Error Log" view. If annotation processing is triggered, you should see some messages about AndroidAnnotations.
For other people who are running into this and the leading answer doesn't work, run a build and then search for the file androidannotations.log somewhere in the project. This log file is generated and may hint at what is wrong.
For me, it had a warning message that it could not locate AndroidManifest.xml. Though this seemed like just a warning, it was actually the cause of the error... Not finding my AndroidManifest.xml file resulted in it not generating some of the classes it should have.
Check if you have the xml file. If not, the solution is obvious. If you do have it, the typical reason AA cannot find the file is because it is in a non-standard location -- AA recursively checks the parent directories above where it generates files for this xml file and will fail if it's not there. In my case, my AndroidManifest.xml was located in [project root]/app/src/main which is not a direct ancestor folder so that was the problem.
You can specify where your xml file is in your project build.gradle:
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = ["androidManifestFile": "specify_location_of_AndroidManifest.xml_here"]
}
}
}
}

Categories

Resources