专利名称:针对Java ME软件中MIDlet主类的测试方法
技术领域:
本发明涉及一种嵌入式软件测试方法,尤其涉及一种Java ME嵌入式软件 中的MIDlet主类的测试方法。
背景技术:
Java ME (Java Micro Edition),也被称作J2ME,是为机顶盒、移动电话 和PDA之类的嵌入式消费电子设备提供的高度优化的Java语言平台。MIDlet是 一种运行在符合MIDP规范的设备上的Java ME应用程序,是当前主要的一种Java ME应用程序类型。目前支持Java的手机都支持MIDlet 。 一个MIDlet包括至少 一个派生自MIDP定义的抽象类javax. microedition. midlet. MIDlet的Java类, 我们称此Java类为MIDlet主类。
xUnit是编写软件测试用例最常用的框架。实际上,它是适用于不同编程语 言和不同应用目的的一组测试框架,其中JUnit是应用最广泛的基于xUnit的 Java测试框架,但是该框架不能直接用在Java ME环境,因为Java ME不支持 反射API,而反射API正是JUnit必需用到的。人们做了大量工作将JUnit移植 到Java ME领域,其中主要有J2MEUnit和JMUnit和Mobi 1 e JUnit三种,而JMUni t 更以它的高效、易用、简单和开源等优良特性成为移动程序开发者的首选。
然而,目前基于这些流行的Java ME测试框架编写的测试用例都存在一个 很难解决的问题,就是都无法对MIDlet主类进行完整测试。因为对MIDlet主 类实现测试,最大的障碍在于MIDlet实例化的问题,由于当前MIDP规范不允 许在应用程序中实例化MIDlet (只有AMS——虚拟机层面才有这样的授权)。因 此当前Java ME程序的测试用例都是针对非MIDlet类建立,都在回避MIDlet 主类测试的问题。因而也直接影响了 MIDlet应用程序测试的完整性。在当前最 流行的Java ME测试框架JMUnit中,实现一种对MIDlet主类进行完整测试的 方法具有积极的意义,也是急需解决的问题。
发明内容
本发明针对以上问题的提出,而研制一种针对Java ME嵌入式软件中的 MIDlet主类的测试方法。它通过建立MIDlet主类的常规测试类与特殊测试类相结合的方式,实现对MIDlet主类的测试;特殊测试类是通过对MIDlet主类做源代码插装,实现保留MIDlet类身份的同时又成为一个TestCase类,将测试方法和原方法放在同一个类中,不需在测试方法中对被测类做实例化,而且可以方便地对私有方法写测试,也可以实现对MIDlet主类中用户界面相关的方法写测试;通过定制TestSuite类,可以将MIDlet主类的各种测试类与其他类的测试类统一管理。其具体实现技术手段如下
一种Java ME嵌入式软件中的MIDlet主类的测试方法,其特征是,包括以下步骤
a、 首先,按JMUnit测试框架中建立常规TestCase类的方式,生成一个或多个针对MIDlet主类的常规TestCase类;
b、 然后,在对MIDlet主类做备份的情况下,将MIDlet主类做源代码插装,使之成为JMUnit框架下的特殊TestCase类;
c、 建立TestSuite类,将上述两步骤建好的两种TestCase类以及其他类的TestCase类加入TestSuite中统一管理;
d、 以启动MIDlet的方式运行前面得到的TestSuite类进行测试。步骤a的实现方式如下步骤
(1) 要在TestCase类的构造方法中得到MIDlet主类的一个实例对象;
(2) TestCase类中的各个测试方法均要引用(1)中得到的实例对象对主类进行测试。
所述步骤b的具体步骤如下
(1) 将MIDlet主类做备份;
(2) 修改原MIDlet主类的父类为TestCase类;
(3) 在保留MIDlet主类的构造方法体内容的基础上,在构造方法体内添加对父类TestCase类构造方法的调用;
(4) 将MIDlet主类中的生命周期相关的方法更名;
(5) 在MIDlet主类中添加各个测试方法。
所述步骤(5)中,在MIDlet主类中添加的测试方法如下
(1) 添加针对MIDlet主类中的原方法做测试的各个测试方法;
(2) 在遵守JMUnit框架的要求的条件下,实现测试执行的管理方法,并按常规方式实现setUp与tearDown方法;
步骤c中所述TestCase类加入TestSuite中,采用以JMUnit框架中的TestSuite类为父类,定制一个本测试方法中需要的TestSuite类,在该TestSuite类的构造方法体内使用add方法添加前面改造好的TestCase类的实例。
步骤c中所述TestCase类加入TestSuite中,还可以采用JMUnit中缺省的TestSuite类,直接在JAD文件中增加JMUnitTestClasses属性描述各个TestCase类。
本发明实现了一种可对MIDlet主类做完整测试的方法,能够在当前流行的Java ME测试框架JMUnit中实现,不对JMUnit测试框架本身做改动,不影响对其他非MIDlet类做测试,并可将MIDlet主类的测试与非MIDlet类的测试统一管理,可与测试框架无缝集成。本方法可以作为当前测试框架的补充功能,实施简便,可以方便地集成进Eclipse与Netbeans等流行的开发平台中使用。
图1是本发明的实施过程流程图。
图2是在一个在NetBeans平台上的实施结果图。
具体实施例方式
结合图l所示流程图,来说明本发明的具体实现过程。
首先,按JMUnit测试框架中建立常规TestCase类的方式,生成一个针对MIDlet主类的常规TestCase类。
(1) 要在TestCase类的构造方法中得到MIDlet主类的一个实例对象。由于JMUnit测试框架中的TestCase类为一个MIDlet,可以在一个MIDlet的构造方法中得到另一个MIDlet的实例,也只有这样才能得到可在程序中操纵的一个MIDlet实例;
(2) TestCase类中的各个测试方法均要引用(1)中得到的实例对象对主类进行测试。
这种针对MIDlet主类的TestCase类可以对MIDlet主类中部分非私有方法做测试,可能会有某些简单的MIDlet主类只需要用这种常规的TestCase类去测试即可。但是对一般的MIDlet主类的测试,往往还需要建立下面的特殊TestCase类,以实现对常规难测的方法写测试。
然后,在对MIDlet主类做备份后,将MIDlet主类做源代码插装,使之成为JMUnit框架下的特殊TestCase类。实现既保留MIDlet类的身份又要变成一个TestCase类。
(1) 将MIDlet主类做备份。
(2) 采用向MIDlet主类直接注入代码的方式,而不更改MIDlet主类名,是因为其他类中可能会用到MIDlet主类类名。在MIDlet主类中添加对jmunit类库的导入;然后将MIDlet主类的父类由MIDlet修改为TestCase。由于TestCase类本身是一个MIDlet类,这样也会保留原MIDlet主类的MIDlet身份特征。
(3) 在保留MIDlet主类的构造方法体内容的基础上,在构造方法体内添加对父类TestCase类构造方法的调用,实现本类中测试方法数目和测试类描述信息向测试框架的传递。只需在MIDlet主类的构造方法体内的首行调用super方法(将本类中测试方法数目和测试类的描述信息作为其参数)即可。
(4) 实现既保留原MIDlet主类中的生命周期相关的方法,又要遵从TestCase类的生命周期管理。采取将MIDlet主类中的生命周期相关的方法更名的方式,需要更名的生命周期方法包括startA卯、pauseA卯和destroyApp。
(5) 添加各个测试方法,实现测试执行的管理方法,并根据需要实现setUp方法与tearDown方法。直接在MIDlet主类中添加以下方法
(a) 添加针对MIDlet主类中的原方法做测试的各个测试方法,由于原方法和测试方法在同一个类中,不需在测试方法中对被测类做实例化。可以实现对MIDlet主类中私有方法、用户界面相关的方法等这些难测的方法写测试。
(b) 实现测试执行的管理方法(test方法,其为父类的抽象方法),只要遵守JMUnit框架的要求实现该方法即可。另外,根据需要,可按常规方式实现setUp与tearDown方法。
这样就得到了由MIDlet主类改造来的特殊TestCase类。
然后,建立一个TestSuite类,将前面建好的两种TestCase类加入TestSuite中。如一个Java ME项目中有多个MIDlet主类要测,均可按前面步骤得到相应的TestCase类加入到TestSuite中。另外,如果用户还有其他非MIDlet主类的TestCase类,也可都加入到TestSuite中统一管理。可采用以下两种方式之一。
(1)以JMUnit框架中的TestSuite类为父类,定制一个本测试方法中需要的TestSuite类,在该TestSuite类的构造方法体内使用add方法添加前面改造好的TestCase类的实例。注意只能在TestSuite类的构造方法体内完成以上TestCase的添加。
另外,需要在MIDlet套件属性文件(清单文件和JAD文件)的MIDlet列表项中添加定制好的TestSuite类名。
(2)还可以采用JMUnit框架中缺省的TestSuite类。需要在MIDlet套件属性的MIDlet列表项中添力口加unit. framework, cldclx. TestSuite,并在JAD文件中增加一项属性JMUnitTestClasses,其值为用空格分隔的多个完整的TestCase类名。
最后,在JMUnit框架中运行前面得到的TestSuite类。采用运行TestSuite类的方式而不是直接运行TestCase类的方式,是因为便于管理测试用例,可以将MIDlet主类的测试用例与其他类的测试用例统一管理运行,而且TestSuite运行测试与显示结果的方式更适合测试多线程方法与用户界面相关的方法。
本发明可以在各种常见的开发平台中实施,图l是本方法的实施流程图。下面针对 一 个具体的 MIDlet 项目(含两个 MIDlet 主类calculator. CalculatorM皿et与calculator. AnotherM皿et,并含有一个非MIDlet类math. Arithmetic),以Netbeans 5. x/6. x开发平台(已安装了支持Java ME的Mobility Pack插件)为例,并假定用户选用CLDC11的JMUnit库,详细阐述一下如何用本发明方法在JMUnit框架下对以上三个类都做测试。为了方便,主要以CalculatorMIDlet为例做具体实施说明。
1、在MIDlet项目属性/库与资源项中添加了 CLDC11的JMUnit库后,按JMUnit测试框架中建立常规TestCase类的方式,生成一个针对CalculatorMIDlet类的常规TestCase类,如CalculatorMIDletSimpleTest。用于对CalculatorMIDlet类中的4个简单方法做测试。添加CalculatorMIDlet类型的类变量声明,如 private CalculatorMIDlet instance;在CalculatorMIDletSimpleTest的构造方法中添加实例化CalculatorMIDlet类代码。如
public CalculatorMIDletSimpleTest() {
super (4, "CalculatorMIDlet Conventional Test〃); 〃本类中有4个测试方法instance=new calculator. CalculatorMIDlet (); 〃在此处获取被测MIDlet的实例注只有在以上位置才能得到CalculatorMIDlet的一个实例;CalculatorMIDletTest类中的各个测试方法均要引用以上得到的instance,才能对CalculatorMIDlet中的方法进行测试。
以上常规 TestCase 类 CalculatorMIDletSimpleTest 只适合测CalculatorMIDlet中的4个简单的公有方法,对于其余的6个方法难以测试。因此还需建立特殊TestCase类
2、将MIDlet主类插装成JMUnit框架下的特殊TestCase类。
(1) 对被测的MIDlet主类文件做备份,如对CalculatorMIDlet. Java文件做备份,备份文件名为CalculatorMIDlet. java-orig;
向CalculatorMIDlet类中添加对加unit类库的导入代码import jmunit. framework, cldcll.氺;
(2) 修改该类的父类由extends MIDlet改为extends TestCase。
(3) 由于本类中要建6个测试方法,故在CalculatorMIDlet类的构造方法体内的首行新增以下代码即可
super(6, "CalculatorMIDlet Special Test");
(4) 将CalculatorMIDlet类中原startApp、 pauseApp、 destroyApp方法更名为orig$startApp、 orig$pauseApp、 orig$destroyApp。
(5) 在CalculatorMIDlet类中注入以下方法
(a)由于要对本例中的co腿andAction() 、 origSstartA卯()等6个方法各写一个测试方法,在CalculatorMIDlet类中直接添加testcommandAction()、testorigSstartApp()等6个测试方法。比如原orig$startApp 0方法一部分内容如下
public void orig$startApp() {count = 101;
getDisplay(). setCurrent(get—calculatorForm());
建立它的一个测试方法为
public void testo:rig$sta:rtApp() throws AssertionFailedException {System, out. println(〃startApp〃);int expectedCount = 101;
String expectedTitle 二 "Calculator";
orig$startApp();
assertEquals(expectedCount, count);
assertEquals(expectedTitle, getDisplay(). getCurrent(). getTitle());
原commandAction()方法的一部分内容如下
public void commandAction(Command command, Displayable displayable) {
a二Integer. parselnt(get—field—a(). getString()); b=Integer. parselnt(get一field_b0. getString());
else if (command = addCommand) {
get—resultltem(). setText(Integer. toString(Arithmetic, getlnstance(). add(a, b))); getDisplay(). setCurrent(get—calculatorForm());
建立它的一个测试方法为
public void testcommandAction() throws AssertionFailedExc印tion { System, out. println(〃commandAction〃); String expectedResult = 〃256〃; get—field_a(). setString(〃67〃); get_field_a(). setString(〃189〃); commandAction (addCommaiid, calculatorForm); assertEquals(expectedResult, get—resultltem(). getText());
其他测试方法此不赘述。
(b)实现父类中管理测试执行的抽象方法test(),如下形式:
public void test(irrt testNumber) throws Throwable { switch(testNumber) {case O:testcommandAction();break; case l:testorig$startApp();break; case 2:testget—calculatorForm();break;
case 5:test get—resultltem ();break; default:break;
(c)根据需要实现setUp()与tearDown()方法。本例中这两个方法暂为空。 这样得到的改动后的CalculatorMIDlet类便是一个完整的JMUnit框架中 的TestCase类。
对于本例中的另一个MIDlet类calculator. AnotherMIDlet,由于里面的方 法体都是非常简单的公有方法,只需建立一个常规的测试类即可,如 calculator. AnotherMIDletTest (其中建立4个测试方法)。X寸于本例中的其他 类math. Arithmetic,按照常规方式生成TestCase类即可,比如生成的测试类 名为math. ArithmeticTest (其中建立5个测试方法)。
3.建立一个TestSuite类名为testsuite. MyTestSuite,其主体内容如下
import jmunit. framework, cldcll. TestSuite; public class MyTestSuite extends TestSuite{ public MyTestSuite() {
super(〃My Test Suite〃);
add(new calculator. CalculatorMIDlet());
add(new calculator. CalculatorMIDletSimpleTest());
add(new calculator. AnotherMIDletTest());
add(new math. ArithmeticTest());
两个MIDlet生成的TestCase类和非MIDlet生成的TestCase类都被加入 到MyTestSuite中。
在MIDlet套件属性的MIDlet列表项中添加如下项
名称MyTestSuite类testsuite. MyTestSuite 图标可为空。或者,用户可以选择不定制以上MyTestSuite类,而是直接采用JMUnit框 架中缺省的加unit. framework, cldcll. TestSuite类。只需要在MIDlet套件属 性的MIDlet列表项中添加如下项
名称MyTestSuite 类jmunit. framework, cldcll. TestSuite;
并在JAD属性中增加如下一项
名称JMUnitTestClasses 值以空格分开的本例中的四个TestCase类。 4.在NetBeans中运行本MIDlet项目,便可在手机模拟器启动选项中出现 MyTestSuite项,如图2(a)所示,选择MyTestSuite启动后,出现测试方法运 行前的界面,如图2(b)所示,点击"test"后,三个测试类(两个MIDlet测试 类和一个非MIDlet测试类)中的19个测试方法全部被运行,运行结果如图2(c)。 方法的实施过程可以方便地做成NetBeans的功能插件,便于用户直接使用。另 外在其他开发平台上的实施过程,与以上过程的阐述相类似。
以上所述,仅为本发明较佳的具体实施方式
,但本发明的保护范围并不局 限于此,任何熟悉本技术领域的技术人员在本发明揭露的技术范围内,根据本 发明的技术方案及其发明构思加以等同替换或改变,都应涵盖在本发明的保护 范围之内。
权利要求
1、一种Java ME嵌入式软件中的MIDlet主类的测试方法,其特征是,包括以下步骤a、首先,按JMUnit测试框架中建立常规TestCase类的方式,生成一个或多个针对MIDlet主类的常规TestCase类;b、然后,在对MIDlet主类做备份的情况下,将MIDlet主类做源代码插装,使之成为JMUnit框架下的特殊TestCase类;c、建立TestSuite类,将上述两步骤建好的两种TestCase类以及其他类的TestCase类加入TestSuite中统一管理;d、以启动MIDlet的方式运行前面得到的TestSuite类进行测试。
2、 根据权利要求1所述的一种Java ME嵌入式软件中的MIDlet主类的测试方法,其特征在于步骤a的实现方式有如下步骤(1) 要在TestCase类的构造方法中得到MIDlet主类的实例对象;(2) TestCase类中的各个测试方法均要引用(1)中得到的实例对象对主类进行测试。
3、 根据权利要求1所述的一种Java ME嵌入式软件中的MIDlet主类的测试方法,其特征在于所述步骤b的具体步骤如下(1) 将MIDlet主类做备份;(2) 修改原MIDlet主类的父类为TestCase类;(3) 在保留MIDlet主类的构造方法体内容的基础上,在构造方法体内添加对父类TestCase类构造方法的调用;(4) 将MIDlet主类中的生命周期相关的方法更名;(5) 在MIDlet主类中添加各个测试方法。
全文摘要
本发明公开了一种针对Java ME软件中MIDlet主类的测试方法,它通过建立MIDlet主类的常规测试类与特殊测试类相结合的方式,实现对MIDlet主类的测试;特殊测试类是通过对MIDlet主类做源代码插装,可保留MIDlet类身份的同时又成为一个TestCase类,将测试方法和原方法放在同一个类中,方便地对私有方法写测试,也可以实现对MIDlet主类中用户界面相关的方法写测试;定制TestSuite类,保证MIDlet主类的各种测试类与其他类的测试类统一管理。本发明首次实现了在JMUnit测试框架下对MIDlet主类做完整测试。适于在JavaME移动设备应用程序测试中广泛推广。
文档编号G06F11/36GK101510171SQ200910010899
公开日2009年8月19日 申请日期2009年3月25日 优先权日2009年3月25日
发明者杜振军, 王文军, 王正磊, 荣 陈 申请人:大连海事大学