IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

Est-il possible de tester une classe Swing avec l'API de test JUnit sous Eclipse ?


Sujet :

AWT/Swing Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 5
    Par défaut Est-il possible de tester une classe Swing avec l'API de test JUnit sous Eclipse ?
    Bonjour à tous,

    je ne parviens pas à trouver la réponse à ma question dans la FAQ.

    Savez vous si il est possible de tester une classe Swing dans Eclipse Kepler Service Release 2 avec JUnit-4.7 ?

    Je cherche à tester des GUI (Graphic User Interface) écrites avec Java jdk1.7.0_65 et notamment son API Swing.

    J'ai une classe qui m'ouvre une JFrame contenant un JPanel et ses composants. Lorsque je teste cette classe dans une classe applicative (avec méthode main(...)) en ouvrant un Thread EDT, tout fonctionne parfaitement.
    La fenêtre s'affiche et je vois tout ce qui doit apparaitre à l'écran.

    Je souhaiterais savoir si il est possible de faire la même chose dans une méthode d'un Test JUnit-4.7 sous Eclipse Kepler.
    J'utilise le JUnit dans Eclipse Kepler (JUnit-4.7.jar déclaré dans mes librairies) et j'essaie de faire un JUnit Test case comme pour les classes non graphiques.

    Le test JUnit semble se dérouler normalement (barre verte) avec une classe graphique Swing, mais je ne parviens pas à afficher la JFrame contenant un JPanel et ses composants.

    Je suppose que le Thread EDT gérant l'affichage des composants graphiques Swing peut poser problème mais je suis trop court en Java pour pouvoir me dépêtrer de ce souci.

    Quelqu'un aurait-il trouvé une solution dans Eclipse Kepler ? Merci d'avance.

    Cordialement,

    Daniel Lévy
    dany.levy@free.fr

  2. #2
    Invité
    Invité(e)
    Par défaut
    Vous pouvez éventuellement créer un script de test utilisant la classe Robot

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 5
    Par défaut Merci beaucoup
    Citation Envoyé par chanyslas Voir le message
    Vous pouvez éventuellement créer un script de test utilisant la classe Robot
    Merci beaucoup. Je vais donc essayer cette classe Robot.

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    La classe robot, selon moi, c'est overkill pour du unit test. Ca va simuler des clic et des entrées souris via le système natif de l'OS. Autrement dit, si ça clic à coté, tu peux balancer tout ton test au final dans un email, effacer des fichiers dans l'exploreur, etc. Assez dangereux et de toutes façons très difficile d'avoir un feedback pour le tapper dans un Assert.

    Personellement, quand je dois tester que des composants swings se comportent correctement, c'est souvent des tests de synchro. Genre "a tiens, si je sélectionne tel élement dans la liste, tel et tel JTextField doivent s'activer". Et ça c'est assez facile à tester. Tu instancie la JFrame, tu crée un getter pour avoir la JList et les textfields, et ton test deviens


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Fenetre maFenetre = new Fenetre();
    maFenetre.getLaListe().setSelectedIndex(3);
    assetEquals("Tartempion",maFenetre.getNameField().getText());
    Pour des chose un peu plus complexe, genre "HA si je clique droit sur le JLabel, une JPopup dois apparaitre", c'est plus complexe. Tu peux facilement balancer l'event via processMouseEvent() sur le composant. Pour détecter l'affichage de la JPopup, tu pourrais utiliser powerMockito pour intercepter les new sur JPopupMenu et en conclure que, oui, on a bien lancer une popup. Ou diviser mieux ton code pour que la popup soit gérée par une classe à part facilement mockable.

    Pour le reste, les interactions complexe, rien ne vaut l'oeil du testeur au final.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2013
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 5
    Par défaut Incompatibilité entre le Thread EDT et JUnit ?
    Citation Envoyé par tchize_ Voir le message
    La classe robot, selon moi, c'est overkill pour du unit test. Ca va simuler des clic et des entrées souris via le système natif de l'OS. Autrement dit, si ça clic à coté, tu peux balancer tout ton test au final dans un email, effacer des fichiers dans l'exploreur, etc. Assez dangereux et de toutes façons très difficile d'avoir un feedback pour le tapper dans un Assert.

    Personellement, quand je dois tester que des composants swings se comportent correctement, c'est souvent des tests de synchro. Genre "a tiens, si je sélectionne tel élement dans la liste, tel et tel JTextField doivent s'activer". Et ça c'est assez facile à tester. Tu instancie la JFrame, tu crée un getter pour avoir la JList et les textfields, et ton test deviens


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Fenetre maFenetre = new Fenetre();
    maFenetre.getLaListe().setSelectedIndex(3);
    assetEquals("Tartempion",maFenetre.getNameField().getText());
    Pour des chose un peu plus complexe, genre "HA si je clique droit sur le JLabel, une JPopup dois apparaitre", c'est plus complexe. Tu peux facilement balancer l'event via processMouseEvent() sur le composant. Pour détecter l'affichage de la JPopup, tu pourrais utiliser powerMockito pour intercepter les new sur JPopupMenu et en conclure que, oui, on a bien lancer une popup. Ou diviser mieux ton code pour que la popup soit gérée par une classe à part facilement mockable.

    Pour le reste, les interactions complexe, rien ne vaut l'oeil du testeur au final.
    Merci beaucoup,

    en fait, ma question portait plus sur le problème du Thread EDT pour l'affichage graphique. Quand je fais une classe applicative avec une méthode main comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    public static void main(final String[] args) {
     
    		/* Utilise le Event Dispatch Thread (EDT). */
    		SwingUtilities.invokeLater(new Runnable() {
     
    			@Override
    			public void run() {
     
    				/* Création d'une JFrame. */
    				final JFrame frame = new JFrame();
     
    				/* Création d'un JPanel. */
    				final JPanel panel = new JPanel();
     
    				/* Coloration et dimensionnement du panel. */
    				panel.setBackground(Color.BLUE);
    				panel.setPreferredSize(new Dimension(900, 700));
    				panel.setMinimumSize(new Dimension(900, 700));
     
    				/* Passe un GridBagLayout au ContentPane de la JFrame . */
    				frame.getContentPane().setLayout(new GridBagLayout());
     
    				/* Ferme l'application lorsque l'on ferme la fenêtre. */
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    				/* Ajout du JPanel à la JFrame. */
    				frame.getContentPane().add(panel);
     
    				/* Met en place la JFrame. */
    		                frame.pack();
     
    		                /* Dimensionne la JFrame. */
    				frame.setSize(1000, 800);
     
    				/* JFrame redimensionnable. */
    				frame.setResizable(true);
     
    				/* JFrame centrée au mileu de l'écran. */
    				frame.setLocationRelativeTo(null);
     
    				/* Affichage de la JFrame. */
    				frame.setVisible(true);
     
    			} // Fin de Run().____________________________
     
    		}); // Fin de new Runnable()._______________________________
     
    	} // Fin de main(...)._________________________________________________
    Je lance dans Eclipse cette application. Tout fonctionne parfaitement et la JFrame s'affiche.

    Je ne parviens à faire la même chose au sein d'une méthode d'un test Junit. L'affichage semble impossible. Je suppose qu'il y a une incompatibilité entre l'utilisation du Thread EDT et l'API JUnit mais je n'en suis pas sûr.

    Je voulais donc savoir si il y avait une astuce permettant d'afficher du Swing dans un test JUnit (ouvrir un nouveau Thread, utilisation d'une classe SwingWorker, ....).

    Merci d'avance.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    La première chose que je ferais, c'est sortir du main le contenu de run(), ca te donne un point d'entrée pour ton unit test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public static JFrame startMainFrame(){
    				/* Création d'une JFrame. */
    				final JFrame frame = new JFrame();
     
    				/* Création d'un JPanel. */
    				final JPanel panel = new JPanel();
     
    				/* Coloration et dimensionnement du panel. */
    				panel.setBackground(Color.BLUE);
    				panel.setPreferredSize(new Dimension(900, 700));
    				panel.setMinimumSize(new Dimension(900, 700));
     
    				/* Passe un GridBagLayout au ContentPane de la JFrame . */
    				frame.getContentPane().setLayout(new GridBagLayout());
     
    				/* Ferme l'application lorsque l'on ferme la fenêtre. */
    				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    				/* Ajout du JPanel à la JFrame. */
    				frame.getContentPane().add(panel);
     
    				/* Met en place la JFrame. */
    		                frame.pack();
     
    		                /* Dimensionne la JFrame. */
    				frame.setSize(1000, 800);
     
    				/* JFrame redimensionnable. */
    				frame.setResizable(true);
     
    				/* JFrame centrée au mileu de l'écran. */
    				frame.setLocationRelativeTo(null);
     
    				/* Affichage de la JFrame. */
    				frame.setVisible(true);
                                    return frame;
     
    }
     
    public static void main(final String[] args) {
     
    		/* Utilise le Event Dispatch Thread (EDT). */
    		SwingUtilities.invokeLater(new Runnable() {
     
    			@Override
    			public void run() {
     				startMainFrame();
     
    			} // Fin de Run().____________________________
     
    		}); // Fin de new Runnable()._______________________________
     
    	} // Fin de main(...)._________________________________________________
    Ensuite, tu peux commencer ton test comme ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    JFrame aTester = null;
     
    @Test
    public void testFenetre() throws Exception { // Exception à clarifier
       SwingUtilities.invokeAndWait(new Runnable(){public void run(){aTester = Main.startMainFrame();}});
       // Laisse à swing le temps de consommer les évènement éventuellement créés par l'apparition de la fenêtre en se remettant à la fin.
       SwingUtilities.invokeAndWait(new Runnable(){public void run(){}}); 
       // Go pour le test
       assertNotNull(aTester);
       assertTrue(aTester.isVisible());
    }

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    La classe robot, selon moi, c'est overkill pour du unit test. Ca va simuler des clic et des entrées souris via le système natif de l'OS. Autrement dit, si ça clic à coté, tu peux balancer tout ton test au final dans un email, effacer des fichiers dans l'exploreur, etc. Assez dangereux et de toutes façons très difficile d'avoir un feedback pour le tapper dans un Assert.
    Votre vision apocalyptique de l'utilisation de la classe Robot n'est pas très sérieuse et prête à sourire. Ce n'est pas parce que vous n'utilisez pas une fonctionnalité d'un langage qu'il faut la dénigrer avec autant de caricature.
    Je suis d'accord avec vous qu'elle manque encore de fonctionnalités et "viser" les composants n'est pas forcément très pratique, mais elle a le mérite d'exister et vient compléter les outils permettant de réaliser des tests.
    D'autre part, pour utiliser correctement cette classe, au lieu de "viser", vous pouvez utiliser les méthodes de focus sur les composants avant de faire intervenir le Robot ou faire en sorte que celui-ci utilise des commandes recevables par votre GUI (les accélérateurs, etc), plutôt que de le faire cliquer ou taper comme un gremlins. Il ne s'agit pas, dans cette discussion, de tests de robustesse.

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par chanyslas Voir le message
    Votre vision apocalyptique de l'utilisation de la classe Robot n'est pas très sérieuse et prête à sourire. Ce n'est pas parce que vous n'utilisez pas une fonctionnalité d'un langage qu'il faut la dénigrer avec autant de caricature.
    Ce n'est pas caricatural et part bien d'expériences personnelle. La classe Robot ne fait que créer des évenements systèmes et ceux si peuvent aussi bien arriver sur une de vos fenètre qu'à coté à cause d'un bug. Et quand le test et un test de drag and drop, ça se résume à un drag and drop "à coté". En l'occurence dans mon cas à l'époque c'est tombé dans le eclipse derrière qui a fait disparaitre un dossier du code pour le faire disparaitre dans un sous dossier obscur. C'est allé trop vite pour voir ce qui se passait et j'ai perdu une demi journée à remettre le projet en état...

    La plupart des tests n'ont pas besoin de Robot car on peut directement injecter les évènements sur la frame, qui dispatchera elle même aux différents composants. Du code swing c'est du code comme un autre, ce sont des objets avec des méthodes, et c'est testable de la même manière: on appelle les méthode, on met des mocks où il faut et on vérifie ce qui en sort.

    Bref, je parlais pas de faire travailler Robots comme un gremlings, mais d'éviter un triple travail de test à savoir:
    Tester que le code principal n'a pas de soucis (le but du unit test)
    Tester que le code de test ne pourra jamais dérapper (c'est la partie que je trouve overkill dans Robots selon moi)
    S'assurer pendant les 20 minutes que tourne le test qu'aucune andouille de collègue ne touchera votre clavier pour vous montrer un truc

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 26/01/2012, 17h46
  2. Réponses: 6
    Dernier message: 28/10/2011, 12h01
  3. Réponses: 2
    Dernier message: 28/09/2010, 19h00
  4. Réponses: 8
    Dernier message: 23/02/2008, 09h49
  5. est-il possible d'executer une requete SQL avec jvs?
    Par roxxxy dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 19/04/2007, 15h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo