Skip to main content

Mobile JUnit and absence of reflection.

Posted by alexeyp on July 14, 2007 at 4:52 AM PDT

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 href="http://blog.emptyway.com/2007/04/05/comparison-of-java-me-unit-testing-frameworks/">Vladimir's
blog. I would like to add few words and will describe how we
deal
with this problem using href="http://cqme.dev.java.net/framework.html">ME Framework
at Sun.

I like the elegant solution implemented in href="http://developer.sonyericsson.com/site/global/newsandevents/latestnews/newsjuly06/p_mobile_juint1.0_javame_cldc.jsp"
onclick="javascript:urchinTracker('/outbound/developer.sonyericsson.com/site/global/newsandevents/latestnews/newsjuly06/p_mobile_juint1.0_javame_cldc.jsp'); javascript:urchinTracker('/outbound/developer.sonyericsson.com/site/global/newsandevents/latestnews/newsjuly06/p_mobile_juint1.0_javame_cldc.jsp');">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 href="http://www.w3.org/TR/test-metadata/">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 href="http://weblogs.java.net/blog/alexeyp/archive/2007/03/test_harness_an.html">wrote
once, MultiTest has slightly different API then JUnit but similar
principles. It's href="http://fisheye4.cenqua.com/browse/jtharness/trunk/code/src/com/sun/javatest/lib/MultiTest.java?r=195">version
for Java SE, that is natively supported by href="http://jtharness.dev.java.net">JT harness,
uses reflection. Its href="http://fisheye4.cenqua.com/browse/cqme/trunk/code/src/share/classes/com/sun/tck/cldc/lib/MultiTest.java?r=230">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.

Related Topics >>