The Source for Java Technology Collaboration
User: Password:



Alexey Popov's Blog

July 2007 Archives


Mobile JUnit and absence of reflection.

Posted by alexeyp on July 14, 2007 at 04:52 AM | Permalink | Comments (0)

In classical JUnit you have multiple test methods in a single class that match some pattern, test framework iterates through these methods using relection. CLDC/MIDP does not have reflection API, this is one of problems that need to be solved when adopting JUnit-like test frameworks to CLDC/MIDP. 

There are not too many solutions to this problem, well described in Vladimir's blog. I would like to add few words and will describe how we deal with this problem using ME Framework at Sun.

I like the elegant solution implemented in Sony Ericsson Mobile JUnit 1.0. Absence of reflection in CLDC (client side) sometimes can be dealt with at server side. In this case, when list of test methods to iterate through is static and not calculated at runtime, you can analyse class files or sources and generate this iterator-launcher method or class.

Another solution is to use preprocessors and code generation.

This is an approach that we use at Sun for compatibility test development for Java ME and Java SE. Test sources are described in a meta language that allows to combine meta data and code. Documentation and .java sources of tests are generated from this source file, as well as code for all calls to individual test methods. Here is the example of a generated launcher method for MultiTest API:

    protected void runTestCases() {
        if (isSelected("Connector2002")) {
            addStatus(Connector2002());
        }
        if (isSelected("Connector2003")) {
            addStatus(Connector2003());
        }
    }

As I wrote once, MultiTest has slightly different API then JUnit but similar principles. It's version for Java SE, that is natively supported by JT harness, uses reflection. Its CLDC-compatible variation, supported by ME Framework, requires this abstract 'runTestCases' method to be defined, in our case it is generated.

There other bonuses of code generation, like sharing compatibility tests across TCKs for Java platform API. We can have Java ME and Java SE versions of tests for the class that exists in both platforms generated from a single source.



ME application testing - MIDlet instantiation

Posted by alexeyp on July 08, 2007 at 03:09 AM | Permalink | 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:

MIDletinstr1.PNG


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.





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds