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