 |
ME application testing - MIDlet instantiation
Posted by alexeyp on July 08, 2007 at 03:09 AM | Comments (2)
The very common problem people meet when trying to unit-test
their
MIDlets is that you generally can not do something like this:
public
class MyTest
extends
TestCase {
public
void test() {
MyMIDletApplication myma = new MyMIDletApplication();
assertEquals("Never get here", 7, 8);
}
}
MIDP spec prohibits calling MIDlet constructor from
application
code, for
security reasons MIDlet can be instantiated only by AMS, Application
Management
Software. All MIDP xUnit-like test frameworks, I am aware of, assume
that test execution is done by a special utility MIDlet, lets call it
MIDletTester, for example. Since it is not possible to get instance
of your application MIDlet class from the MIDletTester, unit
testing should be limited to library classes.
Here are couple of ideas, we consider implementing some of
them for
ME
Framework.
Provisioning server and instrumentation
Ideally, testing should be done on the instance, that runs in
the
environment, that is closest to real. Though you have to test every
unit of the program in isolation, it would also
be useful to have possibility to execute some tests on the MIDP
application, that is packaged and instantiated in a regular way, not on
library classes, packaged with your test application.
This can be done by adding hooks to the application, where you
can
embed your tests. This approach will require the control over the
application code, may
not always be possible.
If you supply minimalistic xUnit-like test framework with a
server,
responsible for packaging and provisioning of the test
application, you can implement a solution for this and for some other
MIDP-specific testing problem by using instrumentation of the compiled
application class files to embed whatever hooks you need. Check the
picture:
You need to modify the MIDlet class of your application under test with:
- one or many methods, that will run tests. For
example instantiate a test
class by a classname and call its methods.
- for each test to pass its classname, for example hardcode
to
the newly generated method or in a resource file
- add a mechanizm to call these methods.
Interesting question is where calling of a test method makes sense. I
think having a UI for it, a Command is not a good idea - after all we
do all this so that testers click mouse less. Placing it into
any specific place in startRun may not work well ... may be I want
this MIDlet instance after startRun was called by AMS.
Potential approach here would be to rename all
MIDlet
methods that can be called by AMS and replace them with testing hook
methods. Allow to bypass them or call original MIDlet methods from
them. MIDlet.startUp method after instrumentation may look like:
public final void
startApp()
{
test_startUp_preconditions();
_original_startUp();
test_startUp_postconditions();
}
Any comments will be appreciated.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Parts of your article are unclear to me -- regardless, I wonder why you wouldn't package your app code and test code as separate MIDlets in a single suite... if done correctly, you could then call the app code from the test code for testing purposes without polluting your app code with test code. Also, the size of your deployed (probably obfuscated) MIDlet would be reduced. Even with obfuscation, one goal should be to reduce extraneous code in any mobile application. Agreed?
Regards,
Evan J. Goff
Posted by: evan_j_goff on July 13, 2007 at 12:59 PM
-
Hi Evan
thank you for the comment and questions, sorry that I was not completely clear
The approach you describe is the one that is used for this purpose now. When two midlets are packaged into a single MIDlet suite, we can launch one (test) MIDlet and access all classes in the MIDlet suite from the running MIDlet
This has two limitations and proposed approach with instrumentation is a potential solution:
Doing so will not allow you to instantiate one MIDlet from another - calling new MIDlet() will result in SecurityException.
this can not be used for automation of functional testing where you need application under test to be launched by AMS and go through full application life cycle.
There are non-standard exceptions, like some implementations allow to call new MIDlet from inside of MIDlet constructor, we can not rely on this
I am not aware of a standard way in MIDP2.0 to have multiple MIDlets from the MIDlet suite running simultaneously and access classes of one MIDlet from another.
Completely agree with your point about reducing extraneous code from the application. In the described approach we instrument and repackage class files of the application in the test process only, this modification is applied to already built application by a server, that provisions these applications to test devices. Source code is left unchanged, we modify built MIDlet suite (that may be previously obfuscated).
Thank you
Alexey
Posted by: alexeyp on July 14, 2007 at 03:28 AM
|