我的意见是在单元测试阶段尽量用目测法,只有在需要经常地反复测试的地方,才应用自动化测试。所以,按此推出,在出版本后、版本验证之前最适合对界面使用自动化测试。
由于界面测试自动化工作量非常之大,所以我们没有必要对每一个用例都进行自动化测试,我们只需要对功能性的用例,系统性的用例进行自动化测试即可,这样既可以用上自动化测试的好处,也避免了繁重的工作任务。
上面有点扯远了,其实无论是在什么阶段的测试中,自动化总有它的用处,下面就主要说说如何进行界面测试自动化。
其实界面测试的工具已经有不少了,像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掉。
以上整个测试过程无需人工干预,所以自动化程度很高,代价是你要些很多额外的界面测试代码。在目测法和这种自动化方法中如何选择就取决于你的需要了。