|
|
JFCUnit实战
JFCUnit介绍 JFCUnit使得你能够为Java偏移应用程序编写测试例子。它为从用代码打开的窗口上获得句柄提供了支持;为在一个部件层次定位部件提供支持;为在部件中发起事件(例如按一个按钮)以及以线程安全方式处理部件测试提供支持。JFCunit的基本测试思路是:它提供了很多方法,可以用来模拟许多本应由传统测试人员手工进行的触发事件,如:点击按钮,给文本框输入字符或数字,鼠标双击事件等,从而实现了测试的自动化。这一优点在需用户输入大量信息的界面测试中显的尤为重要。实际上JFCUnit的测试用例十分像RobotJ中的脚本的编写,使用熟练后对于自动化大批量测试十分有意义。 更加详细的介绍可以参考本人前面贴过的相关主题“ZT:JUNIT用于界面测试中的增强版JFCunit,建议用其进行界面单元测试”,这里不再敷诉。 使用示例 以下是一个具体实例,测试对象是一个Jdialog,界面效果如下: 我们设计的测试目的是: 1、 检查界面上是否存在各个设计组件; 2、 在用户名和密码为空的情况下,模拟点击确定按钮事件,是否能在原来的对话框上显示一个错误提示框,提示框的标题为"Login Error"; 即最后显示效果如下: 以下是相关的测试对象代码和测试用例代码。 测试对象代码:
import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.borland.jbcl.layout.*; import java.awt.BorderLayout;
/** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2004</p> * <p>Company: </p> * @author leiwei * @version 1.0 */
public class LoginScreen extends JDialog{ JPanel jPanel1 = new JPanel(); JLabel jLabel1 = new JLabel(); JLabel jLabel2 = new JLabel(); JTextField LoginNameTextField = new JTextField(); JButton EnterButton = new JButton(); JButton ExitButton = new JButton(); BorderLayout borderLayout1 = new BorderLayout(); JPasswordField PasswordTextField = new JPasswordField(); String title =""; private GridBagLayout gridBagLayout1 = new GridBagLayout(); public LoginScreen(String ititle) { try { jbInit(); super.setTitle(ititle); } catch(Exception e) { e.printStackTrace(); }
} private void jbInit() throws Exception { this.setName("loginScreen"); this.setTitle(title); this.setBounds(300,300,300,300); jLabel2.setFont(new java.awt.Font("Dialog", 0, 13)); jLabel2.setText("密 码:"); jLabel1.setFont(new java.awt.Font("Dialog", 0, 13)); jLabel1.setText("用户名:"); jPanel1.setLayout(gridBagLayout1); this.getContentPane().setLayout(borderLayout1); EnterButton.setFont(new java.awt.Font("Dialog", 0, 12)); EnterButton.setText("确定"); EnterButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { EnterButton_actionPerformed(e); } }); ExitButton.setFont(new java.awt.Font("Dialog", 0, 12)); ExitButton.setText("取消"); ExitButton.addActionListener(new java.awt.event.ActionListener(){ public void actionPerformed(ActionEvent e) { ExitButton_actionPerformed(e); } }); LoginNameTextField.setText(""); PasswordTextField.setText(""); jPanel1.add(jLabel1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(52, 49, 0, 0), 0, 0)); jPanel1.add(LoginNameTextField, new GridBagConstraints(1, 0, 2, 1, 1.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(52, 7, 0, 73), 214, 0)); jPanel1.add(PasswordTextField, new GridBagConstraints(1, 1, 2, 1, 1.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(17, 7, 0, 73), 214, 0)); jPanel1.add(jLabel2, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0 ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(19, 49, 0, 7), 0, 0)); jPanel1.add(EnterButton, new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(35, 88, 62, 0), 12, 0)); jPanel1.add(ExitButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(38, 91, 62, 73), 13, 0)); this.getContentPane().add(jPanel1, BorderLayout.CENTER,0); this.pack(); ExitButton.setName("ExitButton"); EnterButton.setName("EnterButton"); LoginNameTextField.setName("LoginNameTextField"); PasswordTextField.setName("PasswordTextField"); }
public void show(){ super.show(); } public static void main(String args[]){ JDialog dialog = new LoginScreen("loginScreen"); dialog.show(); }
void ExitButton_actionPerformed(ActionEvent e) { System.exit(0); }
void EnterButton_actionPerformed(ActionEvent e) { if(this.PasswordTextField.getPassword().length == 0){ javax.swing.JOptionPane.showMessageDialog(this,"Login Error","Login Error",JOptionPane.ERROR_MESSAGE); } } }
测试用例代码:
import java.util.*;
import javax.swing.*;
import junit.extensions.jfcunit.*; import junit.extensions.jfcunit.eventdata.*; import junit.framework.*; import org.apache.regexp.*;
/** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c) 2004</p> * <p>Company: </p> * @author leiwei * @version 1.0 */
public class LoginScreenTest extends JFCTestCase {
private LoginScreen loginScreen = null; private TestHelper helper = null;
public LoginScreenTest(String name) { super(name); }
protected void setUp() throws Exception { super.setUp(); helper = new JFCTestHelper(); loginScreen = new LoginScreen("LoginScreenTest: " + getName()); loginScreen.setVisible(true); }
protected void tearDown() throws Exception { loginScreen = null; helper.cleanUp(this); super.tearDown(); }
public void testUI() { JDialog dialog;
JButton exitButton = (JButton) helper.findNamedComponent("ExitButton", loginScreen, 0); assertNotNull("Could not find the Exit button", exitButton);
JButton enterButton = (JButton) helper.findNamedComponent("EnterButton", loginScreen, 0); assertNotNull("Could not find the Enter button", enterButton);
JTextField userNameField = (JTextField) helper.findNamedComponent( "LoginNameTextField", loginScreen, 0); assertNotNull("Could not find the userNameField", userNameField);
assertEquals("Username field is empty", "", userNameField.getText());
JTextField passwordField = (JTextField) helper.findNamedComponent( "PasswordTextField", loginScreen, 0); assertNotNull("Could not find the passwordField", passwordField);
assertEquals("Password field is empty", "", passwordField.getText());
try { helper.enterClickAndLeave(new MouseEventData(this, enterButton)); } catch (Exception ex) { ex.printStackTrace(); }
List showingDialogs = helper.getShowingDialogs(loginScreen); assertEquals("Number of dialogs showing is wrong", 2, showingDialogs.size());
dialog = (JDialog) showingDialogs.get(1); assertEquals("Wrong dialog showing up", "Login Error", dialog.getTitle());
helper.disposeWindow(dialog, this); }
public static Test suite() { return new TestSuite(LoginScreenTest.class); }
public void TestUI(){}
public static void main(String args[]) { junit.textui.TestRunner.run(suite());
}
}
小结 1、 JFCUnit的基本框架与原理与Junit一样,其实从实现上是完全基于Junit,是Junit在GUI界面测试上的有效扩展。 2、 JFCUnit功能十分强大,擅长对象实例检查,各种人机界面响应事件的模拟,便于功能性检查。 3、 JFCUnit不善于界面布局,美观方面的检查,看来人工测试还是不可缺少的。 4、 JFCUnit中对对象进行测试的基础是获得测试对象实例,关键是find…Component系列API的应用,具体查找主要基于两个方面,对象组件的“Name”属性和在容器中的Index,而这两种方式都不是很直观,具体使用何种方式也很大程度上取决于开发人员的编码,具体使用时有一定难度和局限性。 5、 JFCUnit还有很多深入用法,比如支持GUI测试的多线程方法,支持XML方式测试,以后有时间再与大家分享。 6、 由于相关资料比较缺乏,很多测试经验完全是个人摸索得来,希望以后有人做更深入的研究。
相关资料 【1】 http://sourceforge.net/ 【2】 http://epoxy.mrs.umn.edu/ 【3】 《JFCunit 在单元测试中的应用》
|
|