En Java standard il existe une librairie de test dédiée au IHM de type client lourd pour les API swing et awt qui s’appele Fest [1] [3]. Celle est vraiment concu pour etre simple et logique en utilisant les noms des éléments de l’IHM pour se mapper sur leur interfaces de fonctionnement.
Pour l’utiliser il suffit de tirer l'artefact suivant:
<dependency>Pour l’utiliser il reste à définir une classe de test classique JUnit héritant de la classe FestSwingJUnitTestCase dans laquelle il faudra initialiser un robot Fest et le donner à un objet de type FrameFixture qui va se charger de piloter le robot afin que celui ci parse et effectuer les interaction adéquate sur notre IHM.
<groupId>org.easytesting</groupId>
<artifactId>fest-util</artifactId>
<version>1.1.6</version>
<scope>test</scope>
</dependency>
Avant cela, Pour que le robot soit capable de parser notre IHM il faudra par contre indiquer a Fest sur quel IHM il doit faire ses actions (grâce a un GuiQuery). On spécifie alors une méthode statique d’initialisation dédié dans laquelle nous instancierons notre IHM:
@RunsInEDTDu coup, il nous faudra initialiser dans un setUp notre environnement de test contenant le FrameMixture:
private static MainFrame createNewEditor(BundleContext context) {
final GuiQuery<MainFrame> query = new GuiQuery<MainFrame>() {
@Override
protected MainFrame executeInEDT() {
MainFrame app = null;
try {
app = new MainFrame(context);
} catch (final TcOsgiException e) {
e.printStackTrace();
}
return app;
}
};
return GuiActionRunner.execute(query);
}
@OverrideGrace a cela, il ne nous restera plus qu’a declarer les actions que l’on souhaitera faire sur l’IHM dans des tests spécifiques comme on le ferait dans un test unitaire classique sauf que la nous allons scénariser les actions:
protected void onSetUp() {
try {
BundleContext context = Mockito.mock(BundleContext.class);
editor = new FrameFixture(robot(), MainFrameTest.createNewEditor(context));
editor.show();
} catch (Exception e) {
e.printStackTrace();
}
}
@TestA noter qu'à ce niveau d’abstraction, nous ne sommes plus vraiment en train de faire des tests unitaires mais plutôt des tests fonctionnels mais cela n’a pas forcement d’importance dans notre cas (a noter malgré tout que l’approche est particulièrement adapté à la mise en place de test pour vérifier des cas d’utilisation particulière en lien direct avec le besoin utilisateur)
public void profilCreationSelection() {
editor.menuItem("Select MorphMath Action").click();
editor.comboBox("combo1").selectItem("dilatation").click();
editor.menuItem("GO").click();
System.out.println(new File(".").getAbsolutePath());
editor.fileChooser().fileNameTextBox().setText(
"docvierge.bmp");
editor.fileChooser().approve();
Thread.sleep(500);
editor.close();
}
Voila un petit aperçu de Fest et de ses capacités pour des tests d’IHM. Point particulier a prendre en compte lors de l'exécution des tests: ces derniers sont réalisés avec une IHM visible vous permettant de voir quels sont les actions et mouvement de souris réalisées pour faire le test. Cela est clairement intéressant mais comporte un inconvénient majeur, vos tests ne fonctionnent pas sans environnement graphique comme dans un serveur d'intégration continu. Typiquement vous aurez une erreur du type (dans Travis [2] par exemple):
PM org.fest.swing.monitor.WindowStatus <init>
WARNING: Error ocurred when creating a new Robot
java.awt.AWTException: headless environment
at java.awt.Robot.<init>(Robot.java:91)
at org.fest.swing.util.RobotFactory.newRobotInPrimaryScreen(RobotFactory.java:35)
at org.fest.swing.monitor.WindowStatus.<init>(WindowStatus.java:58)
at org.fest.swing.monitor.WindowStatus.<init>(WindowStatus.java:51)
at org.fest.swing.monitor.WindowMonitor.<init>(WindowMonitor.java:51)
at org.fest.swing.monitor.WindowMonitor$SingletonLazyLoader$1.executeInEDT(WindowMonitor.java:134)
at org.fest.swing.monitor.WindowMonitor$SingletonLazyLoader$1.executeInEDT(WindowMonitor.java:132)
at org.fest.swing.edt.GuiQuery.run(GuiQuery.java:41)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Pour résoudre ce problème il vous suffira d’utiliser xvfb (un server X11) [4] . Comme décrit dans [5], cela permet de simuler un environnement graphique. (ou un autre exemple [6]).
References:
[1] http://www.vogella.com/tutorials/FEST/article.html
[2] https://travis-ci.org/
[3] http://tuhrig.de/automated-ui-testing-with-swing-fest/
[4] https://www.x.org/archive/X11R7.6/doc/man/man1/Xvfb.1.xhtml
[5] https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
[6] https://gist.github.com/cecilemuller/764afa5d4c67e17741d9bc258b45cdc1
Aucun commentaire:
Enregistrer un commentaire