Java单元测试进阶之如何进行界面测试(也让界面测试自动化起来)

  • Post author:
  • Post category:java


上一篇文章讲到在单元测试阶段可以用目测法完成大部分的界面测试,并论述了在单元测试阶段对界面进行自动化测试的困难性。那么界面的自动化测试就真的没有必要做吗,毕竟界面的自动化测试工作量大,处理复杂,弄不好就是阶段延期。

我的意见是在单元测试阶段尽量用目测法,只有在需要经常地反复测试的地方,才应用自动化测试。所以,按此推出,在出版本后、版本验证之前最适合对界面使用自动化测试。

由于界面测试自动化工作量非常之大,所以我们没有必要对每一个用例都进行自动化测试,我们只需要对功能性的用例,系统性的用例进行自动化测试即可,这样既可以用上自动化测试的好处,也避免了繁重的工作任务。

上面有点扯远了,其实无论是在什么阶段的测试中,自动化总有它的用处,下面就主要说说如何进行界面测试自动化。

其实界面测试的工具已经有不少了,像JFCUnit和Jemmy,我比较喜欢Jemmy,就因为它够简洁,易用。下面看看Jemmy结合JUnit的例子:

被测试的ui类:




/**


**********************************************************


* 项目名称:lhjTest


* 文件名称:CoolUiClass.java


* 文件描述:CoolUiClass.java


* 作者:Administrator


* 创建日期:2007-3-24


* 修改记录:


**********************************************************


*/







package


org.lhj.cool.uiunit;






import


java.awt.Dimension;




import


java.awt.GridBagConstraints;




import


java.awt.GridBagLayout;




import


java.awt.Insets;




import


java.awt.event.ActionEvent;




import


java.awt.event.ActionListener;






import


javax.swing.JButton;




import


javax.swing.JFrame;




import


javax.swing.JPanel;




import


javax.swing.JScrollPane;




import


javax.swing.JTextArea;







/**




*


@author


Administrator




*/







public




class


CoolUiClass


extends


JPanel





{





private


JTextArea msgTxt


=




new


JTextArea(


400


,


320


);






private


JButton coolBtn


=




new


JButton(





Cool





);






public


CoolUiClass()





{





this


.setLayout(


new


GridBagLayout());




this


.setMinimumSize(


new


Dimension(


400


,


350


));




this


.setPreferredSize(


new


Dimension(


400


,


350


));




coolBtn.setMinimumSize(


new


Dimension(


80


,


21


));


coolBtn.setPreferredSize(


new


Dimension(


80


,


21


));




JScrollPane scrollPane


=




new


JScrollPane(msgTxt);


scrollPane.setMinimumSize(


new


Dimension(


400


,


320


));


scrollPane.setPreferredSize(


new


Dimension(


400


,


320


));






this


.add(scrollPane,


new


GridBagConstraints(


0


,


0


,


1


,


1


,


0.0


,


0.0


, GridBagConstraints.CENTER, GridBagConstraints.BOTH,


new


Insets(


5


,


5


,


5


,


5


),


0


,


0


));




this


.add(coolBtn,


new


GridBagConstraints(


0


,


1


,


1


,


1


,


0.0


,


0.0


, GridBagConstraints.CENTER, GridBagConstraints.NONE,


new


Insets(


5


,


5


,


5


,


5


),


0


,


0


));




coolBtn.addActionListener(


new


ActionListener()





{







public




void


actionPerformed(ActionEvent arg0)





{



appendText();


}







}



);


}









protected




void


appendText()





{



msgTxt.append(





cool





);


}










/**




* test the calss in main,use your eye to test.


*


@param


args




*/







public




static




void


main(String[] args)





{



JFrame frm


=




new


JFrame(





CoolUiClass





);


frm.getContentPane().add(


new


CoolUiClass());


frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);


frm.pack();


frm.setVisible(


true


);


}







}





测试类:




/**


**********************************************************


* Project Name: lhjTest


* File Name   : CoolUiClassJTest.java


* File Desc   : CoolUiClassJTest.java


* Author      : Administrator


* Create      : 2007-3-25


* Modify:


**********************************************************


*/







package


org.lhj.cool.uiunit;






import


java.awt.Dimension;






import


javax.swing.JFrame;






import


junit.framework.TestCase;






import


org.lhj.cool.uiunit.CoolUiClass;




import


org.netbeans.jemmy.operators.JButtonOperator;




import


org.netbeans.jemmy.operators.JFrameOperator;




import


org.netbeans.jemmy.operators.JTextAreaOperator;







/**




*


@author


Administrator




*/







public




class


CoolUiClassJTest


extends


TestCase





{





private


JFrame frm;






private


JFrameOperator frmOpr;







/*


(non-Javadoc)


* @see junit.framework.TestCase#setUp()




*/







protected




void


setUp()


throws


Exception





{





super


.setUp();




frm


=




new


JFrame(





CoolUiClassTest





);


frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);


frm.setSize(


new


Dimension(


400


,


320


));


frm.getContentPane().add(


new


CoolUiClass());


frm.pack();


frm.setVisible(


true


);




frmOpr


=




new


JFrameOperator(





CoolUiClassTest





);


}










/*


(non-Javadoc)


* @see junit.framework.TestCase#tearDown()




*/







protected




void


tearDown()


throws


Exception





{



frmOpr.dispose();






super


.tearDown();


}









public




void


testUi()





{



JTextAreaOperator txtOpr


=




new


JTextAreaOperator(frmOpr,


0


);




assertEquals(


“”


, txtOpr.getText());




txtOpr.append(





abcde





);




assertEquals(





abcde





, txtOpr.getText());




txtOpr.clearText();




assertEquals(


“”


, txtOpr.getText());




JButtonOperator btnOpr


=




new


JButtonOperator(frmOpr,





Cool





);


btnOpr.doClick();




assertEquals(





cool





, txtOpr.getText());




txtOpr.append(





cool





);




assertEquals(





cool cool





, txtOpr.getText());


}







}





从上面可以看出,Jemmy的使用跟对界面的操作是一样的,好比我们是在直接地对界面控件进行操作一样,只不过Jemmy的控件都是以Operator结尾的。

谈谈测试步骤:

1、在setUp中,我创建了一个JFrame,然后把需要测试的面板加上去并显示,记得一定要现调用显示,要不然后面JFrameOperator在new的时候会一直等待返回。

2、创建JFrameOperator,参数为刚才创建JFrame时的参数,即标题,创建的JFrameOperator相当于指定JFrame的代理,以后对JFrameOperator的所有操作就相当于对JFrame进行操作。

3、以建立的JFrameOperator为参数之一,另一个参数是同类型控件的索引(例如上面的0代表JFrame里面的第一个JTextArea),或者是同类型控件的Text(例如上面的“Cool”就是JFrame里面Text为“Cool”的JButton,这里不能用控件的name属性,我试过,结果是找不着的,大家不妨试试看。),创建相应类型的控件。以后对该对象进行的操作也相当于对实际的控件进行操作一样。

4、从现在就可以操作界面了,对于JTextAreaOperator,可以像使用JTextArea一样进行操作,如上面的getText,append,clear;对于JButtonOperator,除了可以使用JButton的功能外,还可以调用doClick以模拟按钮点击事件。

5、最后可以使用JUnit的assert系列函数进行测试。

6、在tearDown函数中,记得调用JFrameOperator的dispose方法关闭窗口

7、运行该测试,运行过程和结果跟运行JUnit的TestCase是一样的,只不过在运行过程当中会显示一个对话框,等测试结束后这个对话框也会自动的dispose掉。

以上整个测试过程无需人工干预,所以自动化程度很高,代价是你要些很多额外的界面测试代码。在目测法和这种自动化方法中如何选择就取决于你的需要了。