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...!! :)