vendredi 22 janvier 2010 17:22
tja
[Tests] ASP.NET MVC 2 et les Tests Unitaires avec NBehave - Suite
Après une petite introduction dans mon post [Tests] ASP.NET MVC 2 et les Tests Unitaires avec NBehave aux tests unitaires avec NBehave. J’ai décidé de terminer mon exemple en employant la nouvelle syntaxe de NBehave. Cette fois ci je teste la classe AccountController du template de création de l’application web ASP.NET MVC 2.
De quelle nouvelle syntaxe on parle ?
Si vous vous rappelez l’exemple précédent nous avons utilisé la syntaxe fluent pour définir nos scenarios. En fait, cette syntaxe n’est plus conseillée ce que personnellement je trouve un peu dommage. Il est dorénavant préconisé d’utiliser les attributs Given/When/Then directement pour décorer les méthodes.
De plus les Stories et les Scenarios doivent être décrits dans un fichier texte externe ce qui permet de modifier les scenarios de test sans recompiler le code.
La partie pratique
Tout d’abord définissons nos scenarios de tests dans un fichier texte externe. Pour le besoin de notre exemple je crée un fichier AccoutController.scenario que j’inclus dans mon projet de tests que se présente comme ceci:
Le contenu de ce fichier contient une Story et deux Scenarios pour tester que l’utilisateur peut se logeur avec un login et un mot de passe valide et qu’un message d’erreur sera affiché dans le cas où l’utilisateur ne possède pas de login et/ou de mot de passe valide:
Story: Handle user log in
Scenario: User logs in
Given I would like to log in
When I log in as bdd with a password nbehave without remembering me
Then I should be redirected to the home page
Scenario: User doesn't log in
Given I would like to log in
When I log in as BAD with a password BAD without remembering me
Then The error message should be shown
Comme vous pouvez le constater les scenarios ne contiennent aucune ligne de code et sont compréhensibles par des utilisateurs non techniques.
Maintenant définissons notre classe de test pour les scenarios ci-dessus. La classe doit être décoré avec l’attribut ActionsSteps afin d’interpréter ce fichier de texte. Une correspondance est fait entre chaque ligne de texte et les méthodes décorées avec les attributs correspondants. Donc par exemple la phrase :
Given I would like to log in
sera mappée soit à la méthode décorée comme ceci :
1 2 |
[Given("I would like to log in")] public void AccesAccountController() |
soit à la méthode qui sera appelé de cette manière :
1 2 |
[Given] public void I_would_like_to_log_in() |
Je crois également que le CamelCase marche au lieu des “_”.
Le but de ce post n’est pas l’explication de la manière dont les tests ont été écrits mais si vous avez des questions n’hésitez pas à me faire un commentaire. En tout cas avec NBehave nos tests peuvent ressembler à ceci:
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 54 55 |
[ActionSteps] public class AccountControllerTests { private AccountController controller; private IFormsAuthenticationService formsService; private IMembershipService membershipService; private ActionResult result; private LogOnModel model;
private void SetUpController() { var controllerBuilder = new TestControllerBuilder();
formsService = MockRepository.GenerateStub<IFormsAuthenticationService>(); membershipService = MockRepository.GenerateStub<IMembershipService>(); model = MockRepository.GenerateStub<LogOnModel>();
controller = controllerBuilder.CreateController<AccountController>(new object[] {formsService, membershipService}); }
[Given("I would like to log in")] public void AccesAccountController() { SetUpController(); controller.ShouldNotBeNull(); }
[When("I log in as $username with a password $password without remembering me")] public void LogIn(string username, string password) { bool rememberMe = false;
membershipService.Stub(x => x.ValidateUser(username, password)).Return(true); formsService.Stub(x => x.SignIn(username, rememberMe));
model.UserName = "bdd"; model.Password = "nbehave";
controller.ModelState.IsValid.ShouldBeTrue();
result = controller.LogOn(model, string.Empty); }
[Then("I should be redirected to the home page")] public void RedirectToHomePage() { result.AssertActionRedirect().ToAction<HomeController>(x => x.Index()); }
[Then("The error message should be shown")] public void ShowErrorMessage() { controller.ModelState[""].Errors[0].ErrorMessage.ShouldEqual("The user name or password provided is incorrect."); } } |
A noter que notre méthode SetUpController() prépare notre contrôleur de test en lui passant tous les objets fake nécessaires.
Vous pouvez également passer les paramètres à vos méthodes à partir du fichier de texte en les marquant avec “$” comme dans la phrase ci dessus: I log in as $username with a password $password without remembering me. Le mot trouvé dans le fichier texte sera passé en paramètre à la méthode qui d’ailleurs doit accepter ces paramètres dans sa signature.
Exécution des tests
Maintenant il faut qu’en exécute nos tests pour s’assurer que tout fonctionne correctement. Pour cela nous allons utiliser la console fournie avec NBehave. La ligne de commande suivante permet d’exécuter nos tests:
NBehave-Console.exe MvcApplication.Tests.dll /sf=Specs\AccountController.scenario
Remarque: En paramètre sf nous passons notre fichier texte contenant des scénarios.
Si tout se passe bien vous devriez avoir le résultats suivant:
Conclusion
Personnellement j’aime bien l’approche BDD. Je trouve que le fait d’écrire des scénarios et des stories permet de mieux se concentrer sur la fonctionnalité métier que nous voulons tester. Concernant la nouvelle syntaxe de NBehave il y a des avantages et des inconvénients.
Avantages
- les tests sont plus facile à lire car sont écrit dans un langage naturel.
- le code de tests est plus facile à lire également.
- les stories et les scenarios peuvent être écrits par des personnes non techniques.
- possibilité de modifier les valeurs des tests sans recompiler le code.
Inconvénients
- pour le moment on est obligé d’utiliser la console de NBehave pour exécuter les tests. Je n’ai pas trouvé comment les lancer avec ReSharper ou NUnit. Si vous avez des infos là dessus je suis preneur.
- il faut tout de même modifier et recompiler le code si vous ajoutez une phrase Given/Then/When qui n’est pas mappé dans le code. Je veux dire par là que la l’utilisation du fichier texte est quand même limité.
Pour ma part, l’utilisation de NBehave est très satisfaisante. N’hésitez pas à y jeter un œil car ça vaut vraiment le coup.
A bientôt :)
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :