I would like to write test cases for a GUI. I want to know how do you simulate a click of JButton, or how do you extract the elements of a JTable.
For the purpose of this, I have built a simple GUI that increase the count by 1 if the button is clicked and the JTextfield is empty, but the count is replaced by the integer in the JTextfield if a number is provided. Of course I would like to use Regex to make sure the text entered into the JTextfield is actually an integer, but let's assume users won't mess around and enter a non-integer. In addition, the JLabel updates the current count while the JTable adds a new row.
Here's the code:
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();
}
});
}
}
Let's say I would like to simulate opening the GUI, then click the button once without entering any text, then enter 1234 and click the button, then click the button without entering any text, the JTable should have 3 columns: {{1,0}, {1234, 1}, {1235, 1234}}. How can I write the test for that? Thanks!
Java SE comes with a standard tool for doing just this, the Robot class. I've only ever used it to write bots for games and to remotely control a separate computer via a socket server/client pair, but it was actually intended to automate testing, and so it should work for you. The basic format is simple:
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);
Of course you can simulate keyboard events in a similiar way as well using the appropriate keyPress/keyRelease methods. I've sometimes found it useful to use the screenCapture method of the robot class as well to seach for images on the screen and determine where to click.
Note: this does not require that the windows you are testing are built on awt/swing, however it does require that the java implementaton you are using supports awt.