Unit Testing Android Activity with Robolectric

Hello there! Am back with another tutorial on the Robolectric concepts. Today, lets learn how to write Unit Test Cases for Activities. To understand the basic concepts of Robolectric and writing Unit Test Cases, please go through my previous tutorials.

Note : Robolectric Jar of version 2.3 is used in this tutorial.

Robolectric Test Cases
Robolectric Test Cases

Something to remember!

One basic thing you have to remember before you pull your socks to write Unit Test Cases for Activities is that Robolectric does not call the Activity's life cycle methods automatically as in the case of real execution (checkout my previous tutorial to know why).

Robolectric stubs out most of the APIs of Activity to facilitate the test cases. So, you have to initialize the Activity in its own way to start off. With this in mind, lets dive into it.

Diving in!

Let us start by writing a simple "Hello World" Activity. Then we will identify the cases to be tested and will implement Unit Test Cases for them

public class HelloWorldActivity extends Activity implements View.OnClickListener {

    private Button mButton;

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mButton = (Button) findViewById(R.id.button);
        mTextView = (TextView) findViewById(R.id.text_view);
        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
        startActivity(intent);

        mTextView.setText("After click!");
    }

}

As you can see, its a simple, straightforward code. I just have a TextView and a Button. My job is to launch Wifi settings and set the TextView once the button is clicked.

So, how many unit test cases do you think should we write? Well, you might have guessed it, its two. One to test if Wifi Settings gets launched and the other to test if the TextView's text really got set.

Here are the test cases!

@RunWith(RobolectricTestRunner.class)
public class HelloWorldActivityTest {

    private Activity mActivity;
    private Button mButton;
    private TextView mTextView;

    @Before
    public void setup() {
        mActivity = Robolectric.buildActivity(
                        HelloWorldActivity.class).create().get();
        mButton = (Button) mActivity.findViewById(R.id.button);
        mTextView = (TextView) mActivity.findViewById(R.id.text_view);
    }

    @Test
    public void testForTextViewTextToBeChangedAfterClick() {
        mButton.performClick();

        String text = mTextView.getText().toString();
        assertThat(text, equalTo("After click!"));
    }

    @Test
    public void testForWifiSettingsLaunchAfterClick() {
        mButton.performClick();

        Intent expectedIntent = new Intent(Settings.ACTION_WIFI_SETTINGS);
        Assert.assertEquals(
                    shadowOf(mActivity).getNextStartedActivity(),
                    expectedIntent);
    }

}

Initializations

We have seen about @RunWith and @Test annotations in the previous tutorial. But what is this @Before? As the name says, the code in this method runs before the actual test method. We use this method to do any initializations required for test cases. As you can see, initialization of Activity is needed for both the test cases. So, we extract that into setup() method. Similarly, there is an @After method available, and as you might have guessed it, it runs after the execution of each test case.

Remember! In Unit Testing, @Before and @After annotated methods are called for each Test case! Dont think that they are called only once for the entire class. This is because, in Unit Testing, we test each unit as an independent entity. So, we isolate it from the other test cases.

Awesome, now lets get into initializations part in setup() method. As said in the above section, you have to initialize RoboActivity in the Robolectric's way to test. For this, you have to use Robolectric.buildActivity(YourActivity.class) to create a test instance of the Activity. Now, you can call create() on that which calls the onCreate() method and resume() which calls your onResume() method and so on... This way, we can drive through the life cycle methods of the Activity.

Apart from initializing the Activity instance, you get the TextView and Button views similar to how you do in the actual Android Activity.

Testing our code

The first unit test case - This test case is pretty much self-explanatory. You mimic the button click and then check whether the text in Text View is set or not.

The second unit test case - As we learnt in previous tutorials, we should only test if we request system with the desired Intent or not. So, the API getNextStartedActivity() will return the intent with which we called startActivity(). We assert this based on our desired Intent. (Lets learn about shadowOf(Activity) in upcoming tutorials)

Thats it! We wrote our first unit test cases for Activity!

If you use RoboGuice for your Activity, there will be slight modifications to the above code. Don't worry, we'll cover that in the next tutorial.

Please share your views, thoughts or feedback below.

HAPPY CODING...!!!

How to write Robolectric Unit Test Cases?

In this RoboGuice tutorial, I am going to explain you how to write Unit Test Cases to test your Android code with Robolectric. If you are not aware of What Unit Testing is or What Robolectric is, you can checkout my previous tutorial explaining the same.

Robolectric
How to Write Unit Test Cases?

Before moving on to learning how to write Unit Test Cases for Android, lets see how to write Unit Test Cases in general.

As described in my previous tutorial, Unit Testing is the testing of the individual units of source code. Unit Test Cases focus on testing an individual method (or function) or a piece of code in your application. Each method typically expects one or more inputs and gives an output. So, your test cases should simply supply some values as inputs and match the actual output it gives with the expected result. If it matches, your test case passes else it fails.

Say, for example, you write a simple add() method, which should add any two natural numbers but should throw some exception if some negative integers are provided. So, you have got to test this particular method in two different scenarios. One case where you give two positive numbers and verify the actual output. The other case, where you supply negative integers and check for the exception. So, for each scenario, you write one Unit Test Case. Simple!

Now, lets get into more particulars of writing them. The basic funda of writing them is to test only what happens within that method, not what happens beyond its control. Didnt get me? I will explain. Consider this example.

// Business logic Class
public class CarFactory {

    private Tyre tyre;
    private Logo logo;

    public CarFactory() {
        // initializations
    }

    public void manufacture() {
        tyre.fix();
        logo.fix();
    }

}

// Test Class
public class CarFactoryTest {

    @Test
    public void testCarManufacture() {
        carFactory.manufacture();

        verify(tyre).fix();
        verify(logo).fix();
    }

}

Here, in the case of unit testing manufacture() method, we assert our test case by verifying whether calls to tyre.fix() and logo.fix() have been made using the verify() API. But, we dont care about what happens in the fix() method of Tyre class! It is the duty of the Unit Test Cases of Tyre class to test whether the intended functionality happens in that particular call. So, this way, each and every class is covered by their respective test cases which ensure their respective functionality. With this understanding, let us proceed to learning how to write Test Cases using Robolectric.

How to write Robolectric Test Cases?

One basic thing that you have to remember before writing test cases for Android components is that Robolectric doesnt know about the lifecycle of your Activity or Service or whatever the Android class it is. For Robolectric, your Activity's life cycle methods are just like any other normal Java methods. Neither it keeps track of them nor it initializes your Activity's layout and other stuff. It just mocks and stubs them out! It never calls the real methods and executes them.

This means that you can never expect your onCreate() method of Activity to be called when you create an instance of Activity. Also, you can never expect onStart() or onResume() methods to be called after you call onCreate(). You have to call all of them individually in your test cases and test the code in them.

Now, the question that comes to your mind is, "How would it test my code or how would it help me in testing then?" The answer is as stated above, "Its not your job to test the life cycle of Android's Activity class". You should just test whether your intended code gets executed when the appropriate API is called. Robolectric concentrates just on the same. It just tells you whether your intended action has been performed or not.

Confused? To understand it, consider an example of writing Unit Test Case for starting an Activity.

public class MyActivity extends Activity {

    public void startWifiActivity() {
        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
        startActivity(intent);
    }

}

@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {

    @Test
    public void testStartingWifiActivity() {
        myActivity.startAnotherActivity();

        Intent intent = shadowOf(myActivity).getNextStartedActivity();
        assertEquals(intent.getAction(), Settings.ACTION_WIFI_SETTINGS);
    }

}

Our intention here is to start the Wifi Settings Activity when the startWifiActivity() method of MyActivity is called. We have to write a test case to test the same.

If you look at the test case, we verified the starting of  Wifi Settings Activity by getting some Intent by calling shadowOf(myActivity).getNextStartedActivity() and asserting on it. This is a Robolectric API which stubs out the actual startActivity() method of your Android's SDK. What it does is, it stores the Intent our code used to start the Wifi Settings Activity with. It returns the same intent when you make the above call in your test class. Now, you assert it by checking if the Intent Action is correct or not. So, if the call to startActivity() is not made in your code, this Intent would be null and your test case fails.

Here, Robolectric's intention is not to start the actual Activity. Thats the job of Android OS but not Robolectric! So, Robolectric simply makes sure that the call to the system API is made properly (similar to verifying the method call of tyre.fix() in the above example). Mind you again, we should test our code, but not Android's code! This is how you write your unit test cases for Android.

So, coming to the semantics of writing them, you can see two new things over there, one is @RunWith(RobolectricTestRunner.class) and the other @Test. Let me explain. The first one tells Robolectric Test framework that we want to use the default test runner for testing. A Test Runner is nothing but the one which sets up the environment and runs each test case in the file. We will learn more about this in the upcoming posts. As of now, just remember to annotate the class with this annotation. Coming to @Test annotation, as the name says, it is a test case to be executed. The Test framework goes through your file and executes all the methods which are annotated with this annotation. So, you should always annotate your test case with this to tell the framework that it is a test case.

I will explain you more about the Robolectric APIs and the ways of testing Android components like Activity, Service, etc... in my next tutorials. Stay tuned.

Please do leave your feed back below. Thank you.

HAPPY CODING...!!!

Robolectric - Unit Testing Android Applications

23:54 Posted by Unknown 3 comments

What is Unit Testing?

Unit Testing is the testing of the individual units of source code. Now, what is a unit in source code? It is the smallest piece of code that is testable in the entire source code. The test cases we write to test these small chunks of code are called Unit Test Cases.

What is Unit Testing?
What is Unit Testing?
Why should we write Unit Test Cases?

There are several reasons for why we should write them. Few of them are:
  1. You can change or modify your code with more confidence. It means that you can be more confident that your change or implementation does not break any other feature or code.
  2. To facilitate unit tests, you have to write your code in a modular way. If your code is too complicated or if your class becomes too complex, you cannot (or it is very difficult) write unit test cases. So, it actually forces you to write modular code. This makes the maintenance of your code easier.
  3. It helps you develop faster. Let me explain. Say, you have to perform some three to four clicks to get to the point of your code in your actual testing on the device. In order to test the logic you write, you have to build, deploy and do all the above steps to get to that place. A mistake in code, go back and do all of it again! Its a pain and time consuming. But with Unit testing, the testing of your logic happens at the time of running your unit test cases only. Thus, it takes a little time to figure out bugs and test your logic.
Lets consider an example:
    class MyClass {
        int add(int a, int b) {
            return a + b;   // your business logic
        }
    }
    
    class MyClassTest {
        @Test
        void shouldAddBothNumbers() {
            MyClass myClass = new MyClass();
            int sum = myClass.add(1, 2);                    
            assertTrue(sum == 3);   // testing the logic
        }
    }

Here, your testing framework makes the call to your add() method and verifies its result. Instead of you deploying this onto the execution of environment and getting to the point of manually executing it, your test cases does the testing for you. Simple, sweet and straight forward!

What is Robolectric?

In the above example, it is a simple test case, which doesnt involve any of the native APIs of an execution environment.

Coming to Android, you typically use a lot of native APIs in your application code. In order to test this code, you need a testing environment which understands these APIs. It should then test and tell you if it does what it should do.

Robolectric is a Unit test framework which exactly does the same. It understands these and tests them during compilation itself. So, you need not actually run your code on a device to test your logic. This makes your development faster and more efficient.

Lets look at an example
    // Main Activity
    public class MyActivity extends Activity {

        private Button mButton;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            mButton = (Button) findViewById(R.id.button);
            mButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(
                            getBaseContext(), "button clicked",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

    // Unit test case class
    @RunWith(RobolectricTestRunner.class)
    public class MyActivityTest {

        private MyActivity mMyActivity;

        @Before
        public void setup() {
            mMyActivity = Robolectric.buildActivity(MyActivity.class)
                          .create().get();
        }

        @Test
        public void toastShouldBeDisplayedOnButtonClick() {
            Button button = (Button) mMyActivity.findViewById(R.id.button);
            button.performClick(); // Perform the click..!!

            String toast = ShadowToast.getTextOfLatestToast();
            // Test if toast actually shows up
            Assert.assertTrue(toast.equals("button clicked"));
        }
    }

This test case tests if the toast actually gets shown when the button is clicked. You can test this during compile time itself without actually running it! Say, you forgot to call show() on the toast you created, the test case fails!!! So, you quickly fix it and done, you are ready!

This way, you can test almost all of your code with Robolectric Unit Tests. Tomorrow, when someone changes this code and forgets to put the toast back, this code fails and complains. Fixing which, ensures that no feature is broken. This is what gives you confidence to drive and develop your code faster and better.

I will show you how to configure your application to write Unit Test cases in my next Robolectric tutorial.

Please leave the remarks, if any, in the comments section below. Thank you.

HAPPY CODING...!!

What is RoboActivity? Guicing up Activity

This is my second RoboGuice tutorial on configuring Android applications with RoboGuice (Dependency Injection (DI) for Android). If you are not aware of what DI or RoboGuice is, you can check out here!
In this tutorial, I will introduce you to configuring Android Activities with RoboGuice and its advantages over conventional coding.
RoboGuice - RoboActivity
RoboGuice - RoboActivity
Configuring Activity with RoboGuice:
For the RoboGuice DI framework to inject the dependencies into your Activity, your Activity should extend the RoboActivity class. Thats it..!!

RoboActivity vs Activity:
Lets have a glance at the advantages we derive from using RoboActivity over the conventional Activity:
  1. You need not worry about the initializations of your views and resources. It injects them for you automatically.
  2. It reduces the number of lines of code you write. The more the code - the more the chances of bugs. RoboGuice takes care of the mechanics and you can concentrate on the actual business logic.
So, how does it do all these things?

Lets take an example of a simple conventional Android Activity with a TextView and a Button.

Conventional way:
public class ActivityExample extends Activity {

    private TextView mTextView;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_robo_activity_example);

        mTextView = (TextView) findViewById(R.id.text_view);
        mButton = (Button) findViewById(R.id.button);

        mTextView.setText("Hello RoboGuice World...");
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getBaseContext(), "Button clicked", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

In this RoboGuice tutorial, just have a look at the code. The code of getting the resources via the method findViewById() and typecasting them to the respective types can actually be auto-generated! Because, it is obvious that we want to have the resource R.id.text_view as a TextView object. So, if someone smart enough sits over there, can easily guess this and do it for us. RoboGuice exactly does the same thing for us!

RoboGuice way:
@ContentView(R.layout.activity_robo_activity_example) // same as setContentView(R.layout.activity_robo_activity_example);
public class RoboActivityExample extends RoboActivity {

    @InjectView(R.id.text_view) // (TextView) findViewById(R.id.text_view)
    private TextView mTextView;
    @InjectView(R.id.button)
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mTextView.setText("Hello RoboGuice World...");
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getBaseContext(), "Button clicked", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Now you get the thing. Here, we can straightaway concentrate on setting the text view and implementing a listener instead of writing all the boilerplate code of initializing the resource objects.

This all looks simple and conventional coding is no big deal compared to this. But, think about your class growing like anything into a complex body. It becomes very difficult to maintain it in conventional coding, which is not with RoboGuice. RoboGuice even lets you modularize your code, allowing your classes to be loosely coupled and thus easy to maintain. I will introduce you to such concepts in my next posts.

Stay tuned for more Robo stuff.

You can get an example of the above mentioned RoboGuice tutorial here.

Please allot two minutes to provide feedback below. Thank you!

HAPPY CODING...!! :)

What is RoboGuice? A brief introduction to RoboGuice.

04:57 Posted by Unknown 17 comments

What is RoboGuice?

RoboGuice is a Dependency Injection framework which allows Inversion of Control. Now, thats complicated! What is this Dependency Injection (DI)? It is the technique of passing a dependency (a service) to a client (which needs this service for its own stuff) automatically.

RoboGuice is a type of Dependency Injection framework for Android which injects the required dependencies in the classes in our projects. The roots of RoboGuice are in the famous Google Guice, which can be Googled easily.
RoboGuice
RoboGuice

How does it work?

The RoboGuice DI framework recognizes the required dependencies of your class through an annotation @Inject. Then it initializes those objects for us and injects them in our class.

Let us take an example (This example is just to explain the concepts. Real coding differs):

Say, I want to construct a car object. In order to construct it, I need the Wheels class and Color class.

The conventional way:
class Wheels {  
    int noOfWheels = 4;  
}
  
class Color {  
    String color = "red";  
}
  
class Car {  
    Wheels wheels;  
    Color color;  

    public Car(Wheels wheels, Color color) {  
        this.wheels = wheels;  
        this.color = color;  
    }  

    public void manufacture() {  
        fixWheels(wheels);  
        paintColor(color);  
    }  
}

class CarFactory {
    
    public void manufactureCar() {
        // Manufacture a new car here
        Wheels wheels = new Wheels();
        Color color = new Color();
        Car car = new Car(wheels, color);
        car.manufacture();
    }

}

The RoboGuice way:
class Wheels {  
    int noOfWheels = 4;  
}
  
class Color {  
    String color = "red";  
}
  
class Car {  
    Wheels wheels;  
    Color color;  

    @Inject
    public Car(Wheels wheels, Color color) {  
      this.wheels = wheels;  
      this.color = color;  
    }  

    public void manufacture() {  
      fixWheels(wheels);  
      paintColor(color);  
    }  
}

class CarFactory {
    
    @Inject Car car;

    public void manufactureCar() {
        // Manufacture a new car here
        car.manufacture();
        // See the difference, no need to initialize anything
        // DI takes care of everything...!!
    }

}

Here, RoboGuice identifies that Wheels and Color are required for the Car object and constructs them automatically and injects them in the Car class. Isn't it fantastic...?? For me its amazing stuff !!

Its all good. But I can still create the dependencies as per the conventional way. But why should I go with RoboGuice? Well, the answer is that as your code grows, the number of dependencies as well as the complexity of those dependencies grows. Let me explain you.

Say, as per the latest requirements, if the Wheels class requires a Wheel type (say, Alloy), then how would you go about it? You should change the Wheels class as well as the all the places where the Wheels object is created in the conventional coding. Now, imagine if your Wheels class is used by some tons of classes, you should go and change all of them. This is something very serious and hectic. Something like this:

class Wheels {  
    AlloyWheelType alloyWheelType;
    int noOfWheels = 4;

    public Wheels(AlloyWheelType alloyWheelType) {
        this.alloyWheelType = alloyWheelType
    }  
}
 
class CarFactory {
    
    public void manufactureCar() {
        // Note that you have to create AlloyWheelType instance
        // and also have to change the Wheels object creation.
        AlloyWheelType alloyWheelType = new AlloyWheelType();
        Wheels wheels = new Wheels(alloyWheelType);
        Color color = new Color();
        Car car = new Car(wheels, color);
        car.manufacture();
    }

}

Wont it be good if someone manages all these things for us? Here comes our saviour RoboGuice for us...!! It manages all those tons of classes for us...!! Here's how it does:

class Wheels {  
    AlloyWheelType alloyWheelType;
    int noOfWheels = 4;

    @Inject // Injects this automatically
    public Wheels(AlloyWheelType alloyWheelType) {
        this.alloyWheelType = alloyWheelType
    }  
}
 
class CarFactory {
    
    @Inject Car car;

    public void manufactureCar() {
        // You dont have to change anything at all...!!
        car.manufacture();
    }

}

So, if you use RoboGuice, you can manage all these kinds of dependencies and complexities easily in your Android projects for all the hundreds and thousands of classes you write. Also, it provides loose coupling between various modules of your project and hence maintenance of your code and quality improves.

Earlier in my Android projects, everytime I write a helper class or a class to delegate a task, I had to manually pass the Context object to all those classes. Thanks to RoboGuice, now it does it for me everytime.

Please provide your feedback below. Thank you!

HAPPY CODING...!! :)