Common utility classes for Android testing projects - android

I keep tests for my Android projects in four separate projects: unit and functional tests separately, and tests that require native Android environment (Activity/Service tests, functional Robotium tests) separated from tests that I suppose can safely be run in artificial environment (Robolectric + some acceptance tests for non-strictly-Android libraries). However, I need to share some utility classes between some of the projects (mostly I mean the Android Test Kit ones, but it would be nice if I could have them under Robolectric too).
How should I go about this problem? Should I create an Android library or a simple JAR with the stub android.jar as a dependency? I've tried both solutions but got strange errors like NoClassDefFoundError for classes from the support library or IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation for classes from the tested project.

This approach, "a simple JAR with the stub android.jar as a dependency", seems simpler. In your test project, besides including this JAR as a dependency, you need to check the box for this JAR in the "Order and Export" tab of "Java Build Path" in the project property if you are using Eclipse.

Related

Accessing R.java using java test in BUCK

While migrating our build tool to Buck, we stumbled upon the following issues for the unit tests in Android:
Our tests for the view model need to access R.java for asserting the right resources are referenced.
We used the java_test rule but it seems R.java is not found. There is a robolectric_test which builds the .apk but we just want the R.java file in the classpath for the unit tests.
Is there a reason there is no android_test rule.
Any plans of doing so?
We explored the code and looked that we need to see the AndroidLibraryGraphEnhancer and build the Android resources.
Any recommendations?
No plans for adding such rule because it's not clear what it supposed to do and why robolectric_test is not enough.
Buck doesn't build an apk for Robolectric tests.
You really don't want to use java_test to test Android code because Android SDK and Java SDK are different. You have to test Android code with robolectric_test because it uses Android SDK.

Android unit testing - how to run tests in same project as application?

In the Android LunarLander sample project, the unit tests are included right in the project, in a (non-source) folder called 'tests'. This is in line with the SDK testing guide which recommends this layout as opposed to creating tests in a separate project. However, I have no idea how I can actually run these tests.
I can't create an Android Junit Test run configuration:
if I try to 'run all test in project or package' it complains that manifest file doesn't contain instrumentation info - clearly it's using the top-level manifest file instead of the tests manifest file.
if I try to 'run a single test', I can't find any because tests isn't a source folder, and if I set it as a source folder, errors pop up, since it assumes the test class should be in a package starting with 'tests.src'.
It's starting to seem to me that this sample is broken... I hope I am wrong, since I'd rather embed tests into my project and be able to run them easily (instead of creating a separate test project that links to project for application under test). Does anybody know how I can run these tests? Thanks...
Google recommend a single all-in-one directory because it makes your files easy maintainable in many situation, for instance when dealing with source control.
It doesn't matter where the test project is located int the file system, however, you must import it into your Eclipse's workspace, same as what you did for the LunarLander project:
If everything goes well, your Package Explorer should look something like this:
In my Android 4.2 samples, things are not going well, it seems that the source code of LunarLander test project is not up-to-date:
it doesn't come with project.properties file.
it uses same package name as LunarLander project, resulting Eclipse to be fooled when importing package/class from the referenced LunarLander project.
it doesn't automatically add the LunarLander project to test project's classpath, resulting imported package/class from the referenced LunarLander project is invisible.
Once you resolve all issues, you should able to run/debug Android JUnit Test from test project.

Android Junit test - Mockito class not found exception

I'm attempting to build a unit test on Android which utilizes the mockito-all-1.8.5.jar file from mockito.org. I added the jar file to my project using project > properties > project build path > add external jar. This has always worked for me on non-Android java projects.
However, when I run the unit test, I get the following class not found exception:
java.lang.ClassNotFoundException: org.mockito.runners.VerboseMockitoJUnitRunner
Above it is the following message:
Cannot load class. Make sure it is in your apk. Class name: 'org.mockito.runners.VerboseMockitoJUnitRunner'. Message: org.mockito.runners.VerboseMockitoJUnitRunner
I checked the jar and the class is there.
I also tried adding according to this link:
How to use and package a JAR file with my Android app?
But, still no luck. How can I get this class to be found?
Edit: I'm thinking there is a problem with whatever libraries Mockitto depends on - they may not be compatible with the Dalvik jvm. See this post:
http://daverog.wordpress.com/2009/12/14/why-android-isnt-ready-for-tdd-and-how-i-tried-anyway/
1) Import a mocking framework (e.g. mockito) into the project as an additional dependency.
Any imported jars containing class files not compiled to Dalvik bytecode (most) will not work. Attempting to compile the source along with your project will not work either because most libraries will make extensive use of parts of the Java language not compatible with Dalvik: it uses its own library built on a subset of the Apache Harmony Java implementation.
If you are executing inside the Dalvik JVM you won't be able to use Mockito.
If you are running your unit tests on your desktop JVM however (with a testing framework like Robolectric for example) then you are good to go. I am combining the two on my Android projects at present, to good effect.

How to test an Android Library Project

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?
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."
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.
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.
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.)
Create a new Android Library project by checking the "Is Library" checkbox during creation. (for example an Android project named "RemingtonAndroidTools").
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".)
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.
Go the Library tab of Java Build Path for the Android Test App project ("RemingtonAndroidToolsTestApp" in this example).
Add the jar file ("RemingtonAndroidTools.jar" in this example) of the Android Library Project ("RemingtonAndroidTools" in this example) via the "Add Jars..." button.
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.
Go the Library tab of Java Build Path for the Android Library Tester project ("RemingtonAndroidToolsTester" in this example).
Add the jar file ("RemingtonAndroidTools.jar" in this example) of the Android Library Project ("RemingtonAndroidTools" in this example) via the "Add Jars..." button.
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.
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.
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:
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)
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.

Self-contained test library project cannot find the library classes

According to this SDK guide, unit-testing a Library project can be achieved by creating a standard application project, reference the Library project and then instrument the application for unit testing.
However, when I do this and launch the test application I get the message
No tests found with test runner 'JUnit 3'.
I'm using Eclipse and the Android ADT plugin, all latest versions.
Note: the projects compile just fine. The test project also installs fine to the emulator. But in the console I can see that it looks for <library>.apk, which of course doesn't exist since I'm compiling this as a library into the test project.
Anyone got this to work? And if so, what is the trickery here?
Update: after discovering and fixing a problem, which was actually including the test classes (!), the test runner now can find all tests. But, all the tests fail with the following exceptions:
java.lang.NoClassDefFoundError: <nameOfClassInLibraryProject>
nameOfClassInLibraryProject are classes defined in the library project. These classes should be compiled into the test project, and indeed, everything compiles just fine. But when running the test project, the runtime doesn't seem to find the library classes.
After much fiddling and wasted time in Eclipse I have managed to get Android Library projects to work.
According to the Working with Library Projects article:
Instead, you must compile the library indirectly, by referencing the library from a dependent application's build path, then building that application.
The problem was that I interpreted this to mean that the library project should be added to the Projects tab in Java Build Path. Doing this makes the test project compile since the library code is obviously available to the compiler. But since the library is not compiled into a .jar or .apk in itself, the library classes are never deployed to the device.
The solution is to not add the library project to Projects, rather on the Source tab, add the library /src folder using the Link Source... button. And yes, it is the library src folder, not the library project root, that must be linked into the test project.

Categories

Resources