100

I am writing an Android Library Project basing on Android Bitmap class (call it AndroindLib) which contains only utility class (no activity). I tried to test it using Android JUnit, but it keeps complaining that can't find the AnroidLib.apk

What's the right way to Unit test Android Library Project?

Janusz
  • 187,060
  • 113
  • 301
  • 369
Lily
  • 5,872
  • 19
  • 56
  • 75
  • 1
    Or (**shameless plug alert**) you could use a project I created: Android Library Test Harness (what I like to call "Alt H"). It's available as a git repo: https://gitorious.org/alth The project is still in development and the documentation is a little sparse so feel free to hit me up if you have any questions. – i41 Sep 27 '13 at 15:42

5 Answers5

78

Quoting the documentation:

"There are two recommended ways of setting up testing on code and resources in a library project:

  • You can set up a test project that instruments an application project that depends on the library project. You can then add tests to the project for library-specific features.

  • You can set up a standard application project that depends on the library and put the instrumentation in that project. This lets you create a self-contained project that contains both the tests/instrumentations and the code to test."

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 27
    so basically all you have to do is add the library to your test project and test the test project. – njzk2 Aug 23 '11 at 14:01
  • The link is no longer valid, any chance you can point us to the current one? – Abdullah Jibaly Nov 30 '11 at 19:04
  • Looks like: http://developer.android.com/guide/developing/projects/index.html#testing – Abdullah Jibaly Nov 30 '11 at 19:06
  • @AbdullahJibaly: Thanks -- I fixed the answer – CommonsWare Nov 30 '11 at 19:10
  • 4
    Not sure if anyone else has had success with these recommendations but I haven't. Tried the second solution first and when I try to run in Eclipse I get the following: does not specify a android.test.InstrumentationTestRunner instrumentation or does not declare uses-library android.test.runner in its AndroidManifest.xml. This is despite the fact that I added both the instrumentation and uses-library elements to my Manifest. – Bellinghammer Dec 23 '11 at 03:27
  • When I try the first recommendation of creating a simple app project that includes my library and then creating a test project for the simple app project my tests cannot resolve the types from the library project namespaces. *sigh* – Bellinghammer Dec 23 '11 at 03:31
  • 2
    Got the second (and preferred way working). It's very important that you get the uses-library and instrumentation elements in the correct location in your manifest. The instrumentation element is a child of the root manifest element and the uses-library element is a child of the application element. I was putting the uses-library under the manifest element and ending up with the error message above when trying to run the tests. – Bellinghammer Dec 23 '11 at 03:57
  • There is an important requirement for the 2nd scenario to work fine. Both the library and the test project should share same package name. It will still run, but you can stuck into subtle file permission problems as I did. – WindRider Sep 16 '13 at 11:20
  • @CommonsWare looks like the link is obsolete. – Prudhvi Jan 26 '19 at 00:10
  • @Prudhvi: It's an 8.5-year-old answer on a topic (Eclipse library projects) that no longer exists. – CommonsWare Jan 26 '19 at 00:13
  • [Archive of blog post: android-library-project-with-tests-step-by-step](https://web.archive.org/web/20110225105035/http://www.paulbutcher.com/2010/09/android-library-project-with-tests-step-by-step/) helps describe the process needed to implement the second suggestion in CommonsWare's answer – yuzisee Jan 19 '11 at 02:58
17

In your test project simply change the package name so that it's the same as your library's package. For example, you have a library whose package is "com.example.lib". Create a test project targeting your library. In the manifest file you'll see package="com.example.lib.test", and targetPackage="com.example.lib". Just change the package from "com.example.lib.test" to "com.example.lib" (targetPackage leave as is).

Also, make sure that the library is referenced to your test project NOT in Java build path, but as a usual Android library : in Eclipse it must be shown as library in Project->Properties->Android tab, but not in Project->Properties->Java Build Path tab.

Then run you tests.

n611x007
  • 8,952
  • 8
  • 59
  • 102
alexaschka
  • 433
  • 6
  • 14
  • Your ideas made sense to me, so that the test targetted itself (as the app) and the app is linked with the library....but I couldn't get it to work via ant build nor IntelliJ....as the .apk (expected for the app under test) didn't exist when it tried to install it, as it is being compiled to "test/bin/.-debug.apk" – Andrew Mackenzie Nov 24 '13 at 16:55
  • I got it to work by just changing the package name of test project in it's manifest (and the package under test - which should be the same) to NOT coincide with the package name of the library project, plus removing the reference to the target test project in the ant.properties file. – Andrew Mackenzie Nov 24 '13 at 17:44
  • 1
    I think this is a better answer than the accepted one, that just echos the documentation - IMHO. – Andrew Mackenzie Nov 24 '13 at 17:49
5

Per the documentation:

Testing a library module is the same as testing an app. The main difference is that the library and its dependencies are automatically included as dependencies of the test APK. This means that the test APK includes not only its own code, but also the library's AAR and all its dependencies. Because there is no separate "app under test," the androidTest task installs (and uninstalls) only the test APK. When merging multiple manifest files, Gradle follows the default priority order and merges the library's manifest into the test APK's main manifest.

Avilio
  • 581
  • 6
  • 5
1

NOTE: This solution is based on using Eclipse Indigo (3.8.2) and might have to be implemented slightly differently for another IDE although the basic principles will be the same.

I had similar issues and I found that do the following always works:

(NOTE: These instructions are for building a new project group from scratch. If you have already built parts of the project group, then you may have to modify your projects so that they connect in the same way.)

  1. Create a new Android Library project by checking the "Is Library" checkbox during creation. (for example an Android project named "RemingtonAndroidTools").
  2. Build the Android Library project and verify that it created a jar file in the bin folder. (for example a jar file named "RemingtonAndroidTools.jar".)
  3. Create an empty Android Project for testing the Android app that will serve as an Android Test App. (For example an Android project named "RemingtonAndroidToolsTestApp"). You will not need to modify the source code or resources of the Android Test App project unless you have something that must be added for testing. Many things can be tested without any modifications to the Android Test App Project. The Android Test App project is a bridge between your Android Library project and the Android Junit project that makes testing of the Android Library project via Android Junit possible.
  4. Go the Library tab of Java Build Path for the Android Test App project ("RemingtonAndroidToolsTestApp" in this example).
  5. Add the jar file ("RemingtonAndroidTools.jar" in this example) of the Android Library Project ("RemingtonAndroidTools" in this example) via the "Add Jars..." button.
  6. Create a new Android Test project (for example "RemingtonAndroidToolsTester") that will serve as an Android Library Tester and select the Android Test App project ("RemingtonAndroidToolsTestApp" in this example) as the target.
  7. Go the Library tab of Java Build Path for the Android Library Tester project ("RemingtonAndroidToolsTester" in this example).
  8. Add the jar file ("RemingtonAndroidTools.jar" in this example) of the Android Library Project ("RemingtonAndroidTools" in this example) via the "Add Jars..." button.
  9. Find the last folder of your Android package in the Android Library Tester project ("danny.remington.remington_android_tools_test_app.test" for example) and add a test class ("MainActivityTest" for example) that inherits from ActivityInstrumentationTestCase2.
  10. Edit the test class ("TestActivityTest" in this example) to use the activity (for example "TestActivity") of the Android Test App ("RemingtonAndroidToolsTestApp" in this example) as the parameter for ActivityInstrumentationTestCase2.
  11. Edit the test class ("TestActivityTest" in this example) and create a default constructor that makes a call to super(Class) and passing in the class of the Android Test App ("TestActivity.class" for example).

You should end up with three projects (Android Library, Android Test App, Android Library Tester) that look similar to this:

enter image description here

enter image description here

enter image description here

You should end up with a class for testing your Android Library that looks similar to this:

package danny.remington.remington_android_tools_test_app.test;

import android.test.ActivityInstrumentationTestCase2;
import danny.remington.remington_android_tools_test_app.TestActivity;

/**
 * 
 */
public class TestActivityTest extends
      ActivityInstrumentationTestCase2<TestActivity> {

   public TestActivityTest() {
      super(TestActivity.class);
   }

}

You can then add any test that you want. You will not need to reference the Android Test App ("RemingtonAndroidToolsTestApp" in this example) further to run your tests unless they require access to an Android specific component (like the Assets folder, for example). If you need to access any Android specific components you can do so by modifying the Android Test App ("RemingtonAndroidToolsTestApp" in this example) and then referencing it via the instrumentation provided by the standard Android Junit API. (You can read more about that here: http://developer.android.com/tools/testing/testing_android.html)

Danny Remington - OMS
  • 5,244
  • 4
  • 32
  • 21
0

If your ulitiy classes do not depend on any android specific code, you can just use standard JUnit unit tests. No need to use the Android versions.

Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82