Android JUnit and parsing xml data - what to test - android

I am trying to get more experience on JUnit and its usage in Android.
Referring to this official Android training Parsing XML data I wonder if anyone can provide with an example on how to test some of the used methods.
Particularly how would you test the methods included in the class StackOverflowXmlParser and the methods loadXmlFromNetwork() and downloadUrl() [class NetworkActivity.java]

The best advice I can give you on unit testing is to first really understand what a unit of test is. When I write tests, in particular Unit Tests, I make sure my unit of test is a single class. EVERYTHING ELSE is mocked, and my test makes sure every public method on the class does what it promises.
That said, the methods you are asking about are EVIL UNTESTABLE CODE. It's a bit shocking to see code like this come from a Google engineer. My glancing guess is it's a front end web developer because the variables are all declared at the top of the method, Javascript style and initialization of every local variable that doesn't have a value to null suggests whoever wrote the example isn't very experienced with Java.
You would have to significantly refactor the methods to get them into a testable state. For instance loadXmlFromNetwork presents an API that lies. It isn't "loading" xml from the network, it's also parsing it into a List<Entry> then after that is done, it does more by cramming data from these entries into an HTML formatted String and then returns that.
The first problem with just this method alone is that it's creating objects inside of itself, instead of asking for what it needs. This presents a problem for testing because you can't mock these objects to test the logic. In a test you wouldn't want to have to make a network dependency, so you'd want to mock the HttpURLConnection and mock the behavior to exercise YOUR code.
To point you in the right direction, watch this video from Google's lead testing evangelist:
http://www.youtube.com/watch?v=wEhu57pih5w

Related

Why use Dagger or Hilt DI when I can use static functions?

I am learning DI with Dagger2 and Hilt and I've got a question:
When creating android app I notice that I use lots of utility classes with static methods(i.e. a function that receives temperature in Celsius and return it in Fahrenheit). BUT, also I use a class (say NetworkUtils) with a static utility method for performing network call to get data from API (as what Android Nanodegree course's instructors were doing):
What I do is like:
class NetworkUtils{
public static String fetchCityName(double latitude, double longitude){
// code for API call
}
}
And now, while I am learning DI principles from Developer Docs, I notice that network calls are made in an instance class within an instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing?
I read that static methods make testing not easy, however, suppose I used DI like the docs shows,
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances is useless?
Also, the official docs says that our use of #Singleton annotation to set function scope (i.e. for a REST API call function) should be very rare, then:
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object instantiation)
Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods in it?
Thanks.
And now, while I am learning DI principles from Developer Docs, I
notice that network calls are made in an instance class within an
instance method and its parameters are injected using Dagger.
Why does this make difference from what I was doing? I read that static methods make testing not easy, however, suppose I used DI like
the docs shows,
I see two main reasons:
First, of course, is that the static calls make the code hard to test. But yes, there are some testing frameworks that can do the work for you and mock static calls. But whenever you are using them - it most likely means that you are doing something wrong or you are working with legacy code. This leads me to the second topic.
The idea of TDD - Test Driven Development is that you write the tests first, the code second. But the tests "are not important". Actually, the real result is the better code! The unit test just helps, but they are subproducts. Most of the time there is a high correlation between a good code and a testable code. When you have static calls and singletons it is easy for you to call this code from wherever you want. The result is that you stop thinking about design, about the real OOP principles - what is what. You do not think about extra objects, the relation between objects, etc. And you end up with a spaghetti code. Everything is tied to everything else.
Why do I have to instantiate a new object of the NetworkUtils whenever I need to perform API call while creating multiple instances
is useless? Also, the official docs says that our use of #Singleton
annotation to set function scope (i.e. for a REST API call function)
should be very rare, then:
You are saying something which is contradictory - "creating multiple instances is useless". Obviously creating an instance and not using a static call helps you to achieve better and testable code. Maybe you are wondering if it is a performance hit. Here I will quote.. maybe Martin Fowler... but in his book about Refactoring he is explaining that 9 out of 10 times the optimizations are just useless. You are overdoing it. You need to write good code. Then evaluate. Then if there is a need for optimization - you have the good code - the optimization will be relatively easy.
In your case - do not worry. Wrapping the network calls in instance classes will cause how many instances? 3? 5? It is not a problem when you evaluate the benefits.
About the Singleton - you do not need a shared state - so no need for a singleton. You will shoot yourself in the foot. You will keep things that can be garbage collected, add extra code for singleton creation, etc. Just plain object and that's all.
Am I supposed to create instances for everything I need to use even tho it doesn't need to? (except for expensive object
instantiation)
This is a huge question. You should read a few books and still will not know the answer. Try with Uncle Bob's Clean Code and also Martin Fowler's Refactoring. Then read a few articles of people who think that they are overdoing it and find the balance for yourself. In general, you should no be using "new" and any static calls.. But for example, there are a lot of discussions about how useful are really unit tests on Android and there are a lot of people who tend to go in the direction that you need mostly integration and End to End tests. I will not argue what is the right approach.
4. Eventually, could you please clarify the difference between a utility class and a normal class that I should not use static methods
in it?
Basically, you should not be using "Utility classes". Their idea is to wrap some code, which is used in many places, but there is no state involved. You do not need instance variables so the static methods were a good idea. But it will totally kill your testing. So in your case, you should make one type of class and if you need state - add, if you do not need state - just don't. Then you can call the classes whatever you want.

Espresso Best Code Architecture

I want to run an Espresso instrumentation test for my application. Test contains navigation to multiple activities and interactions with several widgets.
What could be the best possible coding style I should follow to keep code clear and maintainable.
For now I had create different class for each activity and access static test method as follow:
#Test
public void validateUserNavigationScenario() {
// Create a bitmap we can use for our simulated camera image
SignOnActivity.validateLogin();
ProductSelector.selectProduct();
ProductDetail.showProductDetails();
ProductDetail.addProductToCart();
pressBack();
ProductSelector.selectProduct();
// ... additional test steps and validation ...
}
Coding test code is not different from coding production code.
The same good patterns and habits used for production code should be present in testing code. Using static reference as the main approach to structure all your suits seems to me a bad decision.
You should check it out Jake Wharton's talk about how to structure your testing code.
Instrumentation Testing Robots
It is focus on Kotlin development, but the same principles apply for Java. To sump up, it claims that you should hide your internal details inside some sort of “robot” pattern. Which means that you should try to be as much semantic as possible with your exposing API in order to create readable and maintainable tests.
Think on your test as if they were be used for other devs, and then think that you are one of them. How do you want it to use them?

Trying to fit a "clean architecture" on an iOS app

Recently I’ve been rethinking my android architecture project, trying to adapt it to a more “clean architecture”, specifically, the kind of design suggested by “Uncle Bob”.
Which it involves several layers of abstractions, a nice isolation of responsibilities and a very strong dependency inversion achieved by dependency injection; which, ultimately, leads to a very decoupled-portable system. A perfect candidate to be tested by unit testing and integration testing.
In my android implementation I’ve ended up having three different modules or layers:
-domain: entities, interactors, presenters (pure java module)
-data: (acts as a repository to supply the data to the domain) (android library module)
-presentation: ui related stuff, fragments, activities, views, etc (android application module)
So, I’m trying to figure out what would be the best approach on the iOS ecosystem.
I’ve tried creating a project with multiple targets to achieve the same solution:
-domain: command line target (which seems very weird but I think is the most pure swift target available)
-data: cocoa touch framework
-presentation: cocoa touch framework
With this approach I can use these targets in the way I did with android modules. But the first caveat I’ve found it is that I need to add manually every new file to the dependent target.
But my knowledge is very limited in projects with multiple targets. I mean I’ve never created an iOS application with multiple targets. So I don’t know even if the solution would be use a framework (cocoa touch/cocoa) as a target instead of a command line module for the domain layer.
Any thought would be really appreciate.
Thanks!
Uncle Bob's Clean Architecture absolutely applies to iOS, Swift, and Obj-C. Architecture is language agnostic. Uncle Bob himself codes mostly in Java but in his talks he rarely mentions Java. All his slides do not even show any code. It is an architecture meant to be applied to any project.
Why am I so sure? Because I've studied MVC, MVVM, ReactiveCocoa, and Clean Architecture for 2 years. I like Clean Architecture the best, by far. I tested it by converting 7 Apple sample projects to using the Clean Architecture. I've used this approach exclusively for over a year. It works out better every time.
Some of the benefits are:
Find and fix bugs faster and easier.
Extract business logic from view controllers into interactors.
Extract presentation logic from view controllers into presenters.
Change existing behaviors with confidence with fast and maintainable unit tests.
Write shorter methods with single responsibility.
Decouple class dependencies with clear established boundaries.
We also added a router component so we can use multiple storyboards. No more conflicts.
Writing unit tests is greatly simplified too because I only need to test the methods at the boundaries. I don't need to test private methods. On top of that, I didn't even need any mocking framework because writing your own mocks and stubs becomes trivial.
I've written my experience for my last 2 years studying iOS architecture at Clean Swift I also put together some Xcode templates to generate all the Clean Architecture components to save a ton of time.
UPDATE - To answer #Víctor Albertos's question about dependency injection in the comment below.
This is a really great question and demands a long detailed answer.
Always keep the VIP cycle in mind. In this case, the doSomethingOnLoad() method is not a boundary method. Rather, it is an internal method invoked only within CreateOrderViewController. In unit testing, we test a unit's expected behavior. We give inputs, observe outputs, then compare the outputs with our expectations.
Yes, I could have made doSomethingOnLoad() a private method. But I chose not to. One of the goals of Swift is to make it easy for developers to write code. All the boundary methods are already listed in the input and output protocols. There is really no need to litter the class with extraneous private modifiers.
Now, we do need to test this behavior of "The CreateOrderViewController should do something on load with this request data" somehow, right? How do we test this if we can't invoke doSomethingOnLoad() because it is a private method? You call viewDidLoad(). The viewDidLoad() method is a boundary method. Which boundary? The boundary between the user and view controller! The user did something to the device to make it load another screen. So how do we invoke viewDidLoad() then? You do it like this:
let bundle = NSBundle(forClass: self.dynamicType)
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
let createOrderViewController = storyboard.instantiateViewControllerWithIdentifier("CreateOrderViewController") as! CreateOrderViewController
let view = createOrderViewController.view
Simply calling the createOrderViewController.view property will cause viewDidLoad() to be invoked. I learned this trick a long time ago from someone. But Natasha The Robot also recently mentioned it too.
When we decide what to test, it is very important to only test the boundary methods. If we test every method of a class, the tests become extremely fragile. Every change we make to the code will break many, many tests. A lot of people give up because of this.
Or, think about it this way. When you ask how to mock CreateOrderRequest, first ask if doSomethingOnLoad() is a boundary method that you should write test for. If not, what is? The boundary method is actually viewDidLoad() in this case. The input is "when this view loads." The output is "call this method with this request object."
This is another benefit of using Clean Swift. All your boundary methods are listed at the top of the file under explicitly named protocols CreateOrderViewControllerInput and CreateOrderViewControllerOutput. You don't need to look elsewhere!
Think about what happens if you were to test doSomethingOnLoad(). You mock the request object, then assert that it equals to your expected request object. You are mocking something and comparing it. It's like assert(1, 1) instead of var a=1; assert(a, 1). What's the point? Too many tests. Too fragile.
Now, there is a time when you do mock CreateOrderRequest. After you've verified the correct CreateOrderRequest can be generated by the view controller component. When you test CreateOrderInteractor's doSomething() boundary method, you then mock CreateOrderRequest using interface dependency injection.
In short, unit testing is not about testing every unit of a class. It is about testing the class as a unit.
It is a mindset shift.
Hope that helps!
I have 3 series of draft posts in Wordpress on different topics:
In-depth look at each of the Clean Swift components
How to break up complex business logic into workers and service objects.
Writing tests in Clean Swift iOS architecture
Which one of these do you want to hear more first? Should I bump up the series on testing?
In my opinion Clean Architecture is a set of ideas, rules, principles... to make a code better.
[Android Clean Architecture]
With this approach I can use these targets in the way I did with android modules.
You are able create a target[About](application target or framework target...) but it depends on your needs
If you read Architecting Android...Reloaded from Fernando Cejas
you might have seen that I used android modules for representing each layer involved in the architecture.
A recurring question in discussions was: Why? The answer is simple… Wrong technical decision
The idea is that is not necessary to use some build components to implement Clean Architecture

Why should i mock objects?

I want to some feedback on why I should use mockito when testing my android application and also does anyone have any real examples of mockito would be extremely useful.
Such as a git project with various use cases of mocking android tests.
Mock objects are useful when you want to test part of an application when either the rest of the application isn't written yet, or when you don't want to actually have the side effects that the real code causes (such as writing to a database).
Mocking objects is commonly used it unit testing.
Unit tests are made to assure that the flow of instructions in your code is correct, and the logic is OK, but doing it separately from other classes/objects. Just one class at a time.
So, when your code makes use of any object of other class - you mock it and it behaves like correct object of mocked class, without actually making object of that class.
I suggest you reading about unit testing, injection, mockito.
Hope it helps you to get the idea behing mock.

Mocking android applications like the contacts app using Mockito

I am trying to write functional tests for an android application. The problem is that most functional testing frameworks that I have explored (calabash-android, robotium) have a limitation on the number of activities from different applications that can be tested in the same test. So if in one workflow I need to select some contacts from the android contact picker I cant test that entire flow because the contact picker activity is part of the android contacts application and the framework can't test an activity from my application and the contacts application at the same time.
One possible solution my team thought of was to mock out the call to the contacts activity to return a dummy intent with contact information so that our application workflow can be tested. We are trying to use mockito to achieve this. However I am stuck pretty early on. Here is what I am trying to do
MyActivity mockActivity = mock(MyActivity.class);
when(mockActivity.startActivityForResult(<?>,anyInt())).thenReturn(fakeIntent);
I am not sure what to put in the first parameter in the second line. I have tried Intent.class and android.content.Intent.class however it throws a compile error. If anyone has worked with mocking activities using mockito, some help will be greatly appreciated.
P.S. - If I understand correctly mocking is used more in unit testing than functional testing. So these tests would be more of a hybrid. If anyone has a better suggestion on how to go about these functional tests on android I am all ears.
It's hard to answer this without knowing the signature of your startActivityForResult method, but the general idea is to use any(Xxx.class), where Xxx is the type of the parameter. So either
when(mockActivity.startActivityForResult(any(Xxx.class),anyInt())).thenReturn(fakeIntent);
or the (kind of equivalent)
doReturn(fakeIntent).when(mockActivity).startActivityForResult(any(Xxx.class),anyInt());
The issue is that you cannot really "mock" (actually "spy") on the activity you're testing since it is created out of your control by Android's instrumentation code. In a unit-test environment where you would have control, you could follow the mock(MyActivity.class) or spy(myActivityInstance) path (spy would actually be better because you could re-use most of the activity's original implementation), but here not.
The only solution I found for this dilemma was to move certain functionality out of the activity into utility classes, ideally utilizing roboguice for that (#ContextSingletons can be used to process activity results). Then, in your test project, you would create your own test guice injector, set that as base application injector before you call getActivity() for the first time and then let the activity work on your mocked utility class.
I outlined the complete process here.

Categories

Resources