Quick look at android testing frameworks

Testing is an integral part of every application to ensure the accuracy and stress the code with every possible input and situation. but why? If you believe that user will always follow the instructions then you are leaving some loopholes in applications and don’t forget, some people always wants to see the world burns (hackers?, bounty hunters).

Android has a strict deadline of 5 seconds to respond to user input if failed then it will produce a ANR dialog and crash the application.

Factors needs to be tested:

  • Network
  • Unexpected inputs
  • Application Performance (memory, cpu consumption)
  • Logic validation

 

Android offers two way to test applications

    • Instrumentation : Allows you to test applications UI on device or emulator
    • JUnit : Allows you to test the application logic

 

Instrumentation Testing: There are many framework available to test application UI and behaviour.

  • Espresso: One of the most famous testing framework to test UI. It allows to perform click and other operations, flexible to write customise validators or matchers.
    Read more about Espresso Testing
  • UI-Automator: To test functionalities like files, wifi setting and perform operation outside your applications UI-Automator is the only way to do it.
  • Appium: if you want to write tests for cross platform app, Appium is one of the most popular platform to write tests although it requires various plugins for different platform and configurations which is an occupational hazard I suppose.

Unit Testing: The process of testing the logic of every method is known as Unit testing. It simply beings with creating the instance of the class, mocking the dependencies and invoking the desired methods by passing the desired inputs if required.

  • Mockito: It’s one of the popular framework to stub method calls with dummy values to test the code logic. Assume you have a method `getTotal()` which can accepts any number of values but internally use another method `getTaxPercantage()` which returns the tax percentage so in order to only test `getTotal()` independent of `getTaxPercantage()` method , you can simply set a fix default return value of  `getTaxPercantage()` method (shown below), hence it’s called mocking.

Mockito.when(mockedObjectOfClassUnderTest.getTaxPercantage()).thenReturn(12);

Mockito cannot mock static and final calls so there are also another popular framework available like `PowerMock`, `EasyMock` etc

  • Robolectric: Often code in activities, fragments, adapters are lifecycle dependent and required the `Context` to work so robolectric allows to create an object of an activity while satisfying the need of lifecycle and context.
  • Junit: Allows to run test methods in an automative way and also provide validation assertion methods to validate the objects or their values and primitive values.

 

Note: Test runners are used to run the test methods and provide the result on the screen. They also provide different-2 features to execute settings or clean up methods etc

 

 

Java 9 with JShell crash course

JShell basically is an interactive command line tool (with an embedded editor) to practice java programming in a more convenient and instantly responsive way just like python, R shell prompt.

So rather than staring with creating class , static main function , you can simply practice concepts in a quick and responsive fashion so no more boilerplate code just to print “Hello world”.

To begin with, you can  download java9 and locate jshell.exe under bin for e.g

“C:\Program Files\Java\jdk-9\bin\jshell.exe” then select and hit enter.

Let’s begin with our holy ancient message “Hello World”. To begin with just type

To print Hello world

jshell> System.out.println("Hello world");
Hello world

Evaluate Expressions

jshell> 1 + 3
$1 ==> 4

jshell> $1
$1 ==> 4

Note : $1  here is a variable name which hold the result of the expression

Imp. Tip : You get the maximum information in jshell , you can set the feedback mode as verbose using below command

jshell> /set feedback v

or via shortcut command

jshell> /se fe v

Now execute the previous addition expression again and see the difference

jshell> 1 + 3
$3 ==> 4
| created scratch variable $3 : int

Create Variables

jshell> int age = 25
age ==> 25
| created variable age : int

 

  • List all variables

    jshell> /vars
    | int $1 = 4
    | int $3 = 4
    | int age = 25

Create Method

jshell> void sessionMethod(){ System.out.println("I am a temporary method"); }
| modified method sessionMethod()
| update overwrote method sessionMethod()

jshell> sessionMethod()
I am a temporary method

Commands

There are some helpful command to view useful information and control the jshell environment and they are prefixed with slash( ). We have already seen couple of them as set, vars

  • Some Useful Commands

    • /help : To view the information about all the available commands
    • /vars : To list all variables
    • /methods : To list all methods
    • /set : To manipulate jshell environment
    • /imports : To View all imports
    • /edit : To view and open snippet in text editor using shown id

Exercise : Create class, Apply edit command and modify and run

  1. Create the class
    jshell> class Foo{}
    | created class Foo
  2. Apply list and open it in editor (A separate text editor window screen)
    jshell> /list
    1 : class Foo{}
    
    jshell> /edit 1
  3. Paste the below snippet
    class Foo{
        void inBar(){
            System.out.println("say cheers with love");
        }
    }

     

  4. Don’t forget to click “Accept” to save the state and exit it , Now you are good to use the class.
    jshell> new Foo().inBar()
    say cheers with love

Features in java 9

There are quite a number of features being added in java 9 and some them are

  • Concrete private methods in interfaces to strengthen functional programming and to keep the API helper methods enclosed inside interfaces
  • Factory methods for collection API to create immutable(cannot be modified) list
    jshell> List<Integer> ints = List.of(1,2,3)
    ints ==> [1, 2, 3]
    | created variable ints : List<Integer>
    
    jshell> ints
    ints ==> [1, 2, 3]
    | value of ints : List<Integer>
    jshell> Map<String,String> rollNo = Map.of("key","value","key2","value2","Article by","Pavneet Singh")
    
    rollNo ==> {key=value, key2=value2, Article by=Pavneet Singh}
    
    | created variable rollNo : Map<String, String>

    Note : Supplying duplicate keys to set and map will produce IllegalArgumentException.

  • Updates in Stream API  including function like takeWhile, dropWhile which take/drop elements while a condition stays true
  • Improved HTTP API backed by builder pattern to keep things concise.
  • And obviously Jshell, along with many others features for jar packaging etc which can be seen via the link.

Happy coding 🙂

Testing Fragments and network call using espresso

Espresso

Espresso is a testing framework by google for UI (user-interface) testing which includes every View component like buttons, List, Fragments . It provides API’s for UI testing in single application. UI test ensures that user don’t have poor interaction or encounter unexpected behavior.

Espresso  has various options to find view on screen , perform actions and verify visibility and state/content of view. e.g

onView(withId(R.id.my_view))        // onView() is a ViewMatcher
    .perform(click())               // click()  is a ViewAction
    .check(matches(isDisplayed())); // matches(isDisplayed()) is a ViewAssertion

where

  1. ViewMatcher : is used to locate the view on UI hierarchy using onView(..)
    • To find views and child in a list onData(..).
  2. ViewActions  : is used to perform action on UI views using ViewInteraction.perform()
  3. ViewAssertion: is used to assert view’s state using ViewInteraction.check() where assertion can be
    • Is text is displayed on screen or not , isDisplayed()
    • View is in enable state, isEnabled()
    • View is a top container or not isRoot()

Note : To create UI test you need to create a class and annotate with  @RunWith(AndroidJUnit4.class)  as

@RunWith(AndroidJUnit4.class)
@LargeTest
public class AppNavigationTest {..}

where @LargeTest mean longer running test including UI

Test Fragment using Espresso

Your Activity (Screen) can be divided into smaller containers called Fragments and during testing you need to first add fragment into host activity which either can be done before starting the actual test or later, when it is required.

 @Before
 public void yourSetUPFragment() {
    activityTestRule.getActivity()
        .getFragmentManager().beginTransaction();
}

Here @Before function will be executed before starting the test. It’s like a setup function to load the fragment into the host activity which is appropriate when test is only fragment oriented.

This transaction can also be done later whenever required.

Note : You can also create normal fragment object and add it to host activity using fragment transaction.

Synchronize Tests with threads and network calls

If you are using thread and any other background process then you also might want to test your code with the same behavior and tell espresso to wait until the tasks are finished.

This can be done using Espresso idling resource

Steps :

  1. Create Espresso idling resource


public class EspressoTestingIdlingResource {
private static final String RESOURCE = "GLOBAL";
private static CountingIdlingResource mCountingIdlingResource =
new CountingIdlingResource(RESOURCE);
public static void increment() {
mCountingIdlingResource.increment();
}
public static void decrement() {
mCountingIdlingResource.decrement();
}
public static IdlingResource getIdlingResource() {
return mCountingIdlingResource;
}
}

2. Now you just need to call increment() function just before executing background process and call decrement() after the background task has been finish.

 EspressoTestingIdlingResource.increment(); 
 //.. execute background process

And after task

 //.. task has been finished
 EspressoTestingIdlingResource.decrement();

Finally , in your test class perform increment and decrement to synchronize espresso with background tasks.


public class AppNavigationTest {
@Rule
public ActivityTestRule<NewsActivity> activityTestRule =
new ActivityTestRule<>(NewsActivity.class);
@Before
public void registerIdlingResource() {
// let espresso know to synchronize with background tasks
IdlingRegistry.getInstance().register(EspressoTestingIdlingResource.getIdlingResource());
}
@After
public void unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoTestingIdlingResource.getIdlingResource());
}
@Test
public void verifyDetailsIntent() {
// check views are displayed or not
onView(withId(R.id.swipe_msg_tv)).check(matches(isDisplayed()));
// perform swipe down gesture to initiate network request
onView(withId(R.id.swipe_container)).perform(swipeDown());
// make sure the empty message is not displayed anymore
onView(withId(R.id.swipe_msg_tv)).check(matches(not(isDisplayed())));
// make sure list is visible
onView(withId(R.id.news_frag_recycler_list)).check(matches(isDisplayed()));
// perform click on third item in the list
onView(withId(R.id.news_frag_recycler_list))
.perform(RecyclerViewActions.actionOnItemAtPosition(3, click()));
// setup code to imitate the action of opening browser
Intents.init();
Matcher<Intent> expectedIntent = hasAction(Intent.ACTION_VIEW);
intending(expectedIntent).respondWith(new Instrumentation.ActivityResult(0, null));
onView(withText(R.string.details_story_link)).perform(click());
intended(expectedIntent);
Intents.release();
}
}

So now espresso with wait for the tasks to finish and let you test your app with the response.

Note : In case you are using AsyncTask then you don’t need any idling resource setup because espresso will take care of it automatically.

Resources

Espresso Android Testing

Espresso idling resource

Goggle android testing samples github

Retrofit and LinkedTreeMap class cast exception

One thumb rule is always stay type safe whenever possible specially when you are not doing anything related with reflection, generic array or something like that.

Retrofit REST call libabrary which is quite popular among android developers due

  • Speed
  • Flexible API generation
  • support of GSON, RxJava , OKHttp and many other parsing libs.

Note : this article expects audience with little knowledge of Android ListView and retrofit library.

While coding in java ,One must follow the some rule and one of them is type safety  especially while doing parsing.

This is the example of the side-effect of using Raw-types for parsing and unchecked casting which resulted in crash.

The below ClassCastException exception is being raised from the adapter class

java.lang.: com.google.gson.internal.LinkedTreeMap 
cannot be cast to com.example.user_pc.myapplication.pojo.ListPojo

when the adapter was not able to find the appropriate type of object from typed list

ArrayList<ListPojo> arrayList = new ArrayList<>();

While reviewing the code , the adapter turn out to be innocent and the fault actually started from the Retrofit REST API end point as


public interface CountryArrayAPI {
@GET("/api/popular_destinations")
public Call<List> getCountries();
}

due to the missing type information (List is a typed interface but here it is of raw type) .GSON was unable to parse it to any Bean type objects and just returned the list of internal representation of parsed data i.e. LinkedMap whereas the desired type is ListPojo.

and further it was down-cast  to ArrayList which still won’t produce any issue except unchecked warning.


Retrofit retrofit = new Retrofit.Builder().baseUrl(Navigation_Url).addConverterFactory(GsonConverterFactory.create()).build();
CountryArrayAPI api = retrofit.create(CountryArrayAPI.class);
Call<List> call = api.getCountries();
call.enqueue(new Callback<List>() {
@Override
public void onResponse(Call<List> call, Response<List> response) {
Gson gson = new Gson();
try {
// unchecked cast and it's bad
ArrayList<ListPojo> listPojos = (ArrayList) response.body();
listRetrofitAndroid = new ListRetrofitAndroid(getApplicationContext(), listPojos);
listView.setAdapter(listRetrofitAndroid);
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
@Override
public void onFailure(Call<List> call, Throwable t) {
Log.d("Failure", t.toString());
}
});

so eventually adapter actually received a typed-list but internally the objects are of LinkedMap not of ListPojo type hence the exception.

Solution:  As suggested avoid raw type so simply provide the type information to Retrofit REST API .

public interface CountryArrayAPI {
   @GET("api/popular_destinations")
   public Call<List<ListPojo>> getCountries();
   // typed list    ^^^^^^^^
}

and apply appropriate changes while making the rest call.

call.enqueue(new Callback<List<ListPojo>>() {
   @Override
   public void onResponse(Call<List<ListPojo>> call, Response<List<ListPojo>> response) {
   List<ListPojo> listPojos = response.body();
   //  always program to interface not to implementation

 

Resource link to original thread

plus use the inspect-code feature under the Analyze option in the toolbar menu to see warnings and make sure to resolve them ASAP.

Generic revisited

Generics was introduced in JDK 5.0 and often heavily used with Collections.

colls-coreinterfaces

Note : Graphic is from official oracle website.

Quick Why

Before generic , All there was non-concrete type references relied on Object and casting, which is known as Raw-Type.

 List list = new ArrayList();
 list.add(new Integer(12));
 list.add("pavneet");
 Integer integer = (Integer)list.get(); // not nice , isn't

With generic , a programmer can restrict the type of list to a specific type.

 List<Integer> list = new ArrayList<>();
 list.add(12);
 // list.add("pavneet"); // compile time error due to defined type

Generic Provides

  • Type inference
new ArrayList<>();  // compiler will automatically infer the type 
                    // with List<Integer>
  • Type Ensure

Generics are only available at compile-time mean compiler will erase all the type related information at compile time phase to support backward compatibility.

A generic methods signature T (with no specific relationship with any type) will be replaced with Object

public static <T extends Number> void display(T anyNumber){ }

Apply javap to view the byte-code.

javap -s yourClassFileName

In Eclipse , Follow steps to View class files in eclipse  and then select your file and press F3

public static void display(java.lang.Number anyNumber);

The type T now has been replaced by Number since “T extends Number”  (imposing upper bound ) mean Number  or it’s sub-types so now display method can only accept Number and it’s sub-types AtomicInteger, AtomicLong, BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short

  • Wildcard
    • ?  : The unknown type. Wildcard can represent any class reference and further the reflection is applied to initialize the fields of  object , created via applying “newInstance()” method
Class<?> c          = Class.forName(a.getCanonicalName());
Constructor<?> cons = c.getConstructor(c);
Object objectStr    = cons.newInstance("java reflection");
System.out.println(objectStr); //  java reflection

Let’s just push it a little further, Create a method which receives the class type and creates a list of passed class type and also returns it

public static <T> List<T> createObject(Class<T> cls,String fieldName)throws Exception{
       List<T> list = new ArrayList<>();
       /*  Use loops to create as many objects as you want againt user input , database            
        *  results and apply reflection to set fields*/
       T obj       = cls.newInstance();
       Field field = cls.getDeclaredField(fieldName);  // get private fields
       field.setAccessible(true);                    // make field accessible
       field.set(obj,"Pavneet");                     // set value of field
       list.add(obj);
       return list;
   }

Call this function like

List<Foo> list = createObject(Foo.class,"name");
list.get(0).sayHi();        // Hi Pavneet

where Foo class will look like this

 class Foo{
    private String name ;
    public void sayHi (){ System.out.println("Hi "+name); }
 }

The createObject function will accept the  class type and field name to set your desire value and return the same List type via applying type inference

 

  • ? extends Type : A Producer which allows only given type or it’s sub-type. To restrict the display method to Number , the type could be defined as “T extends Number” 
 public static void display(List<? extends Number> anyNumber){

But why a Producer , first take a look at what generic doesn’t allow

List<Number> list      = new ArrayList<>();
List<Integer> listInts = new ArrayList<>();
list = listInts;   // error , cannot convert List<Integer> to List<Number>

This often can be perceived as misconception and it’s all over the developer community but still take a look, by assuming the possibly of above statement

list = listInts;
list.add(2.2); // oops, i thought it should be able to add only integers

So Anything<SomeFoo> is not a subtype of Anything<SomeBar> where Foo is a subtype of Bar.

So now the above can be replaced with

List<? extends Number> list = new ArrayList<>();
List<Integer> listInts = new ArrayList<>();
list = listInts; // yes , you did it, but still 
                // can't perform any add operation, hence a producer

So extends with wildcard is basically used to iterate lists while applying restrictions on the type of list. A function below can accept only list of Numbers for traversing and further processing but still it can accept List<Double> and List<Integer> so it is not safe to perform add method with any Number to it.

public static void display(List<? extends Number> anyNumber)
    {//traverse or process elements via loop}
  • ? super Foo : A Consumer , which guarantees that the type will always  be of Foo type for example
 public static void display(List<? super Number> anyNumber){ }

Now the display function guarantees that the type of anyNumber will always be of Number type , e.g.

List<? super Number> list1 = new ArrayList<>();
List<Integer> list = new ArrayList<>();
display(list1);
display(list); // error ,? super Number is not applicable for Integer type

Note : you can add any numeric value to list1 but cannot pass any list expect Number

Another example

class A { }
class B extends A { }
class C extends A { }

public static void foo(List<? super A> list){ }

Now foo can only accept List of A so

foo(new ArrayList<A>()); // Valid
foo(new ArrayList<B>()); // Invalid
foo(new ArrayList<C>()); // Invalid
List<? super A> aList=new ArrayList<>();
foo(aList); // Valid

What is the benefit of using wildcard over generic types

  • Wild can be used independent of generic context ,e.g as shown in previously ,while creating a List or a Class reference.
  • They being more clarity because the declaration is at the single place on the other hand the generic types needs to be declared first in method signature or during class definition.
  • Wild cards are more flexible whereas generic types bring the dependency among usage. e.g. createObject method which restrict the return type, same as the class parameter type.