Question

I feel there is much confusion around how to use JUnit to test an Android Library project.
I will describe all the errors I encountered so far(for the sake of other programmers trying to do the same) and at the end I will specify my last and current problem.

  1. Since a Library is not an Application, it does not produce an .apk file in the bin directory, just a .jar file, and you need an .apk to use Android JUnit testing

  2. So you definitely need to create a new project for the tests, follow this guide
    Note: Even though the guide tells you to use TestCase and its derived class AndroidTestCase, several posts seem to point that TestCase is used only for JUnit3 tests, JUnit4 tests do not extend any class.
    I don't know what I am supposed to use when you want to run a test that uses the Android API, if you want to use it under JUnit4, I have not reached that point yet.

  3. For tests that do not use the Android API, use JUnit4 style class. If you follow only the guides your test will fail when you run it "Invalid layout of ... at value". This is because the run configuration includes Android in its classpath. Go to the JUnit test run configuration for the test (Right click on the test->Properties->Run/Debug Settings->Edit) and remove Android from classPath boostrap entries.
    EDIT
    When you run the test for the first time, in Eclipse, you have to choose which launcher to use "Eclipse JUnit Launcher" or "Android JUnit Test Launcher" if you choose the Android launcher, no need to remove the bootstrap entry.

  4. From now on I had no success. For tests that use the Android API, extend AndroidTestCase. These tests will take longer to launch, they need an emulator running, even if you are not testing the application itself but a utility class with no interface to the user.

  5. To run Android UNIT case test the launcher looks for the target package APK file, which a Library target project does NOT have.

  6. The target package was automatically inserted in the manifest of your test project when you followed the guide in #2. The manifest for the test project should look like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.Common.lib.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="14" />

    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.Common.lib" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <uses-library android:name="android.test.runner" />
    </application>

</manifest>

Here the target package is the Library I am trying to test. A solution is given in this post It is to use the test project as application which has an APK. So now I changed the target package from

        android:targetPackage="com.Common.lib" />

to

        android:targetPackage="com.Common.lib.test" />

But still the launcher looks for the Library APK, even though I added the Library as reference in the test project, see the logcat below (Note the CommonLibTest.apk is loaded succesfully):

[2014-02-24 16:17:50 - CommonLibTest] Dx 
trouble writing output: already prepared
[2014-02-24 16:17:51 - CommonLibTest] ------------------------------
[2014-02-24 16:17:51 - CommonLibTest] Android Launch!
[2014-02-24 16:17:51 - CommonLibTest] adb is running normally.
[2014-02-24 16:17:51 - CommonLibTest] Performing android.test.InstrumentationTestRunner JUnit launch
[2014-02-24 16:17:51 - CommonLibTest] Automatic Target Mode: using existing emulator 'emulator-5554' running compatible AVD 'Phone-x86-jb'
[2014-02-24 16:17:51 - CommonLibTest] Uploading CommonLibTest.apk onto device 'emulator-5554'
[2014-02-24 16:17:52 - CommonLibTest] Installing CommonLibTest.apk...
[2014-02-24 16:17:52 - CommonLibTest] Success!
[2014-02-24 16:17:52 - CommonLib] Could not find CommonLib.apk!
[2014-02-24 16:17:52 - CommonLibTest] Launching instrumentation android.test.InstrumentationTestRunner on emulator-5554
[2014-02-24 16:17:53 - CommonLibTest] Test run failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException'

This is as far as I got.
If want to believe someone already has tested a Library project succesfully with JUnit and has the solution to my problem.

Was it helpful?

Solution

To complete the tale, I solved the last obstacle and the test now runs.
Lets start with the bottom line:

AndroidTestCase requires JUnit3 tests. The annotation @Test fails the test with ClassNotFound for the org.junit.Test class.

Once I commented out all @Test annotations the test started to run. One more guideline: test names should start with the prefix "test" for JUnit3

Strangely the JUnit4 annotation @BeforeClass did not trigger a failure.

Conclusion:
JUnit4 test styles is only good for pure Java Unit tests. For Android Unit tests use JUnit3 style, since JUnit4 is backwards compatible it will compile fine.
Please note that this post refers only to Unit testing, I haven't got to the stage where I need to test the Android application itself with functional tests.

OTHER TIPS

Some findings:

The apk is "needed" since the wizard adds the project-under-test as a project dependency (see properties in the test-project). During testing the framework needs to upload that project to the device somehow, hence the need for an apk. Since there is no apk there will be a warning message. Removing this dependency silences the warning. Note, since no apk is uploaded no library is uploaded to the device either, giving NoClassDefFound exceptions later on in the tests.

In my case, similar to the original post, removing the project-under-test dependency from the test-project and adding all needed jars manually, both built and required, from the-project-under-test solved it. I didn't needed the extra "test application" dependent on the project-under-test some posts elsewere suggests. Maybe this is a convinient solution if one otherwise have a lot of jars to add manually.

Both keeping the project dependency and manually adding the required jars led to problems resolving classes yeilding in NoClassDefFound exceptions. I don't now why.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top