Recherche :

Développement Web : de la conception aux tests


Visual Studio 2010 renforce considérablement ses fonctions de développement web etde tests. Avec la gamme Expression et les technologies web telles que ASP .Net ouSilverlight, le développeur dispose de tous les outils nécessaires au développement web. Dans cet article nous allons utiliser et mettre en oeuvre Team Foundation Server. La phase d'installation est disponible sur notre site web : www.programmez.com.


MISE EN OEUVRE DU PROJET WEB
Création d'une solution Visual Studio

Compte tenu de la complexité du projet, il est souvent nécessaire de découper la solution en de nombreux projets, en fonction de règles de découpage des responsabilités assez classiques :
o Couches d'accès aux données et aux services.
o Services transverses.
o Couche métier.
o Couche présentation.

Dans le cadre de cet article, nous allons utiliser une structuration assez simple, issue d'un des nouveaux modèles de projet : le projet " Silverlight Business Application ". Ce type de projet est apporté par la couche RIA Services. Il peut être vu comme une surcouche d'un projet Silverlight classique fournissant les éléments suivants :
  • Une gestion simplifiée de l'exposition des services. Au lieu de devoir modifier manuellement les fichiers de configuration de l'application, l'exposition des classes dérivant de la classe de base DomainService se fait automatiquement (en pratique, le type de projet embarque la déclaration d'un module http dont le rôle est, entre autres, de configurer le système à l'exécution).
  • Une intégration pour le client Silverlight des informations des MembershipProvider et RoleProvider ASP .Net. Ainsi, l'application Silverlight peut utiliser les informations de login et de profil de l'utilisateur.
  • Une génération des proxies WCF à la compilation, avec possibilité de partager du code entre le serveur et le client. A la compilation, le système produit des proxies en se basant sur des informations liées à la réflexion et à certaines conventions de nommage. Ce faisant, et même s'il faut toujours revalider côté serveur ce qui est posté pour des raisons de sécurité, il est alors possible de partager les métadonnées des objets métiers avec le client, ce qui permet de réaliser des tests de validation sans avoir besoin de repasser par le serveur.
Mais avant de mettre cela en oeuvre, il faut d'abord installer quelques éléments :
  • Les outils Silverlight 4 pour Visual Studio 2010, sur http://silver-light.net/getstarted/silverlight-4-beta/#tools. Ces outils incluent la couche RIA Services.
  • Blend 3.1, sur http://www.microsoft.com/downloads/details.aspx?FamilyID=6806e466-dd25-482b-a9b3-3f93d2599699&displaylang=en. Cette version est compatible avec le nouveau format de fichier de projet de Visual Studio 2010.
  • Et pour le principe, le toolkit Silverlight, sur http://silverlight.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=36060. Ce dernier contient de nombreux contrôles complémentaires (graphiques, autocomplétion, etc.).
Une fois ces modules installés, vous pouvez enfin créer votre projet en l'intégrant au gestionnaire de source : [Fig.1] Le résultat est une solution avec deux projets :
  • Un projet Web contenant les services.
  • Un projet Silverlight contenant l'interface utilisateur. [Fig.2]
Si vous regardez les propriétés du projet Silverlight, vous verrez qu'un élément inhabituel est présent sur l'onglet Silverlight : [Fig.3] Le lien " .Net RIA Services " permet en fait d'indiquer quel projet C# doit être utilisé comme source de la génération des proxies. Et si vous regardez les fichiers cachés du projet Silverlight, vous verrez qu'un sous-répertoire " Generated_Code " a été créé : [Fig.4] Ce répertoire contient plusieurs éléments :

o Un fichier MyBusinessApplication. Web.g.cs. Ce fichier définit plusieurs classes :
-WebContext, qui contient le contexte en cours (l'utilisateur, s'il est authentifié).
-Une classe XxxContext par classe publique héritant de DomainService dans le projet C#. Par défaut, vous trouverez AuthenticationContext, permettant de dialoguer avec le service d'authentification, et RegistrationContext, pour gérer l'enregistrement d'un nouvel utilisateur.
-Les classes correspondant aux types de données consommées par les précédentes classes.
o Un fichier *. shared.cs par fichier *. shared.cs présent dans le projet C# (par défaut, un seul). Ces fichiers sont en fait recopiés : c'est donc à vous de vous assurer que le fichier compile bien en .Net et en Silverlight. Pour gérer les cas trop complexes, une directive de compilation (SILVERLIGHT) existe afin de permettre une compilation conditionnelle en fonction de l'environnement. Cette structuration est la plus simple possible. Dans le cadre d'une vraie application, les services seraient certainement définis dans des projets dédiés, tout comme les objets métiers. Un projet Silverlight ne pouvant se lier qu'à un seul projet .Net, il faut alors penser à structurer ses projets en conséquence :
- Par exemple, un projet .Net par ensembles de domaines fonctionnels.
- Pour chaque projet .Net, un projet Silverlight lié mettant en oeuvre la partie cliente associée au domaine fonctionnel.
- Et une application Silverlight mettant en oeuvre ces divers projets.
[Fig.5]

Accès au projet depuis Expression Blend

Pour pouvoir travailler sur le projet, les infographistes auront besoin de deux outils :
o Team Explorer.
o Blend 3.1 La gestion des sources est maintenant native dans Blend, il n'y a donc plus de configuration spécifique à faire ou de patch à installer. Et comme précédemment, il faut d'abord récupérer le projet avec Team Explorer sur le poste client. Une fois cela fait, lorsque le projet est ouvert dans Blend, les commandes de gestion de sources sont disponibles : [Fig.6]. Les graphistes peuvent alors directement travailler sur la solution et en modifier les écrans, sans passer par des étapes d'échanges de fichier ou de conversion de format. Typiquement, ce travail se fait en parallèle aux développements…

Partage de métadonnées et appels de services

Comme indiqué précédemment, l'un des avantages de ce type de projet est de pouvoir partager aussi des informations de métadonnées. Ces informations peuvent provenir d'un modèle EDMX si la couche de données a été générée avec Linq To SQL ou Entities Fra-mework. Mais dans le cas d'objets .Net " pur " (des POCO, pour Plain Old C# Object), il faut fournir les informations en question. Pour cela, on va utiliser un attribut introduit avec le Framework 3.5 : l'attribut MetadataType. Cet attribut permet d'associer à une classe existante une classe décrivant des métadonnéees, sans modifier la classe existante, et sans adhérence à une technologie d'interface particulière. Typiquement, ces métadonnées pourraient aussi resservir avec des projets de type ASP .Net MVC ou ASP .Net Dynamic Data. Concrètement, pour une classe donnée, disons Panier, vous devez créer une deuxième classe, comportant des champs du même nom (mais le type importe peu) :

[MetadataType (typeof (PanierMetadata))]
public class Panier
{
public double Montant { get ; set ; }
public Guid PanierId { get ; set ; }
public string NomUtilisateur { get ; set ; }
internal sealed class PanierMetadata
{
[Required]
[Range (0, double. MaxValue)]
public object Montant ;

[Required] [Key] public object PanierId ;
[Required]
[StringLength (8, MinimumLength = 8)]
public object NomUtilisateur ;
}
}
Ici, la classe fournissant les métadonnées est créée comme imbriquée à la classe définissant l'objet, mais cela n'est pas obligatoire. Par exemple, dans le cas de classes générées, ou pour des raisons de lisibilité, vous pouvez tout à fait définir cette classe et positionner l'attribut dans un fichier séparé (en définissant Panier comme une classe partielle typiquement). Les principaux éléments à retenir sont :
o L'utilisation de l'attribut Key. Cet attribut indique au système quelle est la clé unique identifiant l'objet. La présence d'un élément avec cette clé est obligatoire.
o Des attributs de validation (Range, Required, StringLength, etc). D'autres attributs existent (expressions régulières par exemple) et vous pouvez étendre le système en héritant de l'attribut Validation.

Une fois votre classe créée, vous devez l'exposer via un domaine de service :

[EnableClientAccess]
public class PanierService : DomainService
{
[Query (IsComposable = false)]
public Panier GetPanier (Guid id)
{
return new Panier () {PanierId = id, Montant = 0, NomUtilisateur
= "John Doe"} ;
}
}

Le service doit hériter de la classe DomainService et avoir l'attribut EnableAccessClient. L'attibut Query permet ici de préciser que la requête ne peut pas être utilisée comme source d'une autre requête (en clair, vous ne pouvez par associer un filtre supplémentaire lors de la composition de la requête côté client). Après avoir recompilé la solution, vous constaterez que le fichier MyBusinessApplication. Web.g.cs a changé : il inclut maintenant une classe PanierServiceContext (qui permet d'exécuter la méthode GetPanier) et une classe Panier. Cette dernière expose les champs de la classe source, les attributs liés aux métadonnées et des méthodes partielles vous permettant de modifier le comportement de la classe sans craindre de perdre votre travail en cas de regénération du code.


public sealed partial class Panier : Entity
{
#region Extensibility Method Definitions
///
/// This method is invoked from the constructor once
initialization is complete and

/// can be used for further object setup.
///

partial void OnCreated (); partial void OnMontantChanging (double value) ; partial void OnMontantChanged (); partial void OnNomUtilisateurChanging (string value) ; partial void OnNomUtilisateurChanged (); partial void OnPanierIdChanging (Guid value) ; partial void OnPanierIdChanged ();
#endregion
[DataMember ()] [Required ()] public double Montant
{
get
{ return this._montant ; }
set
{ if ((this._montant ! = value)) {
this. ValidateProperty ("Montant", value) ; this. OnMontantChanging (value) ; this. RaiseDataMemberChanging ("Montant") ; this._montant = value ; this. RaiseDataMemberChanged ("Montant") ; this. OnMontantChanged ();
} } } }

Enfin, pour créer, modifier ou supprimer des éléments, vous devez pour chaque type d'éléments devant supporter ces opérations :
o Soit définir les méthodes InsertXxx, DeleteXxx, UpdateXxx.
o Soit marquer des méthodes avec les attributs Insert, Delete, Update.

Les méthodes sont à définir dans le domaine de service, et les attributs ne sont nécessaires que si la convention de nom n'est pas respectée (ici, dans le cas de l'insertion) :


[EnableClientAccess]
public class PanierService : DomainService { [Insert]
public void CreatePanier (Panier panier) { }
[Update]
public void UpdatePanier (Panier panier) { }
[Delete] public void DeletePanier (Panier panier)

{
}
}

Une fois ces méthodes définies, lorsque le code client invoquera une sauvegarde du contexte de données, la méthode SubmitChanges de la classe de service sera automatiquement invoquée, et cette dernière invoquera alors implicitement toutes les méthodes associées aux types des données modifiées : il n'est pas utile côté client d'appeler explicitement ces méthodes pour chaque donnée gérée… Et comme en Silverlight, tous les appels sont asynchrones, pour récupérer une exception côté client, penser à utiliser la surcharge de la méthode prenant un callback en paramètre :

protected void Submit ()
{
PanierContext ctx = new PanierContext ();
ctx. SubmitChanges (OnSubmitCompleted, null) ;
}
private void OnSubmitCompleted (SubmitOperation so)
{
if (so. HasError)
{
MessageBox. Show (string. Format ("Submit Failed : {0}", so. Error.
Message));
so. MarkErrorAsHandled ();
}
}

Enfin, pour exposer une méthode qui n'est pas liée à une opération de données, pensez à marquer la méthode avec l'attribut ServiceOperation, afin qu'une méthode d'appel côté client soit générée.

TESTS DE MONTÉE EN CHARGE
Présentation de Visual Studio Team Test 2010
La version 2010 de Visual Team Test a subi une évolution majeure dans la présentation du produit. Trois versions sont maintenant disponibles pour répondre aux différents besoins de tests applicatifs :
o Visual Studio Team Test 2010 Essentials (en bleu sur le schéma ci-dessous) destinés aux testeurs non-développeurs pour création et l'exécution de cas de tests manuels ou automatiques.
o Visual Studio Team Test 2010 (en vert + bleu sur le schéma ci-dessous) destiné aux développeurs complétant les possibilités de Visual Studio Team Test 2008.
o Visual Studio Lab Management (en orange sur le schéma) destiné à la mise en place d'environnement virtualisé. [Fig.7] Nous allons ici voir la création de tests web et la mise en place de tests de charge via l'outil Visual Studio Team Test 2010.

Application Web à tester
Dans le cadre de cet article, nous utiliserons une application Web quelconque (celle créée précédemment ou tout autre) : [Fig.8]


Création d'un projet de Test
Quel que soit le type de tests à créer, la première étape consiste à créer un projet de type Test. [Fig.9]
- Par défaut, le projet de Test créé contient les fichiers suivants :
o UnitTest1.cs : Template de test unitaire.
o Fichier vsmdi : Offre une vue listant les tests présents dans la solution. Cette vue permet par exemple de sélectionner les tests à exécuter.
o Fichiers testsettings : Fichiers de configuration des tests. Le choix de la configuration à utiliser est possible via le menu " Test ".

[Fig.10]
- Le menu Test se présente de la façon suivante : [Fig.11]

Ajout d'un test Web
Dans le projet de test précédemment créé, il est possible d'ajouter un fichier de type " Web Performance Test ". Visual Studio Team Test lance automatiquement un enregistreur de requête http et un navigateur. Il nous est alors possible de naviguer sur notre site de test, toutes les requêtes client/serveur étant enregistrées. [Fig.12] Dans le cadre de cet article, le test consiste à enregistrer un nouvel utilisateur. Une fois le scénario enregistré, nous retrouvons l'ensemble des pages sur lesquelles nous avons navigué ainsi que les paramètres envoyés au serveur. [Fig.13]

MODIFICATION DU TEST WEB
Modification des requêtes
Une fois le test web créé, il est alors possible de modifier les propriétés de chaque requête, notamment le temps d'attente à simuler (ThinkTime) lors de la relance du test. Ce temps d'attente est pré rempli avec le temps d'attente lors de l'enregistrement du scénario. Ce temps nous permet de simuler la navigation d'un vrai utilisateur. [Fig.14]
Dans la version de Visual Studio Team Test 2010, une nouveauté consiste à afficher de manière globale certaines propriétés importantes de ces requêtes. (Bouton ). " Reporting Name " est aussi une nouvelle propriété qui permet de modifier le nom affiché lors de l'affichage du résultat d'exécution d'un test. Ce nom sera en effet plus compréhensible que la requête en elle-même. [Fig.15]

Paramètres des requêtes
Paramètres statiques : Le bouton permet de détecter tous les serveurs web dans les requêtes du test. Un paramètre est alors créé pour chaque serveur détecté. Les requêtes du test sont automatiquement mises à jour. Il nous sera alors plus simple de modifier les url dans le cas d'un changement de plate-forme ou de serveurs. Dans notre cas, un seul serveur a été détecté. Web Server [Fig.16]
A noter : Il est nous est possible de créer notre propre paramètre. La référence à ce paramètre est possible via la commande " {{ParameterName}} ".

À noter : Il est possible de créer des règles d'extraction qui permettent d'extraire d'une réponse des informations pour les positionner en tant que paramètre statique.

Paramètres dynamiques : Dans notre scénario, la requête de création d'un utilisateur enregistré contient les informations de l'utilisateur. Si nous relançons notre test, il sera en échec puisque l'utilisateur a déjà été créé. Il nous faut donc pouvoir utiliser une source dynamique de données pour référencer les informations des utilisateurs à créer. Le bouton permet de créer une source de données. Dans notre cas, nous utiliserons un fichier csv.
À noter : Il est possible d'utiliser une base de données SQL ou un fichier XML.

[Fig.17]
Notre source de données est alors disponible dans notre test. Trois modes d'accès aux données sont disponibles (Aléatoire, Séquentiel, Unique). [Fig.18] Nous pouvons alors modifier la requête pour utiliser cette source de données. [Fig.19]
Validation des requêtes
Pour valider qu'une requête est exécutée correctement, il est possible d'ajouter des règles de validation. [Fig.20] Les règles principales sont les suivantes :
Response Time Goal : Pourcentage autorisé pour chaque requête par rapport à la valeur de référence " Response Time Goal ", propriété propre à chaque requête.
Response Url : Vérifie que l'url de réponse est identique à celle enregistrée dans le scénario.
Required Tag/Required Attribute Value : Vérifie la présence d'un tag dans la requête de réponse.
FindText : Vérifie la présence d'un texte dans l'url de réponse. Deux nouvelles règles de validation ont été ajoutées dans cette version :
Selected option : Permet de vérifier que la valeur sélectionnée dans une combobox ou une dropdownlist est correcte
Tag Inner Text : Permet de vérifier la valeur d'un attribut HTML.
À noter : Il est possible de créer ses propres règles de validation.

Dans notre cas, nous utiliserons les règles de validation par défaut " Response Time Goal " et " Response Url ". Il nous faut donc modifier le " Response Time Goal " de chaque requête. [Fig.21]

Exécution du test Web
Le bouton permet d'exécuter le test en mode debug ou non :
[Fig.22]
L'évolution et le résultat du test sont disponibles via 2 écrans :
" Test Results " : Résultat d'exécution du test [Fig.23]
" Web test " : Résultat de chaque requête. Le nom de la requête est bien " Reporting Name " comme vu précédemment. [Fig.24]

L'onglet " Web Browser " affiche le résultat HTML de la requête.
L'onglet " Request " affiche toutes les informations de la requête envoyée (GET/POST, Headers, Cookies, QueryString, Post Parameters).
L'onglet " Response " affiche l'en-tête et le corps de la réponse.
L'onglet " Context " affiche tous les paramètres du test comme par exemple la valeur des paramètres dynamiques du test.
L'onglet " Details " affiche le résultat des règles de validation ainsi que les éventuelles exceptions.

Modification du flux d'exécution du test
L'exécution du test s'effectue de manière séquentielle. Avec la version 2010, il est maintenant possible de conditionner la logique d'exécution en ajoutant des règles de type " Loop " ou " Condition ". Dans notre cas, conditionnons le déroulement du test en vérifiant si la première page a correctement répondu.[Fig.25]
À noter : La condition peut porter sur des critères variés :

-Présence d'un cookie
-Règle de probabilité : le résultat de la condition sera aléatoire basé sur le pourcentage indiqué.
- Comparaison d'un paramètre statique et d'une valeur.
-Code de retour d'une page
- Valeur d'un cookie
-Résultat d'une requête Une fois la condition validée, elle est visible dans l'écran du test :
[Fig.26]
À noter : La règle de type boucle fonctionne sur le même principe.

Création de tests de charge
Notre test web permet de tester un scénario d'utilisation de notre application en mode mono utilisateur. L'objectif des tests de charge est donc de tester notre application en mode multi- utilisateurs. Ajoutons dans notre projet de test, un fichier de type " LoadTest ".
[Fig.27]
Ce wizard va nous guider dans la configuration de notre test de charge. Il existe 2 temps d'attente :
Celui entre 2 tests
Celui pour chaque requête.

Etape 1 : Nom du test de charge et configuration des temps d'attente :
Soit utilisation des temps d'attente enregistrés
Soit pas de temps d'attente

Soit une distribution aléatoire autour des temps enregistrés. Ici nous positionnons le temps d'attente entre chaque requête à 10 secondes et utilisons des temps d'attente enregistrés pour chaque requête. [Fig.28]

Etape 2 : Configuration de la montée en charge des utilisateurs :
Soit utilisation d'un nombre constant d'utilisateurs.
Soit utilisation d'une montée contrôlée. Dans notre cas, nous choisissons de contrôler la montée du nombre d'utilisateurs de la manière suivante : [Fig.29 et 30]

Etape 3 : Configuration des tests à exécuter. Dans notre cas, notre test de charge est basé sur un test web unique. Cette étape permet de configurer l'ordre des tests à exécuter.

Etape 4 : Choix de tests à réaliser [Fig.31]

Etape 5 : Choix des cartes réseau à utiliser. Il est possible de configurer la distribution des cartes réseaux utilisées pour ce test de charge. Cela permet de contrôler l'évolution des flux selon différents canaux. Dans notre cas, nous nous limiterons à la carte Ethernet.

Etape 6 : Choix des navigateurs. Distribution des navigateurs à utiliser pour le test de charge. Dans notre cas, nous utiliserons Internet Explorer 7 et Internet Explorer 8 (50 % chacun). [Fig.32]

Etape 7 : Configuration des serveurs à monitorer. Durant le test de charge, il faut récupérer des informations utiles sur chaque machine concernée pour pouvoir évaluer comment notre application réagit. Des profils existent en fonction de la machine ajoutée : dans le cas par exemple, d'un serveur SQL ou d'un serveur web, les compteurs de performance récupérés ne seront pas identiques, (accès au disque ou évolution du process IIS par exemple). [Fig.33] Dans notre cas, nous nous limiterons à notre serveur Web qui est aussi un serveur SQL.

Etape 8 : Configuration de la durée du test.
- Soit basée sur le nombre d'itérations des tests.
- Soit basée sur le temps.

Dans notre cas, nous limiterons notre test de charge à 20 minutes et un temps de démarrage d'une minute pour charger les 10 premiers utilisateurs et ne pas tenir compte des premières valeurs qui comprennent le temps de démarrage de l'application. [Fig.34]
À noter Le " sampling rate " permet de configurer le nombre de secondes entre chaque récupération des compteurs de performance.

Ainsi configuré, notre test est prêt à être lancé. [Fig.35]

Lancement du test de charge
Une fois lancé, il est possible de suivre l'évolution du test à travers des graphiques représentant les valeurs des compteurs de performance sélectionnés.
Evolution du test [Fig.36]
À noter : il est possible d'ajouter des graphiques pour contrôler certaines valeurs.


Configuration du test de charge
Dans notre cas, nous avons utilisé une seule et unique machine pour l'application et le test de charge. Il est cependant possible de différencier chaque rôle sur des machines différentes. (Fig.37)
À noter : Dans Visual studio 2010, le modèle de licence a changé :

Visual Studio 2008 : Le contrôleur est gratuit et une licence par processeur et par Agent est nécessaire.
Visual Studio 2010 : Le coût est basé sur le nombre d'utilisateurs à simuler. Il est donc possible d'installer autant d'agents que vous le souhaitez, l'objectif étant de ne pas dépasser le nombre d'utilisateurs virtuels achetés.

EN CONCLUSION

Ainsi se termine cette présentation des différentes étapes liées à la mise en œuvre d'un nouveau projet Web, avec :
- Mise en place d'un gestionnaire de source.
- Création du projet Silverlight.
- Instrumentation du projet pour la montée en charge. Bien entendu, il y aurait toujours plus à faire :
- Tests unitaires.
- Build quotidienne avec audit du code.
- Génération d'environnements de tests dédiés,
- Personnalisation des process et des work items. Mais cela, c'est pour une autre fois


Pierre-Charles Peullemeulle
Programmez.com - 2012 - Tous droits réservés
Développement - WEB - ASP - PHP - C++ - Delphi - Java - Magazines - Ressources - Forum - Télécharger - Video - Emploi - Campus - .Net - Tutoriels

Le présent site Web est édité par Go 02, Sarl inscrite au RCS de Paris sous le N° 411321366 et dont le siège social est au 21 rue de Fécamp 75012 Paris.
Adresse de courrier électronique :diff@programmez.com

Le directeur de la publication du site www.programmez.com est Jean-Claude Vaudecrane en qualité de gérant de la sarl GO 02

Le portail du décideur informatique en entreprise : Solutions & Logiciels