Si vous avez l’habitude de faire des tests d’interface Web avec Selenium, vous savez sûrement à quel point ces tests deviennent difficiles à maintenir ou sont difficiles à lire (voire déchiffrer). FluentSelenium est un projet Open Source offert par Pyxis (http://fluentselenium.codeplex.com) pour améliorer la lisibilité de ces tests et par la même occasion, en faciliter l’écriture avec l’utilisation d’un langage dédié (Domain Specific Language ou DSL). Les meilleures pratiques proposent qu’un développeur soit capable de comprendre le comportement d’un test très rapidement. Dans l’exemple suivant, on veut tester l’ajout d’un ‘post’ sur un forum. Pour y arriver, on doit passer par la liste des ‘posts’ et remplir les champs du formulaire pour ensuite cliquer sur le bouton de sauvegarde et revenir à la liste. Si on regarde le code que l’on produirait avec Selenium directement, on obtiendrait ceci : [Test] public void TestAddNewPostCanSeeInTheList() {

selenium.Open(“Forum/AllPosts.aspx”); selenium.WaitForPageToLoad(“2000”);selenium.Click(“//a[contains(@id, ‘newPost’)]”); selenium.WaitForPageToLoad(“2000”); selenium.Type(“//*[contains(@id, ‘txtAuthor’)]”, “Paul”); selenium.Type(“//*[contains(@id, ‘txtSubject’)]”, “Simple example of the library.”); selenium.Click(“//*[contains(@id, ‘btnSavePost’)]”); selenium.WaitForPageToLoad(“2000”); Assert.AreEqual(“Paul”, selenium.GetText(“//table[contains(@id, ‘grdPosts’)]//tr[2]/td[2]”));

} Je crois que tout le monde s’entend pour dire que ce test n’est pas très lisible. Il y a plusieurs façons de l’améliorer, comme par exemple extraire les XPath dans des constantes ou se créer une espèce de framework pour découper les parties de notre application. Toutefois, ce serait encore mieux si on pouvait lire le test comme si on lisait des phrases. L’exemple suivant montre un peu comment on peut « phraser » le même test en utilisant FluentSelenium : [Test] public void TestAddNewPostCanSeeInTheList() {

forumUser.Goto(“Forum/AllPosts.aspx”); forumUser.For(PostListPage.AddPostButton).Clicks();forumUser.For(NewPostPage.AuthorTextBox).Enters(“Paul”); forumUser.For(NewPostPage.SubjectTextBox).Enters(“Simple example of the library.”); forumUser.For(NewPostPage.SavePostButton).Clicks(); forumUser.For(PostListPage.AllPostsTable).Row(2).ShouldSee(postDate, “Paul”, “Simple example of the library.”);

} De plus, dans cet exemple, on peut très bien imaginer que l’action d’ajouter un ‘post’ reviendrait dans plusieurs tests différents. Alors, notre test ressemblerait plus à ce qui suit : private static readonly ITask AddNewPost = new AddNewPostTask("Paul", "Simple example of the library.", ""); [Test] public void TestAddNewPostCanSeeInTheList() {

forumUser.Goto(“Forum/AllPosts.aspx”); forumUser.Do(AddNewPost); forumUser.For(PostListPage.AllPostsTable).Row(2).ShouldSee(postDate, “Paul”, “Simple example of the library.”);

} À ce point-ci, on pourrait expliciter un peu plus la commande en ajoutant une Factory :  

forumUser.Do(AddNewPost(“Paul”, “Simple example of the library.”));

  Ultimement, l’idée est de rendre les tests le plus lisible possible. FluentSelenium est un API simple pour écrire des tests d’interface, mais l’utilisation d’un langage dédié pour écrire des tests unitaires ou d’intégration est une pratique puissante pour les tests unitaires et d’intégration. Pour avoir plus de détails sur les exemples utilisés, vous pouvez accéder au code du projet sur codeplex : http://fluentselenium.codeplex.com.

gabriel bélanger

Billet précédent

Pyxis dans Les Affaires

Billet suivant

Pyxis Snow Team participe au 24h Tremblant