Swing Unit, SpecUI4j...) mais j'ai envie de m'arrêter sur Fest Swing. Prenez le code Swing suivant :
...
lineNumberTextField.setName(LINE_NUMBER_TEXT_FIELD);
...
searchCriteria1Panel.add(lineNumberTextField, cc.xywh(12, 2, 3, 1));
...
queryButton.setName(QUERY_BUTTON);
//---- queryButton ----
queryButton.setText(bundle.getString("search.queryButton.text"));
queryButton.setAction(queryAction);
searchActionPanel.add(queryButton, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
...
Un panel propose des champs de recherche, un bouton permettant de déclencher cette recherche. Bref, de l'hyper classique. Le code de tests (développé avec Fest) est le suivant :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
public abstract class MyTest extends FestSwingTestCaseTemplate {
...set up must be done. see Fest documentation for more details
protected FrameFixture editor;
private JTabbedPaneFixture criteriaPane;
private JButtonFixture queryButton;
@Test
public void testWhatYouWannaTest() {
queryButton = editor.button(QUERY_BUTTON);
editor.textBox(LINE_NUMBER_TEXT_FIELD).enterText("123456");
...
analysisModel.getSelectedCauseModel().setSelectionIndex(2);
Assert.assertEquals("libCause1", editor.textBox(CAUSE_TEXT_FIELD).text());
criteriaPane.selectTab(1);
editor.textBox(BRANCH_TEXT_FIELD).enterText("");
editor.comboBox(ENTRY_DATE_OPERATOR_COMBO).selectItem(1);
queryButton.click();
// asserts
final SearchCriteria searchCriteria = systemUnderTest.getSearchCriteria();
Assert.assertEquals((Long) Long.parseLong("123456"), searchCriteria.getLineNumber());
Assert.assertNull(searchCriteria.getBranch());
Assert.assertEquals(10, searchCriteria.getTop());
...
Simple, efficace, lisible.
Ainsi Fest Swing présente les avantages suivants : - Exécution sous la forme de tests JUnit. L'exécution des tests reste assez rapide. - Intégration à l'automate de build. Puisque définis au format jUnit, ces tests sont facilement intégrables au build continu (via éventuellement un profil particulier). - API (voire un DSL) limpide à utiliser. Le code des tests est expressif et il est possible de récupérer des boutons, de déclencher des actions, de saisir du texte... - Récursivité du "moteur" de sélection de composants. Tous les frameworks ne le propose pas (UISpec4J par exemple) mais c'est pourtant essentiel tant en termes de productivité des développements qu'en termes de stabilité des tests. Sur l'aspect productivité, le développement d'IHM implique d'empiler les composants et les panels (JComponents, etc...). Fest retrouve de façon récursive, sur la base d'un nom logique, n'importe lequel des composants dans l'arborescence de composants (le fameux tableaux de components pour les techies). Au niveau de la stabilité des tests, vous pouvez donc modifier et refactorer le code Swing (empilement des composants...) sans introduire de fausses régressions.
Mais au delà de l'outil (qui reste essentiel), reste une question : que veut-on tester? De quels défauts souhaite-t-on se prémunir? De mon expérience, il peut être intéressant de tester du comportement (déclenchement d'actions...), du technique (binding dans le cas d'utilisation d'outils type jGoodies, habilitation sur la fonction et la donnée...) ou encore des scenarii métiers complets (saisie des paramêtres de recherche, remplissage de la liste de résultat, affichage du nombre de résultat dans le label prévu à cet effet...). Sur ces aspects Fest Swing fonctionne. En revanche, tester les navigations entre écrans, la gestion du fenêtrage, des menus peut être plus complexes.
Et vous, au niveau de l'IHM que testez vous? Avec quels outils?