Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


JUnit Testing Using Java ME JUnit Frameworks : Page 3

Just because Java Micro Edition lacks reflective capabilities doesn't mean Java Micro Edition developers miss out on the advantages of JUnit styled testing. JUnit-styled frameworks and tools can still improve ME application quality.




Application Security Testing: An Integral Part of DevOps

Working with JMUnit

Setting up JMUnit
After obtaining the JMUnit download, make sure that the two JMUnit .jar files (JMUnit4CLDC10.jar and JMUnit4CLDC11.jar) are available on the classpath for both your Java ME compiler and runtime environment or IDE. The current release of JMUnit is labeled 1.0.2.

JMUnit Test Cases
JMUnit provides two versions of the framework (each version is in its own JAR); one for use with CLDC 1.0 applications and another for CLDC 1.1 applications where floating point primitives are supported. In customary JUnit fashion, the first step to creating appropriate unit tests using JMUnit is to create a test case. To create a test case in JMUnit, you must create a new test case class that either extends JMUnit's jmunit.framework.cldc10.TestCase or jmunit.framework.cldc11.TestCase. As the package names suggest, one provides support for 1.0 and the other 1.1 versions of CLDC. The only difference is that the cldc11.TestCase implementation of assertEquals() and assertNotEquals() methods (see below) support Java floating-point primitives.

By JUnit convention, a test case class should contain the name of the class to test and end with "Test." Therefore, a JMUnit test case to test the simple CLDC 1.1 version of the temperature conversion class above would be defined like this:

public class TemperatureConversionTest extends jmunit.framework.cldc11.TestCase {}

All test methods must be in a test case class. Again, by convention, test method names begin with "test" and then are named after the methods in the class being tested. For example, a test case method to test the fahrenheitToCelsius method should be called testfahrenheitToCelsius. Each test method must "assert" expected results. For those not familiar with JUnit testing, an assertion is a statement which verifies or disproves a programmer's expected results from method execution. JMUnit supports the following assertions:

assertTrue(expression) assertFalse(expression) assertSame(expected,actual) assertNotSame(expected,actual) assertEquals(expected,actual) assertNotEquals(expected,actual) assertNull(object) assertNotNull(object)

In JMUnit, any test method that makes uses of one of these assertion calls must throw AssertionFailedException. The framework uses the exception to identify failed tests. The TemperatureConversionTest class with appropriate test methods would now look something like that listed below.

import jmunit.framework.cldc11.*; public class TemperatureConversionTest extends TestCase { public void testfahrenheitToCelsius() throws AssertionFailedException{ System.out.println("fahrenheitToCelsius"); float result = TemperatureConversion.fahrenheitToCelsius(66F); assertEquals(18.88889F,result); } public void testcelsiusToFahrenheit() throws AssertionFailedException{ System.out.println("celsiusToFahrenheit"); float result = TemperatureConversion.celsiusToFahrenheit(20F); assertEquals(68F, result); } public void testisHotter() throws AssertionFailedException { System.out.println("isHotter"); assertTrue(TemperatureConversion.isHotter(70F,2F)); } public void testisCooler() throws AssertionFailedException { System.out.println("isCooler"); assertTrue(TemperatureConversion.isCooler(10F,10F)); } }

Per standard JUnit implementation, JMUnit test case abstract classes also provide methods of setup() and tearDown() that can be overridden and used to initialize and then cleanup any objects or resources before and after tests run via the test case. For example, in Java ME applications, setup may be used to open a Record Store before testing and tearDown used to close the Record Store after testing. In addition to setup and tearDown, a fail() method allows a test method to return a test failure no matter what any assert statement indicates. This method is often used in some sort of conditional within a test method or it can be used to stub out undeveloped unit tests as a way of indicating work still to be done.

Test case classes in JMUnit come with a constructor. The constructor for your test case class that extends one of JMUnit's test case classes must call on the super constructor, passing in an integer indicating the number of tests in the test case and a string identifying the test case.

public TemperatureConversionTest() { super(4,"TemperatureConversionTest"); }

The integer indicating the number of tests must match the number of actual tests in the test case. It is important to make sure the number of tests you pass into the constructor matches the actual number of tests in the test case. Its relevance shows up when you look at the test case's test(int testNumber) method.

The test(int testNumber) method in a test case kicks off the test methods. Again, because Java ME is without reflective capabilities, test methods cannot be found and executed automatically as in JUnit. So each test method must be added to a switch statement in the test method and invoked based on a test number. In the case of the TemperatureConversionTest, the test method would look like code below:

public void test(int testNumber) throws Throwable { switch(testNumber) { case 0:testfahrenheitToCelsius();break; case 1:testcelsiusToFahrenheit();break; case 2:testisHotter();break; case 3:testisCooler();break; default: break; } }

This is the reason why you must provide the number of tests to the test case constructor. At runtime, the JMUnit framework creates an instance of the test case class. The framework invokes each test method of the test case instance in a loop, starting from 0 to one less than the number of tests indicated via the constructor. In this way, each case of the test method's switch statement (and therefore each unit test) gets invoked by the framework. Forgetting to update the test case class constructor when adding a test method to the test case will result in not all the test cases firing.

Because you write the test method, JMUnit differs from, and is perhaps more flexible, than JUnit in the way it allows test methods to execute. With control of the test method, you can write tests that take parameters—something JUnit does not allow (because of reflection). For example, a test method for TemperatureConverstionTest might look like the following:

public void testcelsiusToFahrenheit(float c, float f) throws AssertionFailedException{ System.out.println("celsiusToFahrenheit(float c)"); float result = TemperatureConversion.celsiusToFahrenheit(c); assertEquals(f, result); }

The test method can then use parameters to call on this test method in the switch statement.

public void test(int testNumber) throws Throwable { switch(testNumber) { case 0:testfahrenheitToCelsius();break; case 1:testcelsiusToFahrenheit();break; case 2:testisHotter();break; case 3:testisCooler();break; case 4:testcelsiusToFahrenheit(20F,68F);break; default: break; } }

Figure 1. Executing a Test Case: Executing a JMUnit test suite offers you the option to exit or test the suite. Results of the test suite are shown graphically.
Figure 2. A Failure Test Case: Failure shows up graphically in red when a test case fails.

JMUnit TestSuite
Test suites manage one or more test cases. JMUnit provides two test suite abstract classes (jmunit.framework.cldc10.TestSuite and jmunit.framework.cldc11.TestSuite) which you extend to create a test suite. Again, as with test cases, the type of test suite you should extend depends on which version of CLDC you are using. Use cldc10.TestSuite for CLDC 1.0 applications and use cldc11.TestSuite for CLDC 1.1 applications. Both test suite abstract classes have a constructor that takes a string as a parameter. The string gives the suite a description.

A test suite's only function is to create an instance of all of its test cases and then call on the test method of the test cases. To add a test case to a test suite, use the add(testCase) method when constructing the test suite. An example test suite for the conversion test cases is given below.

import jmunit.framework.cldc11.TestSuite; public class ConversionTestSuite extends TestSuite{ public ConversionTestSuite() { super("All Conversion Tests"); add(new DistanceConversionTest()); add(new TemperatureConversionTest()); }

Figure 3. Failure Test Case Console Output: Textual output in the case of failure indicates which test case failed, why it failed and provides a stack trace to see where it failed.

Executing JMUnit Tests
JMUnit's TestCase and TestSuite abstract classes are sub-classes of MIDlet. This allows you to run either your individual test cases or test suites in an emulator (or, unlikely but possible, a real device). When run on a simulator, each test case or test suite offers two commands: exit and test. Figure 1 depicts execution results of the tests suite described above. Figure 2 shows how failures are displayed.

You will also want to check the console when executing tests (see Figure 3). Failures, in particular, are better documented in the console output. Failure output includes stack trace information along with actual and expected values from the test. This might be one of the features regarding JMUnit that will disappoint you a little in comparison to J2MEUnit discussed next. Instead of console output, test case failures are actually displayed on the emulation device in J2MEUnit.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date