I've written a real-time subsystem for Android that I'd like to test on the desktop. I would like to run tests via a command line tool of my creation. The subsystem depends on Android as follows:
android.os.Looper
android.os.Handler (including Handler.Callback)
android.os.Message
android.util.Log
I need to stub these classes. Robolectric stubs these classes but apparently doesn't allow for custom instances of Looper. Unless someone can point me to functional stubs, I plan to write them myself. I'd rather avoid the complexity of writing a test harness for a full Android emulator.
How do I get Android Studio to use my stubs for these classes in my tool build? I don't want to modify the subsystem to dynamically receive the classes it should use, out of fear of limiting optimization or making code unnecessarily messy. (But I am open to wrapping android.util.Log.)
Thanks for your help!
Related
I am trying to build an application that runs under JavaSE and Android. Most of the code is the same between the two, but there are some specific functions that need to be separated. I use Eclipse. So I decided to put the shared code in a separate project, and then build one more project for Android and one for Java, which reference the shared project. I put all Java and Android specific functions in one class residing in the Java and Android specific projects. These classes are called UtilsJ (for Java) and UtilsA (for Android). The code in the shared project uses a factory to determine at runtime which version it needs to pick, and then calls the class loader to load the right class. Essentially: if property java.vm.name equals Dalvik, load UtilsA, else load UtilsJ (and of course cast to the Utils interface before returning).
My question is simply if this is a good idea or is something going to eventually break? I've never used class loader before. Any other suggestions how to implement this sharing would also be appreciated.
Generating an interface implementation dynamically is certainly a valid technique. For instance, having a data access interface that has multiple implementations; one each for flat files, MySQL and WebDAV. The program can pick an implementation at run time based on system/platform properties.
But this feels different. If I saw that I had a Java app and an Android app that had a lot of common code, my goal would be to create an Eclipse project that generates a jar file that I could just drop into the libraries of both projects. In that case, the jar file wouldn't contain any code that was incompatible with one platform or the other. So there wouldn't be any reason to have a platform-specific implementation.
Let's take your example some code reading an initialization file. If it's common code, you have an input parameter which is a file. On Android, maybe it's "/data/data/com.whatever.blahblahblah" and on Java you're getting the "user.dir" system parameter for the top level directories. But one way or another, it's a File, and you hand it to your common setup method. That's okay. But if your initialization file read code e.g. needs a Context to get a Resource to read the file for Android, then it's not common code. And it doesn't belong in a library jar for a JVM-hosted app.
So I think that in your case the platform-specific implementation classes are overkill. If it's common code, it's the same code — period.
Let's talk about another example in your comment. If you are using desktop Java, then you are probably using Swing or AWT, so you still have the same issue of running some network task off the UI thread, notifying when it completes, maybe even updating some progress indicator UI while it's processing. Same function, same operation, but the code is so different that I can't see how having it in the same library next to an AsyncTask version could be of any benefit.
And testing might get tricky. Obviously JUnit will work for everything, but some tests would need to run on a device or emulator.
I stated that it was a valid technique, and of course you may have other compelling reasons to choose the multi-platform option. You asked the question; is anything going to break? My answer is: Probably not, but why risk dealing with some heartburn down the road? Speaking for myself, I wouldn't do it. If I had to support multiple MVC apps, my common library would have nothing but M.
I have a question about technology or methodology out there that I can use to test my code fast & simply. Recently I came across the difficulty & frustration regarding to testing my code when I was working on an android project. Everytime when i wanted to test my code, i had to re-compile whole project again and wait for emulator to re-install application which at least takes 40~50 seconds just to check a bit of code working fine. Are there any way that I can compile or test just a small portion of code / 1 ~ 2 methods working without having to re-compile whole project every time? Also which one is the latest and most widely used among the industries?
=====================================
Additional question. I've done some research on JUnit testing of java but is JUnit what i'm looking for? or is it different kind of testing technology
you can make a search about Robotium. it provides you to do blackbox testing.
http://testdroid.com/tech/54/automated-ui-testing-android-applications-robotium
Maybe Robolectric is what You are looking for. You can use JUnit to test only java code that doesn't use methods from android sdk.
have you considered using AndroidTestCase? JUnit can only be used to non-android specific function, but this does the job for your Android-specific code.
There is a very detailed account for android testing available at:
http://developer.android.com/tools/testing/testing_android.html
This includes basic as well as activity testing and is built on top of JUnit.
For people that don't want to use Roboticum and such, but just stick with Eclipse built-in JUnit testing, this is what I would recommend:
Have three projects:
AndroidProject
AndroidProject.test
AndroidProject.test.android
In your AndroidProject.test project you only test Models, Controllers and such which exclusively uses Java-libraries. So no Android Logcats, Toasts, or things like Patterns.WEB_URL.matcher(url).matches()) [android.util.Patterns] (which validates a String URL).
In your AndroidProject.test.android project you test the Activities, Services, Model-classes that use Android libraries like the Pattern-validation mentioned above, etc.
To be able to use Eclipse Run As -> JUnit Test for your JUnit test project you have to do some set-up however, like removing the Android API from each individual Test class, using the junit.framework.Assert and org.junit.Test imports, etc. For a full step-by-step guide to reproduce what I have done to make it work, I refer to my own Stackoverflow-post that I've made:
JUnit Test Android classes without being forced to start the (slow) Emulator.
I'm trying to let a user "make his own service". most direct method I could think of is creating an empty service and letting him "fill it". he will write his own code and I'll compile it along with my project.
(If it's not understood, the code should be injected to the service programmaticaly and not manually).
There are limitations that require it's done this way.
Here's a post about programmatically compiling and running Java code,
How do I programmatically compile and instantiate a Java class?
This is pretty ugly though. You might want to look at having the use supply a script in a higher level language, and executing it via the android scripting environment,
http://google-opensource.blogspot.com/2009/06/introducing-android-scripting.html
There's also the SL4a project,
http://code.google.com/p/android-scripting/
How can I execute a block of code in an android project without having to launch the emulator.
I don't want to deal with the android lifcycle -> I want to test the logic of my app ONLY.
What I have in mind is to create another java project and define dependencies so that I can access the classes that are in my android project.
I would like to launch a kind of Main() method to bypass the emulator... Is it possible?
Thanks!
Look into unit testing. Fits your problem almost perfectly.
Not exactly for a block of code but for methods.
There are special launchers such as JUnit that makes the test-running smother and much more fun. You get green and red lights for every test, great satisfaction to get all green.
JUnit is fairly easy to get started with and is well integrated into eclipse.
I'm trying to develop an external library (not sure if that's the right term) to provide prepackaged functionality in Android projects. Working in Eclipse, I've added the appropriate android.jar file to the build path, and everything is happy both while editing and upon compilation.
However, when I use Android's Handler and Message classes (android.os.Handler, android.os.Message) for inter-thread communication, I get exceptions unless I'm running within an Android app, on the emulator or a device. I can no longer test my library in a "standalone" way without having to go through a running Android target.
Is there any way for me to include these two Android classes and still be able to test my library standalone? Do I need to have the Android source available? Or would it require some sort of conditional compilation hand-waving?
Is there any way for me to include
these two Android classes and still be
able to test my library standalone?
Not readily, by any means I can think of.
Do I need to have the Android source
available?
I don't know where else you would get the implementation from. But, more importantly, those things are not designed to work in isolation outside of the OS, any more than you could just grab a Cocoa class or two and pull them into your Objective-C library and expect them to run on a Windows box.
Off the cuff, knowing nothing about what you're building, I would make whatever dependency you are introducing on Handler and Message be more pluggable. Test outside of Android using a pure-Java implementation, perhaps even just some mocks. Test inside of Android using the real implementation.
You could try the lib Robolectric, that implements the android API so you would be able to create JUnit tests for some isolated code you have:
http://robolectric.org/