Thursday, September 08, 2011

Android Testing: Running tests from code


I was answering some questions at StackOverflow today and one caught my attention. It was asking, well, not directly but I understood this was the intention, how to run the tests not from another computer using adb or Eclipse but from an android application itself. Then, here we are presenting a solution to run instrumentation from code.



private void runTests() {
   final String packageName = getPackageName();
   final List<InstrumentationInfo> list = 
         getPackageManager().queryInstrumentation(packageName, 0);
   if ( list.isEmpty() ) {
      Toast.makeText(this, "Cannot find instrumentation for " + packageName,
         Toast.LENGTH_SHORT).show();
      return;
   }
   final InstrumentationInfo instrumentationInfo = list.get(0);
   final ComponentName componentName = 
         new ComponentName(instrumentationInfo.packageName,
         instrumentationInfo.name);
   if ( !startInstrumentation(componentName, null, null) ) {
      Toast.makeText(this, "Cannot run instrumentation for " + packageName,
         Toast.LENGTH_SHORT).show();
   }
}


You need a valid context to call startInstrumentation() so this is probably added to an Activity.

I can imagine only a valid use case for this, which is running the tests when you don't have the device connected to a computer.
Do you have another use case ?
Speak out.

Hope this helps.

13 comments:

PsuedoNoise said...

If you don't have a physical USB connection, connecting ADB over WiFi is trivial. I can't think of a reason to do this.

Diego Torres Milano said...

Yes, exactly. That's why I mentioned not having a computer at all, not just not being able to connect the device through USB.

Perhaps you want to tests on hundred of devices, who knows...

Pandu said...

Hi Diego,
This was too interesting can u explain in detail how to do this.?
with help of some example..I interested to know more about this.

Unknown said...

Hi, I wonder to see this happening from programitically. It seems same like as DevTools.apk application can give the Option for Instrumentation. Once we can tap on this It can give the list of "Instrumentation Tests" applications.

Thank you for sharing this information us

Regards,
Obula reddy
Agile Test Engineer

Diego Torres Milano said...

DevTools is doing something like that, using the PackageManager to obtain the available Instrumentations and then populating the list.

Does this answer your question ?

Anonymous said...

This sort of thing is useful when testing applications "in the wild". Sitting at a desk, indoors, with good WiFi is NOT a good scenario for mobile computing and yet that's where too many QAs do their tests. Take a bus ride through the city, attempt to use the app at a busy event such as a soccer game, just go outside in the sunlight and see how it reads on your screen.

Another good scenario is if you're working on an app for a client and want to have them walk through a demo script. You can use a test script that is executed locally exercise the app while they watch the actions. This sort of demo is MUCH more effective than simply providing screenshots or video.

ytsolar said...

how to collect the xml report?

EffantTerrible said...
This comment has been removed by the author.
EffantTerrible said...

Where am I have to put that code?

I don't know..

target class? or instrumentation class?

I added target class..

I added in onCreate() method..(startInstrumentation...this code)..

But, when my app executing...it just execute infinitely ~~..

I don't know where am I put that code..

please~help me

Diego Torres Milano said...

@EffantTerrible,

You can find a working example at TemperatureConverterTestsActivity.java.

EffantTerrible said...

Actually, I cannot figure out your link..

Because, No one can invoke the runTests() method.

Then, I just re-check the your source code.

And, I found that you added the runTests() in menu option!.

So, when I just execute the app, then, I push the menu btn, And execute the runTests() method...

That was successful! Thanks a lot!

But, my question is that..

When I just execute the app and instrumentation starts at the same time!..

is that possible?

Dipti Joshi said...

Hi Diego, Thanks for your post, it has helped me a lot!!! I however am facing an issue wherein I have to initialise the UiDevice object and I am doing it in the @Test and not @Before function. However I get the error;
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.UiAutomation.setOnAccessibilityEventListener(android.app.UiAutomation$OnAccessibilityEventListener)' on a null object reference. This is at the line;
Instrumentation instr = InstrumentationRegistry.getInstrumentation();
mDevice = UiDevice.getInstance(instr); ----------------------------------here
Can you please help me in solving this error?

Thanks,
Dipti

Deepak said...

Hi Diego,

thank you for the suggestion. On following above steps getting null pointer exception,

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.UiAutomation.setOnAccessibilityEventListener(android.app.UiAutomation$OnAccessibilityEventListener)' on a null object reference

Any input here is really appreciable.

Dipti Joshi : did you get any solution ? or if any other method followed to start the instrument from the app ?