29

我想为 GUI 编写测试用例。我想知道如何模拟点击JButton,或者如何提取JTable 的元素。

为此,我构建了一个简单的 GUI,如果单击按钮并且 JTextfield 为空,则将计数增加 1,但如果提供了数字,则计数将替换为 JTextfield 中的整数。当然,我想使用 Regex 来确保输入到 JTextfield 中的文本实际上是一个整数,但是让我们假设用户不会乱来输入一个非整数。此外,JLabel 更新当前计数,而 JTable 添加新行。

这是代码:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;


public class sampleGUI extends JFrame implements ActionListener {
    private Integer previous_count;
    private Integer current_count;
    private JButton Button;
    private JTable table;
    private JTextField text;
    private DefaultTableModel model;
    private JScrollPane scroll;
    private JLabel label;

    public sampleGUI() {
        previous_count = null;
        current_count = 0;
        JFrame frame = new JFrame("Sample");
        JPanel panel = new JPanel();

        GroupLayout layout = new GroupLayout(panel);
        panel.setLayout(layout);

        label = new JLabel("Current Count: " + Integer.toString(current_count));
        text = new JTextField(15);
        Button = new JButton("Change the Count!");
        model = new DefaultTableModel();
        model.addColumn("Previous Count");
        model.addColumn("Current Count");
        table = new JTable(model);
        scroll = new JScrollPane(table);

        layout.setHorizontalGroup(layout
                .createParallelGroup(GroupLayout.Alignment.LEADING)
                .addGroup(
                        layout.createSequentialGroup().addComponent(label)
                                .addComponent(text).addComponent(Button))

                .addComponent(scroll));

        layout.setVerticalGroup(layout
                .createSequentialGroup()
                .addGroup(
                        layout.createParallelGroup(
                                GroupLayout.Alignment.BASELINE)
                                .addComponent(label).addComponent(text)
                                .addComponent(Button)).addComponent(scroll));
        Button.addActionListener(this);

        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == Button) {
            if (text.getText().equals("")) {
                previous_count = current_count;
                current_count++;
                label.setText("Current Count: "
                        + Integer.toString(current_count));
                model.addRow(new Object[] { current_count, previous_count });
            } else {
                previous_count = current_count;
                current_count = Integer.parseInt(text.getText());
                label.setText("Current Count: "
                        + Integer.toString(current_count));
                text.setText("");
                model.addRow(new Object[] { current_count, previous_count });
            }
            table.changeSelection(table.getRowCount() - 1, 0, false,
                    false);
        }
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                sampleGUI gui = new sampleGUI();
            }
        });
    }
}

假设我想模拟打开GUI,然后单击按钮一次而不输入任何文本,然后输入1234并单击按钮,然后单击按钮而不输入任何文本,JTable应该有3列:{{1,0 }, {1234, 1}, {1235, 1234}}。我该如何为此编写测试?谢谢!

4

5 回答 5

22

Java SE 附带了一个用于执行此操作的标准工具,即Robot类。我只用它来编写游戏机器人和通过套接字服务器/客户端对远程控制单独的计算机,但它实际上是为了自动化测试,所以它应该适合你。基本格式很简单:

Robot bot = new Robot();
bot.mouseMove(10,10);
bot.mousePress(InputEvent.BUTTON1_MASK);
//add time between press and release or the input event system may 
//not think it is a click
try{Thread.sleep(250);}catch(InterruptedException e){}
bot.mouseRelease(InputEvent.BUTTON1_MASK);

当然,您也可以使用适当的 keyPress/keyRelease 方法以类似的方式模拟键盘事件。我有时发现使用机器人类的 screenCapture 方法以及在屏幕上搜索图像并确定单击位置很有用。

注意:这并不要求您正在测试的窗口是在 awt/swing 上构建的,但是它确实要求您使用的 java 实现支持 awt。

于 2013-05-07T12:09:20.623 回答
5

AssertJ是 FEST 的一个分支,对我来说效果很好,并且支持Swing。开发很活跃(在撰写本文时),支持 Java 8,对一些流行的库(如 Guava 和 Joda Time)有断言,并且有很好的文档记录。它也是免费和开放的。

于 2015-09-24T21:28:57.837 回答
4

几年前我有一个项目需要自动化测试。

我们最终选择了:

jfcunit

我们也试过

fest - 很好,但在撰写本文时只是单线程。

swingunit - 还可以,但我们遇到了一些微妙的问题,所以我们需要放弃它

于 2013-05-07T12:22:19.250 回答
0

一般来说,一个好的做法是将视图层设计得尽可能薄,这样您就不必对其进行测试,而是专注于业务逻辑。为了实现人们使用模型视图演示器或演示模型等设计模式。

但是,如果您必须测试 GUI,那么您可以尝试 windowlicker:- https://code.google.com/p/windowlicker/

于 2013-10-17T14:16:35.067 回答
0

通常,您必须记住要在应用程序中测试的内容。假设您要测试应用程序中的组件,以检查将来是否发生了影响当前格式的任何更改。其次要检查swing 应用程序中提供的逻辑或方法,即流程中的任何更改是否会影响返回语句。

我将放置一段测试代码

让我们考虑这个实现方法

  public void activate() 
{  
    f=new JPanel();  
    tf=new JTextField();  
    tf.setBounds(50,50, 150,20);  
    tf.setName("b1");
    b=new JButton("Click Here");
    b.setName("Click Here");
    b.setBounds(50,100,95,30);  
    f.add(b);
    f.add(tf);  
    f.setSize(400,400);  
    f.setLayout(null);  
    f.setVisible(true);
    //b.doClick();
}

所以下面的测试用例可以(使用junit)

@Test
public void testActivate()
    {
        btn=new Button();
        assertNotNull(btn);
        JPanel jf=btn.f;
        btn.activate();
        int height=b.getHeight();
        int width=b.getWidth();
        assertEquals(30,height);
        assertEquals(95,width);
        int x=b.getX();
        int y=b.getY();
        assertEquals(50,x);
        assertEquals(100,y);
        int x1=tf.getX();
        int y1=tf.getY();
        assertEquals(50,x1);
        assertEquals(50,y1);
    }

进一步,如果你想刺激按钮点击,你可以使用该对象实例的 doClick 方法

    btn.run();
    b.doClick();

    String str=tf1.getText().toString();
    assertEquals("Welcome to junit.",str);
于 2017-01-24T09:53:44.570 回答