I'm writing an instrumentation test for my app in a separated empty project using UIAutomator and AndroidJUnit4 as runner. It runs well on my device. For testing it on Firebase, it needs the application APK which I provided, and the test APK which I took from C:\Users\user\MyApplication\app\build\outputs\apk\androidTest\debug and when I run the test it fails with this error:"Unable to find instrumentation target package:" am I missing something?
I created another manifest into the androidTest package and the target package is red with "cannot resolve symbol" and nothing changed.
I also changed the targetPackage to the name of the package of the application I'm trying to test, in case that was the problem, and nothing changed.
My androidTest manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.myapplication.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="28"/>
<instrumentation
android:targetPackage="com.example.myapplication"
android:name="androidx.test.runner.AndroidJUnitRunner"
/>
<application
tools:replace="label" android:label="SampleTest"/>
</manifest>
After a lot of research, I found out that gradle changes the target package automatically to the application package name which I'm writing test on.
So I had to move my tests to my application project and generate test apk from it, so it will have the same target package while setting the same signature for both.
Related
I'm using RESTMock for my instrumentation tests, but it only works if I set usesCleartextTraffic to true in my manifest. I only want that to be true for instrumentation tests, though. Is there a way to do that?
I tried creating a new manifest file in the androidTest folder. The tests run but they fail like usesCleartextTraffic is still false.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package">
<application android:usesCleartextTraffic="true" />
</manifest>
I know that RESTMock supports https starting from version 0.3.2, but I'd rather not have to deal with it. I actually followed their guide and ended up with this error from OkHttp3:
java.lang.AssertionError: java.security.NoSuchAlgorithmException: The BC provider no longer provides an implementation for KeyPairGenerator.RSA. Please see https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html for more details.
Any ideas?
EDIT:
I followed this answer and moved this manifest I created to the debug source folder and then it worked. Now the android:usesCleartextTraffic="true" option is only applied to my debug build, which is used by the instrumentation tests, so it works, but it still doesn't feel like the proper solution.
For me the solution is to add a simple AndroidManifest.xml in androidTest/AndroidManifest.xml. This is also mentioned in the answer you reference, but in that case it didn't work because old tooling didn't merge this AndroidManifest.xml.
So, inside androidTest directory, and next to java directory, I have the following:
~/source/my-library/src/androidTest develop*
❯ ls
AndroidManifest.xml java
With this AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage.mylibrary">
<application
android:usesCleartextTraffic="true" />
</manifest>
I'm trying to test using the following directory structure (which was setup by Android Studio):
I can run some tests just fine, and even the AllTests.java runs fine without the AndroidManifest.xml file even being there. The thing is, for one of my new tests, I need the android.permission.INTERNET permission. So, I added the following to the AndroidManifest.xml file located within the androidTest directory:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.core"
android:versionCode="2"
android:versionName="2.0" >
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Unfortunately, this doesn't work. I'm still getting the following error when I run one of my tests:
E/RestAPIRequestTest﹕ Permission denied (missing INTERNET permission?)
I've tried setting the package to be com.example.core.test in my AndroidManifest.xml file (since that is what it shows up as in my Settings->Apps list), but with no joy.
I'm thinking it's not even recognizing the AndroidManifest.xml file, since the version number doesn't show in the Settings for the test app, either.
How can I inject the correct permissions for my test project?
I needed to do something similar. I created a folder named "debug" next to androidTest, which corresponds to the debug variant of the app, and put an AndroidManifest.xml with the permission in that folder. Then the permission works under test since the test app uses the debug variant. It's not ideal because it blurs the line between test and debug, which aren't quite the same thing.
I think what's happening is that the permissions in androidTest/AndroidManifest.xml are going to the test app, not the target app, although it's not 100% clear to me if there are actually two different APKs or what.
In older versions of Android Studio and the Android Gradle plugin the androidTest/AndroidManifest.xml file was ignored. This was documented at the tools.android.com site at the time.
With the Android Studio 1.0+ and Android Gradle 1.0+ plugin launch in December 2014 the AndroidManifest.xml file should now be merged with the normal main/AndroidManifest.xml files (in addition to the debug and release manifest files if they exist). More details regarding the manifest merging rules are here.
If you still run into issues or are just debugging manifest related testing issues try this
(Adapt this slightly for Windows):
Drop to a terminal
change to to your project directory
cd MyApplication
Build your project, assuming 'debug' is the build type you want to test with, but you could also be testing with 'release' or a build script defined one.
./gradlew assembleDebugTest
Then inspect your test APK manifest:
ls app/build/intermediates/manifests/test/debug/AndroidManifest.xml
View your application APK manifest:
ls app/build/intermediates/manifests/full/debug/AndroidManifest.xml
A merge output log can be found detailing the manifest merging process:
ls app/build/outputs/apk/manifest-merger-debug-report.txt
A couple of extra notes:
An instrumentation element is automatically added to your test APK's AndroidManifest.xml so you should only be adding extra activities, permissions, etc that your test APK needs.
If testing with mock locations your application APK will need the ACCESS_MOCK_LOCATION permission. You can add the permission to your debug/AndroidManifest.xml file or you can define that the test APK and the application APK should use the same userId when deployed (sharedUserId attribute in your AndroidManifest.xml).
This is a known problem.
Currently (AGP <= 3.4.X) is not supporting AndroidManifest test merging.
This is reported here: https://issuetracker.google.com/issues/127986458
and here there is the issue created by one of the Roboelectric maintainers.
The workaround as described here its near the same proposed by user3286293 and currently is the only way to have the manifest merged for testing purposes.
Hope to see a fix for AGP 3.5 or 3.6
As specified here, during instrumented tests, there are generated two .apk files. If you take a look, the smaller one it's most probably the one named app-debug-androidTest-unaligned.apk and it actually does include the provided permissions.
Inspecting the file with aapt d permissions <apk_file_path>.apk can be useful to see a list of all of them.
Now, there might be an issue with the context itself where the permission is requested. I had a similar problem, trying to write some screenshots on SD card (thus needing the WRITE_EXTERNAL_STORAGE permission).
This answer helped me to fix the problem, although I cannot fully understand why it's necessary.
In few words, you'll need to declare the same android:sharedUserId in both manifests, in order to merge the permissions when both apks are installed on the same device - that happens when tests are running.
This helped me to separate permissions needed just for testing from the one in production.
You need to define that in build.gradle file:
android {
sourceSets {
androidTest.manifest.srcFile "src/androidTest/AndroidManifest.xml"
}
}
One solution would be like build main apk and test apk in single run.
Example: ./gradlew clean :main:assembleDebug :main:assembleDebugAndroidTest.
This will create a new instrumented main application which has all extra permissions required for test application.
I have a seperate Test Project in Eclipse that has been running successfully for a while in both command line and Eclipse. While using Jenkins to run my tests, I've run into the issue where the standard InstrumentationTestRunner does not output in a Jenkins supported xml format. I've read on the internet to use a custom InstrumentationTestRunner. This works in the command line using ADB, but fails in Eclipse when running as Android Test Case.
I've downloaded a custom instrumentation test runner (com.neenbedankt.android.test) and added it to the AndroidManifest like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testedapplication.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<instrumentation
android:name="com.neenbedankt.android.test.InstrumentationTestRunner"
android:targetPackage="com.testedapplication" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<uses-library android:name="android.test.runner" />
</application>
</manifest>
Here is the error that I get in Eclipse:
[Test Project] is not configured correctly for running tests:
A targetPackage attribute for instrumentation android.test.InstrumentationTestRunner in its AndroidManifest.xml could not be found!
You can see that i've set the targetPackage there, so I'm not sure what else I can do?
Add both instrumentation in your AndroidManifest.xml.
<instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.myapp" />
<instrumentation
android:name=".MyRunner"
android:targetPackage="com.example.myapp" />
Then go to Package explorer --> $(Your Test Prject$) --> Run As --> Run configurations --> Android JUnit Test --> $(Your Test Project) --> Instrumentation Runner and select your runner there.
To make eclipse select custom runner by default when doing run as/android junit - simply switch the order in manifest file. Make sure yours is first
<instrumentation
android:name="*.Custom.TestRunner"
android:targetPackage="com.*" />
<instrumentation
android:name="*.InstrumentationTestRunner"
android:targetPackage="com.*" />
Since I can't see your whole project setting, here's a couple check list I'd try.
Do you have a separate Test Project in Eclipse? Is the above instrumentation block in your source project's manifest file or in the test project's manifest file?
Did you include the <uses-library android:name="android.test.runner" /> block?
Did you put the test project's instrumentation block outside the <application> block and the <uses-library> block inside the test project's application block?
Did you try creating a Test Project in Eclipse through the "New Project -> Android Test Project", and just changing the instrumentation class there after adding the source code? If you don't change the instrumentation class does it work?
Are you running the test in Eclipse by doing "Run As -> Android JUnit test"?
If you already did all that, I think pasting your whole AndroidManifest file would help clarify a bit, and whether or not you have 2 separate projects or not.
Ah so far I've been able to get it to work by having both the android.test.InstrumentationRunner runner AND the customer test runner described in the manifest file. I seems that running from Eclipse will use the android.test.InstrumentationRunner and running from the command line will use the custom test runner if its setup in the ant script.
I have developed two android apps...when i install them on my phone to test them.. they overwrite each other. I do not want this to happen. The intent is to have both installed on the phone as separate apps.. how do i fix this? I developed them with eclipse.
I had the same problem despite the fact that package names were different between both APKs.
At the end I had to modify a GRADLE file:
\app\build.gradle
the following line:
applicationId "name.to.change"
In Android Studio 3 you will find this configuration in:
I had the same issue, turned out that I had copied one project to another to save time, and the package setting in the Manifest tag inside the AndroidManifest.xml file was the same for both apps.
Once I changed this and resolved any imports errors, the apps stopped overwriting one another on the phone.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.yyy"
android:versionCode="1"
android:versionName="1.0" >
Do the apps share the same namespace? Verify that they have their own packages in Eclipse.
also share the same user id, modify it in the manifest.
I'm getting this error when trying to run unit tests from Eclipse with an Android Project. The list of Instrumentation Test Runners is empty in the Android preferences.
[2009-06-17 23:57:51 - MyApp] ERROR:
Application does not specify a
android.test.InstrumentationTestRunner
instrumentation or does not declare
uses-library android.test.runner
It's also annoyingly decided that because I tried to run a unit test once, that's what I always want to do.
You're probably missing the uses-library and instrumentation nodes in your AndroidManifest.xml:
<manifest ...>
<application ...>
<!-- ... -->
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="your.package"
android:label="your tests label" />
</manifest>
In the Run Configuration you may have Android JUnit Test, if there are any new launch configuration entries inside this, you delete it and then run your application it will run.
NOTE - This is likely to be the solution if you tried to run the test case before adding the correct lines to the manifest as described in the answer from Josef. If you have done this, delete the configuration (which will be complaining that no instrumentation test runner has been specified in its header) and then run it as an Android Junit Test again and it will create a valid configuration picking up the correct stuff that you have added to the manifest (see Josef's answer for this).
One thing I noticed in this discussion that might be tripping some people up is that you need to make sure the "instrumentation" element in your manifest is a child of "manifest" and not of "application." (The examples here are correct, but this easy to mix up.)
http://developer.android.com/guide/topics/manifest/instrumentation-element.html
If you put your instrumentation stuff inside application, it won't be picked up, and your choices in the Eclipse ADT plugin for instrumentation runner may be blank. (But no error is thrown or shown, etc.)
Just do a right click on your test class from eclipse IDE and click on "Run As". After this select "run Configuration" which will launch a Confiuration Window in eclipse and you need to click on the radio button next to the "Instrumentation Runner" and select the configured Instrumentation Runner from the drop down. Now click on apply and then click on Run .
I think this will solve your problem.
Thanks,
Smruti
It's not in your code, it's just eclipse is a little buggy. In your run configurations it could be trying to run a jUnit test, but select Run Application and that error will go away.
Besides ensuring that the below items are declared in the manifest of your test app, check in the Run Configuration that the "Instrumentation runner" field is set to
"com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner".
This what I ran into when figuring out why I test wouldn't run.
Manifest:
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="your.package"
android:label="your tests label" />
and...
<uses-library android:name="android.test.runner" />
The problem is when you created the project, you would have had a AVD, so these configuration would be missing. My suggested way is first create the AVD and then create the android project :).
If you would have already created the project and if does not have much code you have written I would suggest to delete it and create a new one.