使用Abbot给Java Swing写单元测试,遇到这样一个问题:如果用到了showDialog(...)方法,由于是ModelDialog,系统执行到这里就被block了,无法通过Abbot写单元测试。
举个简单的例子来说:Frame中有个button,点击后会显示JColorChooser Dialog,选取颜色后点击OK或者Cancel按钮,Dialog消失,同时返回Color对象,然后就可以在frame中修改Label的颜色。
所以想象中的单元测试应该是这样:
@Test
public void testSelectColorRedAndClickOKButton() throws Exception {
FrameDemo demo = new FrameDemo();
demo.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
demo.pack();
demo.setVisible(true);
JButton colorButton = (JButton) getFinder().find(demo, new ClassMatcher(JButton.class))
new JMenuItemTester().actionClick(colorButton);//1. Here will block after JColorChooser shows
// 2. Some action to select color red: JColorChooserTester().actionSelectColor(Color.red)
JLabel label = (JLabel) getFinder().find(demo, new ClassMatcher(JButton.class))
assertEquals(Color.red, label.getForeground());
}
类FrameDemo很简单:
public class FrameDemo extends JFrame{
public void FrameDemo(){
JLabel label = new JLabel("Text color will change after you select new color");
label.setForeground(Color.black);
JButton colorButton = new JButton("Choose Color...");
JPanel panel = new JPanel();
panel.add(label);
panel.add(colorButton);
this.setContentPane(panel);
}
}
但是有两个问题:
1.注释1所在地方,当JColorChooser Dialog显示之后线程就被block了;
2.Abbot中没有类JColorChooserTester帮助选择颜色。
根据以上考虑,决定自己写一个JColorChooserTester,完成以下功能:
1.根据输入选择颜色,并点击OK按钮关闭对话框;
2.可以不选取颜色直接点击Cancel按钮关闭对话框;
3.应该在显示对话框之前就调用该方法。
根据这些分析,对上面的测试做了修改:
@Test
public void testSelectColorRedAndClickOKButton() throws Exception {
FrameDemo demo = new FrameDemo();
demo.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
demo.pack();
demo.setVisible(true);
JButton colorButton = (JButton) getFinder().find(demo, new ClassMatcher(JButton.class));
new JColorChooserTester().actionSelectColor(demo, Color.red);// We want dialog to return red
new JMenuItemTester().actionClick(colorButton);
JLabel label = (JLabel) getFinder().find(demo, new ClassMatcher(JButton.class));
assertEquals(Color.red, label.getForeground());
}
测试写完了,接下来就写JColorChooserTester类,上面的测试能够通过,并经过简单的重构后:
package com.tw.ui.tester;
import abbot.finder.BasicFinder;
import abbot.finder.Matcher;
import abbot.finder.ComponentNotFoundException;
import abbot.finder.MultipleComponentsFoundException;
import abbot.finder.matchers.ClassMatcher;
import abbot.tester.JComponentTester;
import abbot.tester.JMenuItemTester;
import javax.swing.*;
import java.awt.*;
import org.apache.log4j.Logger;
public class JColorChooserTester extends JComponentTester {
private static final long DEFAULT_TIME_OUT_IN_MILLISECONDS = 5000;
private long waitInMilliSeconds;
private Logger logger = Logger.getLogger(JColorChooserTester.class);
public JColorChooserTester() {
this(DEFAULT_TIME_OUT_IN_MILLISECONDS);
}
public JColorChooserTester(long waitInMilliSeconds) {
this.waitInMilliSeconds = waitInMilliSeconds;
}
public void actionClickCancel(final Container container) {
final JColorChooserFinder chooserFinder = new JColorChooserFinder(container);
Thread thread = new Thread(){
public void run(){
new JMenuItemTester().actionClick(chooserFinder.getCancelButton());
}
};
thread.start();
}
public void actionSelectColor(Container container, final Color returnedColor) {
final JColorChooserFinder chooserFinder = new JColorChooserFinder(container);
Thread thread = new Thread(){
public void run(){
chooserFinder.getColorChooser().setColor(returnedColor);
new JMenuItemTester().actionClick(chooserFinder.getOKButton());
}
};
thread.start();
}
class JColorChooserFinder {
JColorChooser colorChooser;
JButton cancelButton;
JButton okButton;
private boolean shouldWaitForDialog = true;
long start = System.currentTimeMillis();
public JColorChooserFinder(Container container) {
FindDialog(container);
}
private void FindDialog(final Container container) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JDialog dialog = waitAndFindDialog(container);
if (dialog != null) {
logger.debug("Find JColorChooser Dialog.");
cancelButton = findCancelButton(dialog);
okButton = findOKButton(dialog);
colorChooser = findColorChooser(dialog);
}
} catch (Exception e) {
}
finally {
shouldWaitForDialog = false;
}
}
});
}
private JDialog waitAndFindDialog(final Container container) {
JDialog dialog = null;
long waited = 0;
while (dialog == null && shouldWaitMore(waited)) {
try {
dialog = (JDialog) new BasicFinder().find(container, new ClassMatcher(JDialog.class));
} catch (ComponentNotFoundException e) {
} catch (MultipleComponentsFoundException e) {
logger.debug("Found multiple JDialogs");
break;
}
waited += waitMore(500);
}
return dialog;
}
public JButton getCancelButton() {
long waited = 0;
while (shouldWaitForDialog && shouldWaitMore(waited)) {
waited += waitMore(500);
}
return cancelButton;
}
private long waitMore(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
return millis;
}
public JButton getOKButton() {
long waited = 0;
while (shouldWaitForDialog && shouldWaitMore(waited)) {
waited += waitMore(500);
}
return okButton;
}
public JColorChooser getColorChooser() {
long waited = 0;
while (shouldWaitForDialog && shouldWaitMore(waited)) {
waited += waitMore(500);
}
return colorChooser;
}
private JButton findCancelButton(JDialog dialog) {
return findButtonByText(dialog, UIManager.getString("ColorChooser.cancelText"));
}
private JButton findOKButton(JDialog dialog) {
return findButtonByText(dialog, UIManager.getString("ColorChooser.okText"));
}
private JColorChooser findColorChooser(JDialog dialog) {
try {
return (JColorChooser) new BasicFinder().find(dialog, new ClassMatcher(JColorChooser.class));
} catch (Exception e) {
return null;
}
}
private JButton findButtonByText(JDialog dialog, final String cancelString) {
try {
return (JButton) new BasicFinder().find(dialog, new Matcher() {
public boolean matches(Component component) {
return component.getClass().equals(JButton.class) && ((JButton) component).getText().equals(cancelString);
}
});
} catch (Exception e) {
return null;
}
}
private boolean shouldWaitMore(long waited) {
return waited < waitInMilliSeconds;
}
}
}
JColorChooserTester的源码和测试代码请见附件。
分享到:
- 2009-10-23 16:53
- 浏览 1290
- 评论(0)
- 论坛回复 / 浏览 (0 / 2006)
- 查看更多
相关推荐
JColorChooser是Swing库提供的一个颜色选择器组件。它允许用户通过图形界面选择颜色,用于设置和调整应用程序中的颜色值。
在Java程序中使用 `JColorChooser`,首先需要导入`javax.swing.JColorChooser` 和 `javax.swing.JFrame` 类。例如: ```java import javax.swing.JColorChooser; import javax.swing.JFrame; ``` 2. **实例化...
在Swing中,对话框是一种特殊的窗口,用于向用户提供临时信息或者需要用户进行交互的情况。自定义对话框则允许开发者根据需求定制对话框的外观和行为,以满足特定的应用场景。 一、Swing中的对话框类型 Swing提供了...
Swing中的组件大多数是从`JComponent`类派生出来的,这意味着它们是轻量级组件(Lightweight Components)。轻量级组件是由纯Java代码实现的,它们不依赖于底层操作系统提供的窗口系统资源,从而提高了性能和跨平台...
在Java Swing中,UI设计和交互是通过各种组件来实现的。本文主要关注四个关键组件:JButton(按钮)、JComboBox(组合框)、JList(下拉列表)和JColorChooser(颜色选择器)。这些组件提供了丰富的用户界面功能,...
首先,Swing中的`JColorChooser`类是用来创建颜色选择对话框的核心。开发者可以使用`JColorChooser.showDialog()`方法来显示一个预设的颜色选择对话框。这个对话框包含了一个调色板,用户可以在其中选取或自定义颜色...
在Java Swing中,你可以创建各种窗口应用程序,包括按钮、文本框、菜单、滚动面板等交互元素。Java Swing 提供了一种模型-视图-控制器(MVC)架构,使得开发桌面应用变得更加简单和灵活。 Java Swing 包含了大量的...
在Swing中,扩展组件是指那些超越了标准组件功能的类,它们提供了更复杂的行为或者更丰富的视觉效果。这些组件通常是基于Java基础组件,如JButton、JLabel和JTable等进行增强,以满足特定的用户需求。 例如,"Table...
在Swing中,你可以创建复杂的、功能丰富的桌面应用程序,包括窗口、菜单、按钮、文本框等组件。Swing提供了丰富的可定制性,允许开发者通过调整外观和行为来满足特定需求。 Swing的学习主要涵盖以下几个核心知识点...
Border对象是Swing中的一种基本组件,用于设置组件的边框。Border对象可以是各种不同的边框样式,例如BevelBorder、LineBorder、EmptyBorder、EtchedBorder、TitledBorder等。这些边框可以单独使用,也可以组合使用...
2. **布局管理器**:如FlowLayout、BorderLayout、GridLayout、CardLayout以及各种复合布局的使用,帮助理解如何在Swing中组织组件。 3. **模型-视图-控制器(MVC)**:Swing是如何遵循这一设计模式的,以及如何...
至于标签"水平",在Java Swing中,我们可以使用`BoxLayout`布局管理器来实现水平排列的组件。例如,如果你希望在颜色选择面板旁边还有其他组件,并保持水平排列,可以这样做: ```java JPanel panel = new JPanel...
Java Swing 是Java编程语言中用于构建图形用户界面(GUI)的一个强大的工具包。它是对早期的Abstract Window Toolkit (AWT) 的扩展,提供了更丰富的功能和更好的平台独立性。Swing 包含了大量的组件,使得开发者可以...
Swing学习系列是Java开发中的一个重要部分,它是一种用于构建桌面应用程序的图形用户界面(GUI)工具包。这篇Swing读书笔记目录旨在帮助开发者更好地理解和掌握Swing的相关知识,通过阅读和学习,可以提升在Java GUI...
2. **容器与布局管理器**:在Swing中,JFrame是主窗口,它可包含多个组件。容器(如JPanel)用于组织和管理这些组件,而布局管理器(如FlowLayout、BorderLayout、GridLayout、CardLayout和GridBagLayout)则负责...
Swing提供了诸如JOptionPane、JFileChooser和JColorChooser等对话框,方便进行警告、确认、选择文件或颜色等操作。 9. **Swing工具包(Swing Utilities)**: 提供了一些实用方法,如静态方法`SwingUtilities....
2. **事件处理**:Swing中的事件模型基于观察者模式,事件监听器接口(如ActionListener、MouseListener和KeyListener)用于响应用户的交互操作。学习如何添加监听器并编写事件处理方法是Swing编程的关键。 3. **...
3. **Chapter05**:可能会讨论Swing中的菜单和工具栏设计,包括JMenu、JMenuBar、JMenuItem和JToolBar的用法。 4. **Chapter06**:可能涉及对话框(JOptionPane)、文件选择对话框(JFileChooser)和颜色选择对话框...
5. **对话框和通知**:Swing提供了各种对话框(JOptionPane)和通知组件(JOptionPane、JFileChooser、JColorChooser等)来增强用户交互。 6. **国际化支持**:Swing内置了对多语言支持的功能,开发者可以通过...
- `JFrame`、`JDialog`、`JWindow`和`JApplet`等属于此类,它们是Swing中的特殊组件,虽然也继承自`JRootPane`,但它们的绘制需要使用本地系统资源。这是因为它们代表了窗口级别的组件,必须与底层操作系统进行交互...