Testing Strategy for Web Services based Android app - android

I have a web services based app i.e. each activity calls a particular web service and populate data into view. I haven't done any testing yet but I was in the process of switching to Volley and thought I might add some testing too.
I was wondering what testing strategies should be for such apps. I'm playing around with the gradle-android-test-plugin and although Robolectric doesn't play well with Volley yet, it should soon (I hope).
Anyways, so the structure I use for my app is this:
ObjectJacksonRequest class which get the data from the webservices and parses them into POJOs
RequestQueue standard volley request queue
BaseActivity the parent activity of all my app's activities which houses the RequestQueue object and other common stuff
Various Abstract activities which I use to separate the UI code from the network code. For example, the AbstractAppleActivity is extended by any activity that needs an apple. The abstract activity does things like check if the Apple is still in memory when returning, load new ones, set up adapters for list views, etc.
Here's the questions I currently have. I have some intuition on the answers should be but I'd like to hear from the community. I'm sure there are others questions too that people might have and we can add those to this list:
What's a good way to test the ObjectJacksonRequest object for the various web services ? Should I be writing a separate test for each web service that returns and object ?
Should I be testing network requests with the actual webservices or mock the responses ?
Should I be testing the BaseActivity and the abstract activities or the activities that extend it for it's functionality ?
What is the best way to test an activity that doesn't have any values inserted until the web request is completed ? For example, an activity that loads a list of apples.

What's a good way to test the ObjectJacksonRequest object for the various web services ? Should I be writing a separate test for each
web service that returns and object ?
If I am understanding it correctly you want to test the webservice backend. In that case I would write a test per call, or even multiple tests per call one testing each response senario.
Should I be testing network requests with the actual webservices or mock the responses ?
I would mock out the responses. It is my experience that if you test against a real webservice, you will get random fails because the connection was to slow or timed out or something and you end up running your test twice just to be sure it wasn't a random fail.
Should I be testing the BaseActivity and the abstract activities or the activities that extend it for it's functionality ?
I would not test the BaseActivities unless they have a lot of logic.
What is the best way to test an activity that doesn't have any values inserted until the web request is completed ? For example, an
activity that loads a list of apples.
Mock out the webservice response, so that it has values. You can do this with Robolectric. I believe the relevant method is Robolectric.addRequestInterceptor

I have more experience with testing now so here are my suggestions gathered for various sources:
- What's a good way to test the ObjectJacksonRequest object for the various web services ?
- Should I be writing a separate test for each web service that returns an object ?
- Should I be testing the BaseActivity and the abstract activities or the activities that extend it for it's functionality ?
All of these questions can be bundled into one. This is the question of testing inheritance hierarchies. The answer is, unfortunately, it depends. In most cases however, for abstract classes, testing the sub-classes will test the parent classes as well. Unless you have methods that have different use cases in different sub-classes, in that case you might want to test the abstract class so you can test all the cases as you code them (although if this is happening, you might be better off defining more objects).
- Should I be testing network requests with the actual webservices or mock the responses ?
This is an easy one. Always mock. As the other answer mentioned, you run the risk of writing flaky tests if you are using real webservices. Not to mention that testing the webservices is not your responsibility. You should only be testing code that you are responsible for.
- What is the best way to test an activity that doesn't have any values inserted until the web request is completed ? For example, an activity that loads a list of apples
This should follow from the mocked service. Once you have the mocked service. You can use it to send data to the activity in a reliable way and test the outcome.
Other Notes:
While the above are specific answers. In general I've found it useful to make some engineering decisions that facilitate not only testing but modularity of your apps. So these are some of my tips and to-donts from the engineering mistakes I had in my app design as per the question.
Use custom wrappers for services: In my question I am trying to move from Android's original HTTP to Volley. Part of the reason for these issues is that the app design couples the app with the networking library. One way to get around this is to use wrapper classes that are injected into your code. The underlying implementation of the wrapper class can then change without affecting the other source code. I have a blog post on this topic here.
Use Java modules: The Android gradle plugin in based on the gradle java plugin. You can therefore create Java library modules in your Android app project. I have found this is the best way to unit test your code that doesn't interact with Android API's. This is way easier and faster than both the Android test framework and Robolectric. I find that when I'm using a Java library module, my UI code becomes lighter because I'm trying to have as much work done in the Java module as possible.

Related

Android Unit test API calls with Retrofit2

I haven't done any testing in Android, so please bear with me if this seems a stupid question.
I'm developing an app which makes a lot of network calls from a restful API service. To make the network calls, I'm using Retrofit2 and RxJava.
What would be the best practice/framework to just test if these calls are working? I've started to read the Google Codelab for testing which uses Junit4 and Mockito, but I don't want to do any clicking in the UI to start a test currently, just checking for different API versions which calls are supported or not.
Here some steps for you that I am using:
Use mockito & junit4, for sure :)
I avoid UI tests for these cases
Pass your retrofit Api as a parameter to a class that you want to test
In the test create a mock retrofit api, pass this one as a parameter so you can choose what you want your "Api" to return e.g. objects or errors (see Mockito.when())
Use RxJava's TestSubscriber to test a method e.g. Observable<Location> getLocationFromApi()
Avoid threading in your testing class (e.g. like .observeOn(mainThread())). If inevitable use awaitTerminalEvents in TestSubscriber. If there is no terminal even rethink your test
General tips:
Try to modularize your code so each class has few functionality -> easier to test.
Be patient and don't expect to write tests for e.g. 5% of your code in just one week :) It's a slow process regardless team size

Android REST API with RetroFit

My question is kinda theorical, hope I can get a clear explanation on this.
I've been looking for a nice rest api consumer for android (or some clear info on how to develop a solid one) and I found the rest api design talk from google IO 2010.
"Developing Android REST Client Applications - Google"
It's been 4 since this talk and I think there might exitst new designs and techniques for this matter, or not ?
The scenario that I think that would work the best for me is this one:
So my first question is, does this architecture is still valid for a new app (Starting from the beginning) ?
I've found Retrofit, which seems a pretty nice and stable Api for the rest service, but I can't quite understand how it works, like if it is a good approach to call my api endpoints from activities (or frags) and the library handles the resume/pause (delivering results when activity is on hold, or not) or I must implement this myself.
Sorry for the long post and thanks for the patience !
You must implement how to handle that yourself, to answer your question.
Yes, that architecture is valid, but RetroFit only forms part of the "Rest Method" block. How would you implement it? That depend on what you want. You could use Retrofit (AKA the REST Method) inside the service, and that would be ok, however you can also skip using services and use it inside of an activity or fragment. However if you do the second option(activities/fragments) you can not think in handling the activity life cycle within retrofit(onStart, onPause, etc..) because since these are network calls, you must perform them on worker threads(AsyncTasks for instance).
So in conclusion, whatever option you decide, being Services or worker threads, you must think in using perhaps observers to control your activity/fragment, and remember that requesting network data is always done out of the ui thread. Implementations of how to handle the situation may be done by you depending on your needs and complexity of the application.

android testing mockup components

I would like to make some automatic UI tests for my Android application using recomended approach ( http://developer.android.com/tools/testing/index.html ). My activity fetches data from server and after getting response it modifies some UI elements. I want to check whether UI is modified properly but I also want to test this issue without connecting to server. I thought about providing mock component instead of object which connects to server on behalf of activity. But how could I in my test cases tell acivity to replace original object with mock object? Do you know any good approches?
I thought about putting a special flag in Intent using setActivityIntent (indicating that mock object should be used) before calling getActivity in my ActivityInstrumentationTestCase2 instance.
But this approach requires adding some if statements in application code what makes code less clear and more complicated.
Do you have any better suggestions? Thanks in advance.

What is the best threading choice in an Android application for a RESTful API passing JSON data?

I am new to Android. I’m attempting to write an application which will display multiple pieces of information about open stores. I get that information using a RESTfull API which passes JSON data.
Here is my question: What is the best service/threading implementation choice?
Here are my product requirements:
• I want to encapsulate all the API and JSON into a class that one or more Android “Activities” can call. I think this might dictate a service but this service will only need to run when my application is running and will not be accessible by other applications. The user will be required to authenticate into the remote system via the RESTfull API.
• It will have to be on a separate thread because of the possibility of the API calls taking too much time. I don’t think it will need to be multi-threaded since I don’t see more than one “Activity” will be interfacing with the service at a time.
• The service should look at caching some of the information it gets back so that when an “Activity” makes a call (“GetStoreList” for instance), it could return a list of stores it already queried earlier. I’m not sure if I should keep this information in memory or try using the SQLite functionality in Android. I could have several hundred stores in the list with ten to twelve other pieces of information associated with each store. Some of this information would be displayed in the “Activity” list view and some won’t. Since I don’t have any experience with SQLite, I’m not sure what the performance cost would be over storing the information in memory.
• There will be about a dozen or so methods that the service will need to encapsulate. For instance: once I get the store list, I may want to call the API again to find out if the store is currently open. Some of the information passed will be custom classes and therefore would require “Parceable” class definitions if I have to use IPC’s as part of my solution (if I understand the Android documentation correctly).
• I would also like to “Lazy-load” the list into my “Activity” so that I don’t have to wait for the full list before updating the user interface.
Possible Solutions (this is all guessing, so please don’t crucify me… that’s why I’m asking the question):
I could use a class extended from “Service.” It would have to handle the threading itself so that long internet calls via the RESTful API wouldn’t hang the system. Alternatively, I could do the thread manipulation first and call the API with the assumption that I can take as much time as I want. I think I would need to implement communication between the “Activities” and the service via IPC’s. This seems a little complicated to me. I’m not sure if I can use the “Messenger” class. It looks easier than the AIDL stuff.
I think I could use an “IntentService”. This would automatically create a separate thread and queue messages/tasks. I think I could communicate with the service (to get the lists of stores for instance) by “Binding” to the service. The problem I see is passing data back and forth and I’m not sure how I would cache the data between calls to the API since the service terminates after making the API call.
Anyway, I’d rather learn from someone who has already done this type of app instead of doing it the wrong way and coding it twice.
Thanks for the help.
AbstractThreadedSyncAdapter was made just for stuff like this. There's a fairly comprehensive (but complex example) here. Also, one of my favorite Google IO videos gives a pretty good overview of how to use it.
Your scenario is almost exactly the same as ours in my previous project. Here's what we came up with (I'm sure it's not original, but is patterned from one of those google io videos too)
A Service handles the request-response of RESTful calls to the server. This is triggered by the activity calling startService(Intent) that includes the parameters in a Bundle included in the intent. The Bundle contains information as to what API will be called, and what parameters are included.
The Service doesn't directly pass the result to the activity - instead it writes the result to an sqlite database. The activity will know that the transaction is finished by observing the db (via ContentObserver). Similarly, the Service can notify the activity once a transaction is completed via broadcast; the activity can catch this by registering a BroadcastReceiver - however the resulting data should still not be directly passed to the activity via Bundle, as there may be cases where the data is too large for the Bundle to contain (there's a limit for the length of a String that can be included in a Bundle) - you still want to put the result in the Provider. The activity should query for the data as soon as the Service notifies the activity that the result is there.
Additionally, you can include a "success" or "fail" flag in the Broadcast that the Service will throw for the Activity, so it will know if it still needs to query for result - this removes an additional overhead for failed transactions.
If you need to ask, No we didn't use AIDL for this architecture (but we did use it on another module that does facebook/ym chat over xmpp).
The "lazy-loading" I think can be asked in a different question, as it is an entirely different process.

Android Architecture Design - How to do it right?

how does a good architecture for an android app look like? Should all the "work/business logic" been done in a background service and the Activity communicates just with the service to query/fetch data from somewhere (local/distant)?
Would you implement the "service" that the Activity calls as a real Android-service? Or a POJO-Singleton that does the work (perhaps using background threads). Or instantiate background threads in your activity for time-consuming actions (query a webservice).
How do you abstract your data access the right way? Would you use a ContentProvider to access/abstract your data? How/From where should it be queried? Activity? Service? ..?
I've tried to search for a good app architecture design, but I only found how the Android architecture looks like, not how an Android app should look like.
So what's your opinion about that? What components of an Android application should communicate which each other to ensure best extensibility/encapsulation,...?
There's no one answer to this question. Good OO design isn't Android specific. I'd say that the rule is - if the framework gives you a high level object (such as Service in the case of Android) that fits your use case, use it. If you find yourself making POJO implementations of the same things you get for free with the framework, go with the framework.
As far as separation of concerns, this is standard OO stuff. Don't put anything in your Activity classes that isn't the job of the Activity. Over-stuffing the Activity with methods and properties that the Activity needs but aren't really the job of the Activity is bad - makes the intention of your Activity hard to understand.
I usually separate stuff into sub-packages in my apps.
com.myname.myproject.app - base classes, global application functionality
com.myname.myproject.net - network stuff, network related utils
com.myname.myproject.data - db helpers, providers, etc
com.myname.myproject.model - object model
etc.
As far as communication within your app...
I always have a custom Application class that I register in the manifest. This way, when I have controllers and helpers that need to be a "single instance", I don't have to do all that crazy thread safe singleton stuff...I just keep one global copy of.
RoboGuice is a dependency injection framework that makes this even easier to accomplish...definitely worth looking into. If this interests you, the Google Group for RoboGuice is great and is constantly filled with the creators of the framework who can basically answer anything you need.
As far as in-app communication, I use my single instance Controller and State classes to hold state and do common tasks, and I usually use BroadcastIntents to communicate back to Activities from Services

Categories

Resources