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