wake-up-neo.com

JUnit Tests für GUI in Java

Ich würde gerne Testfälle für eine GUI schreiben. Ich möchte wissen, wie Sie einen Klick auf JButton simulieren oder wie Sie die Elemente einer JTable extrahieren.

Zu diesem Zweck habe ich eine einfache grafische Benutzeroberfläche erstellt, die die Anzahl um 1 erhöht, wenn auf die Schaltfläche geklickt wird und das JText-Feld leer ist. Die Anzahl wird jedoch durch die Ganzzahl im JText-Feld ersetzt, wenn eine Zahl angegeben wird. Natürlich möchte ich Regex verwenden, um sicherzustellen, dass der in das JText-Feld eingegebene Text tatsächlich eine Ganzzahl ist. Nehmen wir jedoch an, dass die Benutzer nicht herumspielen und eine Nicht-Ganzzahl eingeben. Außerdem aktualisiert das JLabel die aktuelle Anzahl, während die JTable eine neue Zeile hinzufügt. 

Hier ist der 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();
            }
        });
    }
}

Angenommen, ich möchte das Öffnen der grafischen Benutzeroberfläche simulieren, dann auf die Schaltfläche klicken, ohne einen Text einzugeben. Dann 1234 eingeben und auf die Schaltfläche klicken. Dann auf die Schaltfläche klicken, ohne einen Text einzugeben. Die JTable sollte 3 Spalten haben: {{1,0 }, {1234, 1}, {1235, 1234}}. Wie kann ich den Test dafür schreiben? Vielen Dank!

19
newtothissite

Java SE verfügt über ein Standardwerkzeug, die Klasse Robot . Ich habe es immer nur zum Schreiben von Bots für Spiele und zur Fernsteuerung eines separaten Computers über ein Socket-Server/Client-Paar verwendet, aber eigentlich sollte das Testen automatisiert werden, und es sollte für Sie funktionieren. Das Basisformat ist einfach:

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);

Natürlich können Sie auch Tastaturereignisse auf ähnliche Weise mit den entsprechenden keyPress/keyRelease-Methoden simulieren. Ich habe es manchmal für nützlich erachtet, die screenCapture-Methode der Roboterklasse zu verwenden, um nach Bildern auf dem Bildschirm zu suchen und zu bestimmen, wo man klicken soll. 

Hinweis: Dies setzt nicht voraus, dass die von Ihnen getesteten Fenster auf awt/swing basieren. Allerdings muss die von Ihnen verwendete Java-Implementierung awt unterstützen.

16
S E

AssertJ ist eine FEST von FEST, die sehr gut für mich funktioniert und Unterstützung für Swing bietet. Die Entwicklung ist aktiv (zum Zeitpunkt des Schreibens), unterstützt Java 8, hat Behauptungen für einige beliebte Bibliotheken wie Guava und Joda Time und ist sehr gut dokumentiert. Es ist auch frei und offen.

4
Jwest08

Ich hatte vor ein paar Jahren ein Projekt, bei dem wir Tests automatisieren mussten.

Am Ende gingen wir mit:

jfcunit

Wir haben es auch ausprobiert

fest - war gut, aber zum Zeitpunkt des Schreibens war nur ein einzelner Thread.

swingunit - auch ok, aber wir hatten ein paar subtile Probleme, also mussten wir es wegnehmen

2
Oliver Watkins

normalerweise müssen Sie daran denken, was Sie in Ihrer Anwendung testen möchten. In den Befehlen wird angegeben, dass Sie die Komponenten in der Anwendung testen möchten, um zu prüfen, ob in der Zukunft Änderungen vorgenommen wurden, die sich auf das aktuelle Format auswirken die in der Swing-Anwendung bereitgestellte Logik oder Methode, dh, ob eine Änderung des Flusses die Rückgabeanweisungen beeinflusst. 

ich werde ein Stück Testcode platzieren

betrachten wir diese Implementierungsmethode

  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 kann der folgende Testfall sein (mit 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);
    }

wenn Sie das Klicken auf die Schaltfläche stimulieren möchten, können Sie die Methode doClick dieser Objektinstanz verwenden

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

    String str=tf1.getText().toString();
    assertEquals("Welcome to junit.",str);
0
Akhil Vijayan

Im Allgemeinen empfiehlt es sich, die Ansichtsebene so dünn wie möglich zu gestalten, sodass Sie sie nicht testen müssen und sich auf eine Geschäftslogik konzentrieren. Um zu erreichen, dass Personen Entwurfsmuster wie Model View Presenter oder Presentation Model verwenden.

Wenn Sie jedoch die GUI testen müssen, können Sie Windowlicker ausprobieren: - https://code.google.com/p/windowlicker/

0
Luke