Snapshots of my experiments...

Saturday, June 18, 2016

Unit Test is one of the most important part of development artifacts, which helps to automatically test whatever code we write. Coverage report measures quality of Unit Tests and points out unused/untested code. This tutorial will help to get started with Unit Testing and Coverage report in Python.
For this tutorial we will use Eclipse PyDEV as Python IDE and its integrated Coverage plugin to generate Code Coverage report.

Sample Code:
Download sample code from GitHub. This includes a function (under /src) to get ODD and EVEN numbers for a supplied Count. If supplied count is ODD, it returns all ODD numbers and vice versa. For this implementation, we have written Tests (under /test) which validates count of numbers returned. Count of numbers returned will be half of Supplied Count e.g. Supplied Count 100, it'll return 50 EVEN numbers.

Project Structure:

Create Python Project ("UnitTest") and then create 2 Source Folders under this Project- "src" and "test". Source codes are kept under "src" and respective Unit Test scripts under "tests" Folder. Unit Test scripts are created using same Package structure as of the actual script but Module name prefixed with "test_".

Unit Tests:

Python (since 2.1) includes Unit Test package (unittest). It helps to test scenarios of functions/classes and assert conditions. We'll cover more about unittest functionality in upcoming tutorials. In this session, I'll cover very simple assertion (assertEqual), which validates equality.

import unittest

import me.pras.data as data

classTest(unittest.TestCase):

deftestData(self):

count = 9

expectedCount = count/2

nums = data.getNumbers( count )

self.assertEqual( len( nums ),
expectedCount, 'Count mismatch...')

if __name__ == "__main__":

unittest.main()

Above code validates functionality of me.pras.data.getNumbers() function. If we run this Test (Right click on test_data.py - Run As - Python unit-test)

Drag and Drop our Project "UnitTest" at the bottom area of "Code Coverage" view.

If you have already run the Unit Tests, it'll show report on right-hand side of "Code Coverage" view. As you can see, we are passing only EVEN count as a part of Unit Test, so it has marked else sectionand_odd() functions as untested.

Isn't it Cool ? It points out any untested code and measures accuracy of your Unit Tests.

Wednesday, September 18, 2013

Have you ever tried to launch Android Toast message from worker thread ? Probably you are wondering why the heck it is giving this error-

java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare()

In this article we are going to explore reason behind the above exception and try to understand how Looper works in Android. At the end, I am going to explain one approach to run Toast from a worker thread, but before that we need to understand how Looper works. If you already know in/out of Looper, you can skip below section and directly move to the solution part.

Looper is a very basic wrapper class which attach a MessageQueue to a Thread and manage this queue. MessageQueue is a structure to sequentialize simultaneous processing requests of a Thread. In Android, message/request processing classes like Handler uses Looper to manage their respective MessageQueue.

Looper = Thread + MessageQueue

Android Looper Life Cycle:

As you can see in the above figure, Looper Life cycle starts when we call prepare(), this static method creates instance of Looper class and store this in a ThreadLocal variable. Below code snippet from Looper.java

privatestaticvoid prepare(boolean quitAllowed) {

if (sThreadLocal.get() != null) {

thrownew RuntimeException("Only one Looper may
be created per thread");

}

sThreadLocal.set(new Looper(quitAllowed));

}

privateLooper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mRun = true;

mThread = Thread.currentThread();

}

Once Looper instance is created we have to call loop() which starts an infinite Loop and process requests accumulated in the Message Queue. Below code from Looper.java

publicstaticvoid loop() {

// Looper instance and Thread
verification

finalMessageQueue queue = me.mQueue;

for (;;) {

Message
msg = queue.next(); // might block

if (msg == null) {

// No message indicates that the message queue is quitting.

return;

}

// Process Messages

}

}

Due to above Infinite Loop, Looper blocks the current Thread execution until we call Quit. To get a hook to know when Looper is done with Message processing or when Message Queue is empty, we need to register MessageQueue.IdleHandler listener to the MessageQueue associated to the respective Looper. This can be achieved as-

// Prepare looper

Looper.prepare();

// Register Queue listener hook

MessageQueue queue = Looper.myQueue();

queue.addIdleHandler(new IdleHandler() {

@Override

publicboolean queueIdle() {

// TODO Auto-generated method stub

returnfalse;

}

});

// Start looping Message Queue

Looper.loop();

Running Toast from Worker Thread

Now, lets explain how we can run Toast in a thread other than UI or Main Thread. If we look inside of Toast.java, when we call makeText() internally it initialize Handler on the Calling thread. So, if the calling thread has not yet been attached to a MessageQueue Toast fails to create its instance. The only way to attach MessageQueue to a Thread is to use Looper, as a result Toast.java throws below exception-

java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare()

Toast.java -> Toast.TN.java -> Handler.java

public Toast(Context context) {

mContext = context;

mTN = new TN();

mTN.mY = context.getResources().getDimensionPixelSize(

com.android.internal.R.dimen.toast_y_offset);

}

public Handler() {

// .......

mLooper = Looper.myLooper();

if (mLooper == null) {

thrownew RuntimeException(

"Can't create handler inside thread that has not called
Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = null;

}

So, I hope we now understand the real meaning of this famous error message. Lets now try an alternate approach to execute Toast in a separate Thread.

We need to initialize Looper and attach MessageQueue to our calling Thread prior to launch Toast. When we call show() method of Toast, it sends Handler message to process display logic of Toast, then it waits for defined time (LONG/SHORT) and then calls hide() which again sends Handler message to remove Toast View. Thus Looper associated to Toast is requesting for MessageQueue twice, so we'll keep a counter to track number of MessageQueue requests and when it is 2, we'll quit the Looper. It is really important to quit the Looper, as if we don't do so, it will block all further operations, since Looper.loop() is a blocking call.