Java 中 GUI 的 JUnit 测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16411823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JUnit Tests for GUI in Java
提问by newtothissite
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.
我想为 GUI 编写测试用例。我想知道你如何模拟JButton的点击,或者你如何提取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.
为此,我构建了一个简单的 GUI,如果单击按钮且 JTextfield 为空,则将计数增加 1,但如果提供了数字,则计数将替换为 JTextfield 中的整数。当然,我想使用 Regex 来确保输入到 JTextfield 的文本实际上是一个整数,但让我们假设用户不会乱七八糟地输入非整数。此外,JLabel 会在 JTable 添加新行时更新当前计数。
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!
假设我想模拟打开GUI,然后单击一次按钮不输入任何文本,然后输入1234并单击该按钮,然后单击该按钮而不输入任何文本,JTable应该有3列:{{1,0 }, {1234, 1}, {1235, 1234}}。我该如何为此编写测试?谢谢!
采纳答案by S E
Java SE comes with a standard tool for doing just this, the Robotclass. 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:
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);
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.
当然,您也可以使用适当的 keyPress/keyRelease 方法以类似的方式模拟键盘事件。我有时发现使用机器人类的 screenCapture 方法搜索屏幕上的图像并确定单击的位置很有用。
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.
注意:这并不要求您正在测试的窗口构建在 awt/swing 上,但是它确实要求您使用的 Java 实现支持 awt。
回答by Oliver Watkins
I had a project a few years back where we needed to automate tests.
几年前我有一个项目需要自动化测试。
We ended up going with :
我们最终选择了:
jfcunit
单位
We also tried out
我们也试过了
fest- was good but at the time of writing was only single threaded.
fest- 很好,但在撰写本文时只是单线程的。
swingunit- also ok, but we had a few subtle problems so we needed to ditch it
Swingunit- 还可以,但我们有一些微妙的问题,所以我们需要放弃它
回答by Luke
Generally a good practice is to design your view layer as thin as possible so you don't have to test it and you focus on a business logic. In order to achive that people are using design patterns like Model View Presenter or Presentation Model.
通常,一个好的做法是将您的视图层设计得尽可能薄,这样您就不必对其进行测试并专注于业务逻辑。为了实现人们正在使用诸如模型视图演示器或演示模型之类的设计模式。
But if you have to test GUI then you can try windowlicker: - https://code.google.com/p/windowlicker/
但是,如果您必须测试 GUI,那么您可以尝试使用 windowlicker: - https://code.google.com/p/windowlicker/
回答by Jwest08
AssertJis a fork of FEST that is working very well for me, and has support for Swing. Development is active (at time of writing), supports Java 8, has assertions for a few popular libraries such as Guava and Joda Time, and is very well documented. It is also free and open.
AssertJ是 FEST 的一个分支,对我来说效果很好,并且支持Swing。开发是活跃的(在撰写本文时),支持 Java 8,对一些流行的库(如 Guava 和 Joda Time)有断言,并且有很好的文档记录。它也是免费和开放的。
回答by Akhil Vijayan
normally you have to keep in mind what you want to test in your application.lets say you want to test the components in the application so as to check whether any changes has taken place in the future that affect the current format.and second to check the logic or method provided in the swing application ie,whether any change in the flow will effect the return statements.
通常你必须记住你想在你的应用程序中测试什么。假设你想测试应用程序中的组件,以检查将来是否发生了影响当前格式的任何更改。然后检查Swing 应用程序中提供的逻辑或方法,即流程中的任何更改是否会影响返回语句。
i will place a piece of test code
我将放置一段测试代码
lets consider this implementation method
让我们考虑这个实现方法
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();
}
so the following test case can be(using junit)
所以下面的测试用例可以是(使用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);
}
further if you want to stimulate button click you can use doClick method of that object instance
进一步,如果你想刺激按钮点击,你可以使用该对象实例的 doClick 方法
btn.run();
b.doClick();
String str=tf1.getText().toString();
assertEquals("Welcome to junit.",str);