Architecture d’une application Angular 2+

L’une des nouveautés d’Angular 2 est de pouvoir organiser son application en modules. Cette nouvelle façon d’architecturer l’application est vraiment au cœur d’Angular et il est important de bien comprendre comment ça marche afin de ne pas être perdu !

La déclaration d’un module

Alors comment se déclare un module ?  Il y a de fortes chances que vous sachiez déjà comment en faire un, car une application Angular 2 est un module en soi. Voici un exemple tiré de la documentation officielle pour vous rafraîchir la mémoire :

import { NgModule }      from '@angular/core';

import { BrowserModule } from '@angular/platform-browser';

@NgModule({

imports:      [ BrowserModule ],

providers:    [ Logger ],

declarations: [ AppComponent ],

exports:      [ AppComponent ],

bootstrap:    [ AppComponent ]

})

export class AppModule { }

Cependant si votre application est un peu complexe il est conseillé de séparer votre application en plusieurs modules (« feature-module ») et de faire un module partagé par tous (« Shared Module »).

Définitions

Bootstrap : Définit les composants qui vont être chargés au lancement de l’application. Chaque application doit bootstrapper au moins un « component », en général on le nomme AppComponent. Le tableau « bootsrap » doit être utilisé uniquement dans l’AppModule.

Declarations : Contient les « component », « directive » et « pipe » utilisé dans ce module. Ne doit pas contenir de services, d’autres modules, etc. Ne doit pas contenir de composants déclarés dans un autre module !

Exports : Permet de partager des éléments du module (« component, « directive », « pipe »). On peut aussi réexporter des éléments importés d’autres modules. Un élément déclaré ne peut être qu’utilisé qu’au sein du module où il a été déclaré, sauf si ce module l’exporte.

Imports : Permet d’importer des modules et d’utiliser les éléments exportés par ces modules. Eviter des imports inutiles, c’est relativement couteux ! Et oui, pour utiliser les composants d’une librairie il faudra importer ce module de librairie dans chacun de vos modules qui en ont besoin !

Providers : Permet d’enregistrer des services. A noté que contrairement aux éléments (« component », « directive » et « pipe »), chaque service mis en tant que providers dans NgModule est enregistré à la racine de l’application, il n’est pas encapsulé dans le module où il est déclaré.

Cas concret

En suivant les conseils précédents, on obtient cette architecture :

© Deborah Kurata

 

On peut aussi rajouter un « core module » afin d’enregistrer les différents providers de votre application, ce qui permet de s’assurer qu’on ne « provide » pas plusieurs fois le même service.

Remarques sur les modules « mixtes »

Certains modules comme le RouterModule déclarent à la fois des composants et des services. Ces modules doivent donc être importés différemment dans l’AppModule et les feature-module.

Exemple pour le RouterModule :

AppModule

@NgModule({

imports: [RouterModule.forRoot(ROUTES)]

})

class AppModule{}
FeatureModule

@NgModule({

imports: [RouterModule.forChild(ROUTES)]

})

class FeatureModule{}

 

Lorsque votre application grossit, il est intéressant de ne pas charger tous les composants d’un seul coup mais de les charger à la volée selon la navigation de l’utilisateur ! C’est ce que l’on appelle les modules « lazy-load » que nous verrons plus en détails dans un prochain post 😉

En attendant, j’espère que cet article vous aura permis de mieux comprendre le fonctionnement des modules Angular et comment architecturer son application.

Migration VSTS vers TFS 2015

Récemment j’ai dû effectuer une migration d’un code source situé sur un VSTS vers le TFS 2015 On-Premise du client. C’est un scénario qui n’est pas officiellement supporté par l’outil TFS Integration Platform, mais je n’ai pas rencontré de soucis majeur (j’ai migré uniquement le code source et non les work items).

Pour rappel TFS Integration Platform est un outil développé par l’équipe ALM Rangers qui permet d’effectuer des migrations entre différentes versions de TFS. Les migrations peuvent être interrompues puis reprises. Cependant cet outil n’est plus mis à jour depuis 2012. A noter pour une migration dans le sens inverse, Microsoft a lancé un outil en preview : TFS Database Import Service for Visual Studio Team Services

Prérequis

  • un serveur SQL (SQL Express peut suffire) plus ancien que SQL Server 2014
  • le compte local qui fait tourner l’application doit pouvoir
    • Être administrateur du poste
    • Créer une base de donnée sur le serveur SQL
    • TFS Source : Être membre du groupe « Project Collection Proxy Service Accounts » et avoir des droits de lecture sur le projet
  • Disposer d’un compte pour le VSTS étant membre du groupe « Project Collection Proxy Service Accounts » et avoir des droits de lecture/écriture sur le projet (il peut être différent du compte local)
  • Visual Studio 2012 Pro ou supérieur (Team Explorer 2012 n’est plus disponible en standalone)

Installation

Après avoir double-cliqué sur le .msi, l’écran ci-dessous apparaît. Ici rien de particulier, installer juste le « TFS Integration Tools ».

Vous arrivez ensuite à cet écran où on vous demande la chaîne de connexion SQL, n’oubliez pas qu’à l’installation l’outil va créer une BDD, votre compte doit donc avoir les droits suffisants sur le serveur.

Bravo l’outil est maintenant installé, passons à la création de la migration !

Migration pas à pas

Voici l’écran d’accueil de l’application. La première chose à faire est de cliquer sur « Create New » (colonne de droite).

Avec l’explorateur Windows allez dans le dossier « Team Foundation Server » si ce n’est pas le cas et choisissez « VersionControl.xml ».

Il faut maintenant configurer la migration, veuillez cliquer sur « Configure » et choisir « VC11 Adapter » :

Sélectionner ensuite votre Team Project de source/cible :

Il ne reste plus qu’à lancer la migration et à résoudre les conflits s’il y en a. A noter que vous pouvez très bien mettre en pause la migration ou la finir une première fois, effectuer quelques commits sur la branche source et la relancer. Cela permet une interruption de service plus courte si une équipe est en train de travailler sur le projet durant la migration.

Une dernière petite astuce pour la route, je conseille de faire la migration sur une nouvelle VM que vous « jetterez » après la migration. Cela évite ainsi de polluer son poste de travail avec une vieille version de VS et de se prémunir d’un éventuel redémarrage de son poste de travail alors que la migration est en cours.

La migration est assez longue car vous aurez surement des conflits à résoudre donc je vous conseille de ne pas l’effectuer si vous avez une quantité importante de données.

 

Retour d’expérience SignalR avec load-balancing

Dans cet article je vais parler d’un cas d’utilisation assez avancé de SignalR : faire communiquer plusieurs applications Angular en temps réel via SignalR, chaque application étant load-balancée sur 2 serveurs. Etant donné que c’est un cas avancé, je considère que vous savez déjà comment fonctionne SignalR (si ce n’est pas le cas, il est très facile de trouver des bons tutoriels sur Google).

Architecture

En effet plusieurs applications peuvent communiquer entre elle via SignalR si celles-ci utilisent la même base de données et le même nom pour le hub. Pour un tutoriel sur comment configurer le Scale-Out SQL Server pour SignalR, je vous conseille celui de Microsoft.

Flux du message au sein de l’application

 

 

signalR

Comme vous pouvez le voir avec le schéma ci-dessus, on a décidé de propager le message SignalR au sein de l’application Angular en « broadcastant » un nouveau message. Ceci permet d’avoir une méthode unique pour effectuer la communication entre le serveur (C#) et le client qui ne fait pas intervenir de code métier.

Voici la classe utilisée pour le message :

public class ChannelEvent<T>
{

public string Id { get; private set; }

public string EventName { get; set; }

public string Timestamp { get; private set; } = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.fff");

public T Data { get; set; }

public ChannelEvent(string eventName, T data)
{
EventName = eventName;
Data = data;
Id = $"{EventName}:{Guid.NewGuid()}-{Timestamp}";
}

}

Côté client, vu que l’application utilisait Angular, nous avons créé un service pour encapsuler le hub.

Le service : 

import { Injectable, Inject } from "@angular/core";
import { Injectable, Inject } from "@angular/core";
import { Subject } from "rxjs/Subject";
import { Observable } from "rxjs/Observable";
import { Broadcaster } from './BroadCasterService';

@Injectable()export class EventHubService {
   public hubConnection: any;
   private hubProxy: any;
   private lastEventsIds = new Array<string>();

   constructor(    
     @Inject(Broadcaster) private broadcaster: Broadcaster)
  {
    this.hubConnection = window.$.hubConnection(window.location.href);
    this.hubProxy = this.hubConnection.createHubProxy("myHub");
    this.hubConnection.error((error: any) => {
    this.errorSubject.next(error);        });
    this.hubProxy.on("send", (ev: Models.ChannelEvent<any>) =>
    {
       if (this.IsNew(ev)) {
         this.broadcaster.broadcast(ev.EventName, ev.Data);
       }
    });
  }
  /** On évite de publier plusieurs fois le même message côté client. Cela peut arriver si par exemple, une personne est dans plusieurs groupes */
  IsNew(ev: Models.ChannelEvent<any>): boolean {
    if (Enumerable.from(this.lastEventsIds).any(x => x === ev.Id)) {
      return false;
    }
    else {
      this.lastEventsIds.push(ev.Id);
      return true;
    }
  }
}

Le broadcaster : service utilisé dans tout l’application pour faire communiquer les composants entre eux, et utilisé aussi par le service ci-dessus.

@Injectable()
export class Broadcaster {

private _eventBus: Subject<BroadcastEvent>;

constructor() {
 this._eventBus = new Subject<BroadcastEvent>();
 }

broadcast(key: any, data?: any) {
 this._eventBus.next({ key, data });
 }

/**
 * NE PAS OUBLIER DE SE DESINSCRIRE SINON L'INSTANCE RESTE EN MEMOIRE !!
 * @param key
 */
 on<T>(key: any): Observable<T> {

return this._eventBus.asObservable()
 .filter(event => event.key === key)
 .map(event => <T>event.data);
 }
}

interface BroadcastEvent {
 key: any;
 data?: any;
}

A savoir

  • Ne pas hésiter à faire une interface pour tester l’envoi de message et vérifier l’état de la connexion SignalR
  • SQL Server n’est pas viable comme Scale-Out pour SignalR si la contrainte temps réel est forte (le Service Broker peut mettre jusqu’à 3 minutes pour notifier si la charge est très importante)
  • Ne pas créer trop de groupes SignalR (> 1 000 ça ralentit)
  • Faire attention à ce que le load balancer laisse passer les web sockets
  • Prérequis : SQL Server 2005+, Windows Server 2012 / Win8 (iis 8.0)

 

Je pense que ce cas d’utilisation de SignalR, même s’il est complexe peut régulièrement être utilisé en entreprise où un utilisateur doit jongler entre plusieurs applications. Cela lui évite de devoir attendre et de rafraîchir la page manuellement, ou d’être automatiquement prévenu qu’un collègue est déjà en train d’éditer cet objet (contrat, client..).

EF6 : Tips&Tricks

EF Core va bientôt prendre la relève mais je pense que EF6 va continué son chemin pendant encore un bon bout de temps avant de disparaître ! C’est pourquoi je me suis dit que j’allais partager avec vous toutes les petites astuces que j’ai découvert ces dernières années.

I. Performances

1) READ_COMMITTED_SNAPSHOT

C’est un paramètre SQL Server au niveau de la base de donnée qui est mis de base en code first, et qui permet « potentiellement » une meilleur scalabilité et moins de deadlocks.

En gros, ça crée un snapshot de la base en read-only sur lequel les SELECT seront executé. Quand un changement s’effectue (par ex : un UPDATE) il s’effectue sur la base (et non sur le snapshot) et un nouveau snapshot de la base est créé.

Ce paramètre est particulièrement adapté lorsque la majorité des requêtes effectuées sont des SELECT.

Commande :

ALTER DATABASE <dbname> SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE <dbname> SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE <dbname> SET MULTI_USER;

2) Warm-up

Lors de la 1ère requête à un Model, EF fait beaucoup de choses avant de pouvoir l’exécuter, cela peut facilement prendre 5-6sec !

Afin d’éviter cela vous pouvez améliorer les choses à plusieurs niveaux, mais personnellement j’ai choisi de contourner le problème en maintenant à chaud mon site sous IIS. Voir cet article de blog pour plus d’infos.

Vous pouvez aussi décider d’utiliser NGEN qui permet d’éviter que l’assembly d’EF (qui est grosse, environ 5Mo) soit JIT à chaque lancement. On peut gagner environ 1-3secondes.

Vous pouvez aussi consulter cet article MSDN pour en savoir plus ce qui se passe et les différentes pistes d’amélioration possibles.

3) Les méthodes async

Sur un site web ou une Web Api le nombre de thread est limité et l’utilisation des méthodes Async de EF permet de libérer le thread courant afin qu’il commence le traitement d’une requête le temps que la base de donnée retourne le résultat.

Plus d’infos sur cet article de blog ou cet article msdn.

4) NoTracking

Lorsque vous faites une requête avec EF, l’état de l’objet est ensuite tracké par le contexte. Régulièrement on n’a pas besoin de ce tracking et cela entraine juste une hausse des consommations CPU/RAM et une perte de performance, surtout dans le cadre de recherche où le nombre d’items retournés est élevé !

Pour éviter de tracker, rien de plus simple, il suffit de rajouter AsNoTracking() à la fin de la query !

Exemple :

var blogs2 = context.Blogs
 .Where(b => b.Name.Contains(".NET"))
 .AsNoTracking()
 .ToList();

5) NCache

NCache est passé OpenSource et peut servir de cache de 2nd niveau pour EF.

6) Break queries

Afin d’améliorer les performances il est souvent préférable de découper une grosse requête en plusieurs petites afin de limiter le nombre d’include.

7) Optimiser les Update via des jointures conditionnelles

Le cas standard d’un update avec EF est le suivant :

L’utilisateur modifie quelques champs -> le client envoie au serveur l’entité entière -> on récupère le graph complet de l’entité côté serveur -> on mappe les champs -> on sauvegarde

Une optimisation courante est donc d’effectuer uniquement les jointures dont on a besoin pour mettre à jour l’entité en base.

La détection du changement peut être faite via le calcul des hashs des entités enfants côté serveur au moment du Get. On recalculera ces mêmes hashs au moment de la sauvegarde et on comparera les hash entre le Get et l’Update pour voir si l’entité enfant doit être mise à jour, et donc si la jointure doit être faite.  Les hashs seront stockés dans une variable au niveau de chaque entité enfants. Pour économiser des cycles CPU serveurs ou de la bande passante ce calcul de hash peut être déporté sur le client.

Exemple

 IQueryable<CLIENT> query = _database.CLIENT; 
 if (clsPersonne.hashIdentiteContactPhysiqueAvant != clsPersonne.hashIdentiteContactPhysiqueApres) 
 query = query.Include(x => x.IDENTITE_CONTACT_PHYSIQUE); 
 ...
 ...
 var client = query.SingleOrDefault(x => x.Id = clsPersonne.Id);

8) Entity Framework Extended Library

Librairie pour EF permettant d’ajouter des fonctionnalités à EF comme les Batch Update/Delete (de base dans EF, on ne peut mettre à jour qu’une ligne par requête).

Permet aussi de gérer un cache simpliste.

9) Au cas où…

N’oublier pas de vérifier vos index et que vos types de données correspondent !

 

2. Les requêtes

1) Mémo pour gérer les graphs d’entités

 

2) Find au lieu de SingleOrDefault

La méthode Find de DbSet permet d’aller récupérer une entité du contexte via sa Primary Key, si l’élément n’est pas trouvé dans le contexte, l’élément est récupéré depuis la base.

Alors qu’avec SingleOrDefault la requête sera toujours exécutée.

3) Logger / Intercepter les requêtes SQL

Une nouveauté peu connue de EF 6.1 est de pouvoir logger les requêtes SQL très facilement, il suffit d’ajouter dans le .config :

<interceptors>
 <interceptor type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework">
 <parameters>
 <parameter value="C:\Temp\LogOutput.txt"/>
 <parameter value="false" type="System.Boolean"/>
 </parameters>
 </interceptor>
 </interceptors>
  • Booléen à False : Le fichier est réécrit à chaque fois que l’application redémarre
  • Booléen à True: Le texte est ajouté à la fin du fichier

4) Func<> vs Expression<Func<>>

Si on souhaite réaliser un filtre, par exemple:

Expression<Func<YourEntity, bool>> FilterByNameLength(int length)

{

return x => x.Name.Length > length;

}

On l’utilise de la manière suivante :

context.Table.Where(FilterByNameLength(500));

Si vous passer une Func<> à une query EF (pour appliquer un filtre par exemple), la méthode ne sera pas traduite en SQL et sera appliquée a posteriori ce qui est rarement ce que l’on souhaite.

Alors que si on utile une Expression<Func<>> la méthode sera bien traduite en SQL.

5) eSQL

Entity SQL (eSQL) est un language indépendant du stockage permettant de récupérer des données sous formes d’objets ou de forme tabulaire. Cela peut être très pratique pour créer des requêtes dynamiques.

Exemple :

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    string esqlQuery = @"SELECT VALUE Contact
        FROM AdventureWorksEntities.Contacts as Contact where Contact.LastName = @ln";

    // The following query returns a collection of Contact objects.
    ObjectQuery<Contact> query = new ObjectQuery<Contact>(esqlQuery, context, MergeOption.NoTracking);
    query.Parameters.Add(new ObjectParameter("ln", "Zhou"));

    // Iterate through the collection of Contact items.
    foreach (Contact result in query)
        Console.WriteLine("Contact First Name: {0}; Last Name: {1}",
                result.FirstName, result.LastName);
}

6) UnitOfWork

C’est un design pattern qui permet d’abstraire toute la couche de persistence tout en évitant de réinstancier le DBContext à chaque opération (ce qui permet aussi de faire des transactions très simplement). Voir cet article msdn pour plus d’informations.

7) DbFunctions

Cette méthode possède des fonctions utilitaires afin d’effectuer des opérations sur les dates au sein des requêtes EF. Voir la doc MSDN.

8) Jointures externes

Pour cela il faut utiliser DefaultIfEmpty, on l’utilise de la manière suivante :

var q = from c in categories

join p in products on c equals p.Category into ps

from p in ps.DefaultIfEmpty()

select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };

III. Divers

1) EF Power Tools

C’est une extension Visual Studio qui permet notamment de :

  • Reverse Engineer Code First : Génère le DBContext, les POCO et le mapping Code First à partir d’une base de données existante (option de base dans VS 2015, via l’ajout d’un modèle ADO.Net)
  • Customize Reverse Engineer Templates : Ajoute le template T4 à votre projet afin de pouvoir customiser la génération de code
  • View Entity Data Model (Read-only) : Affiche une vue du modèle Code First dans le EF designer?
  • View Entity Data Model XML : Affiche l’EDMX XML représentant le Code First.
  • Generate Views : Génère des vues précompilées afin d’améliorer le temps de démarrage de l’application

Plus d’infos ici : https://msdn.microsoft.com/en-us/data/jj593170.aspx

2) Pluralization Service

Vous avez déjà dû le remarquer mais EF possède un algorithme pour mettre aux pluriels les variables, il supporte seulement l’anglais mais vous pouvez faire votre service custom et le pluger à Entity Framework.

Voir cet article pour plus d’infos

 

Voilà, j’espère que vous avez appris quelques petits trucs qui vous faciliteront la vie 😉

Tricks : Gérer son numéro de version au niveau de la solution

Si comme moi, vous avez toujours rêvé de pouvoir gérer son numéro de version au niveau de solution et non au niveau de chaque projet cet article est fait pour vous !

Marche à suivre

  1. Click droit sur la solution -> Ajouter un nouvel item -> Classe Visual C#
  2. Nommez le fichier « SharedAssembyInfo.cs »
  3. Reprenez toutes les infos d’un « AssemblyInfo.cs » d’un projet existant et copier-coller le contenu dans « SharedAssembyInfo.cs ». Les fichiers « AssemblyInfos.cs » se trouvent dans la rubrique « Properties » située juste au-dessus de « Références ».
  4. Mettez en commentaire tout le contenu des différents « AssemblyInfo.cs »
  5. Sur chaque projet :
    1. Click droit -> Ajouter élément existant
    2. Sélectionner le « SharedAssembyInfo.cs »
    3. Choisir d’ajouter en tant que lien
    4. Faites glisser le fichier ajouté au projet dans le dossier « Properties »

A savoir

Vous n’êtes pas obligé de partager toutes les informations dans le « SharedAssembyInfo.cs », tout ce qui est spécifique à chaque projet vous pouvez le laisser dans le « AssemblyInfos.cs » du projet.

Pour allez plus loin

Savez-vous que vous pouvez générer un numéro de build sans usine de build depuis Visual Studio? Pour cela il suffit de :

  1. Mettre en commentaire l’attribut « [assembly: AssemblyFileVersion(« 1.0.0.0 »)]» que l’on trouve dans « SharedAssembyInfo.cs » ou « AssemblyInfos.cs ». Seul l’attribut « AssemblyVersion » doit être spécifié.
  2. Mettre l’attribut « AssemblyVersion » sous la forme : « [assembly: AssemblyVersion(« Majeur.Mineur.* »)] »

Après ça, à chaque build, Visual Studio va remplacer l’étoile par un « numéro de build » et un « numéro de révision » :

  • Numéro de build : Le nombre de jour depuis le 1er Janvier 2000.
  • Numéro de révision : Le nombre de secondes depuis minuit divisé par 2.

 

J’espère que cet article vous aura été utile 😉

 

Sources

http://weblogs.asp.net/ashishnjain/sharing-assembly-version-across-projects-in-a-solution

http://www.csharpcity.com/2012/visual-studio-automatic-version-numbering/

https://msdn.microsoft.com/en-us/library/k49w9389(v=vs.110).aspx

Microsoft Test Manager : Tester un Build

Dans la 1ère partie nous avons vu comment configurer un environnement de test pour Microsoft Test Manager. Nous allons maintenant nous intéresser à comment tester un build sur un environnement configuré et comment faire en sorte que toutes les données qui nous intéresse soient bien collectés, en l’occurence, les données de « Test Impact Analysis« . Ces données permettent de détecter quels tests rejoués en fonction des changement apportés aux code source !

Marche à suivre

  1. Configurer Test Manager pour qu’il se lance toujours en mode administrateur (sinon il n’aura pas les droits pour observer les autres process)
  2. Paramétrer Test Manager (testeur) pour qu’il utilise la configuration créée précédemment en Test settings et la machine où va être déployé l’application comme environnement :
  3. Queue un  XAML build, attendre qu’il finisse. Le premier build va permettre de constituer une base sur laquelle le moteur pourra analyser les différences avec les prochains builds. 
  4. Effectuer le déploiement
  5. Assigner le build au test, une pop-up vous proposant de voir les tests recommandés s’affichera. Assigner un build aux tests permet d’attacher les données de tests à ce build.
  6. Run le Test Plan
  7. Après avoir cliqué sur « Start Test » (pas besoin de coché « Create action recording »), lancer l’application en mode Administrateur afin que le processus tourne avec le même compte utilisateur.
    4
  8. Vérifier à la fin du 1er cas de test que les fichiers « testImpact.xml » et [webServer].testImpactXml sont bien mis en pièce jointe. S’ils ne sont pas présent regarder si vous n’avez pas des fichiers warning afin de déceler des erreurs. 

A Savoir

  • Aucune notification n’apparait si un problème a empêché la collecte d’informations nécessaire à l’analyse
  • Il ne supporte pas bien les multithread/méthodes asynchrone
  • Il détecte correctement le changement de code dans le XAML
  • Test Impact Analysis n’existe pas encore avec le nouveau système de build vNext.
  • Il est préférable qu’un seul application pool utilisant le compte de service tfs et que celui-ci n’ai qu’un seul site web.
  • Le démarrage d’une suite de tests redémarre le serveur IIS

 

Cette procédure fonctionne aussi pour les autres données de tests que l’on peut collecter et rattacher à un build. A ce propos, il faut savoir que pour les données de couverture de code nécessite de labelliser les sources lors du build.  Les données de tests récoltés sont consultables sur le résumé du build dans le portail web tfs (et l’interface est plutôt bien fait !)

J’espère que cette série vous en a appris plus sur les fonctionnalités de Microsoft Test Manager 🙂

Microsoft Test Manager : Créer et utiliser un environnement de Test

Vous connaissez peut-être Microsoft Test Manager, l’outil de Microsoft dédié aux testeurs. Sachez qu’en plus de l’organisation de cas de tests, cet outil permet aussi de collecter des données durant les tests notamment :

  • Les informations système (OS, Naviguateur)
  • Les évènements systèmes
  • Les events Intellitrace
  • La couverture de code du test
  • Les actions utilisateurs (bouton cliqué, texte saisie, etc)

Ces données peuvent tout aussi bien être collectés côté client que côté serveur ! Et quand je dis côté serveur c’est que l’applicatif arrive à tracer les requêtes effectuées au site web IIS faisant tourner vôtre API !

Pour collecter côté client, rien de plus simple le Test Runner intégré à Microsoft Test Manager se charge de tout, mais pour collecter côté serveur, cela nécessite une bonne dose de configuration que nous allons voir ensemble. Dans ce tutoriel nous allons créer un environnement de test pour une application composée d’un client WPF communiquant avec une WebApi.

Cette série de posts sur « Microsoft Test Manager : Créer et utiliser un environnement de Test » sera composée en 2 partie :

  1. Créer un environnement de Test
  2. Tester un build dans un environnement de test

Prérequis :

  • TFS XAML Build
  • License Visual Studio Enterprise ou Test Professionnal
  • 1 application avec du code managé pouvant être traduit en Common Intermediate Language
  • Un compte de domaine TFSTEST
  • Un serveur où seront déployées les applications à tester : TFSTESTSERVEUR
  • Télécharger l’ISO des derniers agents pour Visual Studio 2013 (en effet les agents 2015 ne sont pas compatibles avec Lab Center / Test Manager)
  • Microsoft Test Manager installé sur le poste du testeur
  • Des campagnes de tests dans Microsoft Test Manager

Pour installer le contrôleur et les agents vous pouvez choisir :

  • D’installer le contrôleur sur votre machine de build et les agents sur TFSTESTSERVEUR
  • D’installer le contrôleur sur la machine faisant tourner TFS Web App et les agents sur TFSTESTSERVEUR
  • D’installer le contrôleur et les agents sur TFSTESTSERVEUR

 

Le compte TFSTEST doit être ajouté au groupe administrateur des serveurs où sont installés le contrôleur et/ou les agents (notamment TFSTESTSERVEUR)

L’environnement de test sera ici un « environnement standard » et non un « environnement virtuel »

 

Installer et configurer le Test Contrôleur

  1. Monter l’ISO et à partir du dossier TestController et installer le contrôleur sur TFSTESTSERVEUR.
  2. Le configurer pour qu’il tourne avec le compte TFSTEST et le connecter à la bonne « Collection de projets d’équipe »

image001

  1. Cliquer sur « Appliquer»

 

Installer les agents sur TFSTESTSERVEUR

  1. Monter l’ISO et à partir du dossier TestAgent installer l’agent de test
  2. Configurer l’agent de test pour qu’il tourne avec le compte TFSTEST et l’enregistrer auprès du contrôleur précédemment installé.
  3. TODO Screenshot
  4. Cliquer sur Appliquer

Pour plus d’infos n’hésitez pas à consulter : https://msdn.microsoft.com/en-us/library/hh546460.aspx

 

Créer l’environnement avec Microsoft Test Manager

  1. Allez dans Lab Center puis choisissez l’onglet Contrôleur, vérifiez que votre contrôleur est en ligne.image003
  2. Allez dans l’onglet « Lab », cliquer sur « Nouveau »image005
  3. Etape « Type et nom » : Choisir « Environnement standard » et attribuer un nom
  4. Etape « Ordinateurs » :
    1. Ajouter TFSTESTSERVEUR
    2. Saisir les identifiants du compte TFSTEST
    3. Choisir le type Web Server
  5. Etape « Propriétés de l’ordinateur» : ras
  6. Etape « Avancée » : ras
  7. Etape « Vérification » : Cliquer sur « Vérifier », si tout se passe bien l’environnement devrait être créé.
  8. Cliquez sur « Terminer», l’outil va installer les agents et les configurer sur TFSTESTSERVEUR

Pour plus d’infos n’hésitez pas à consulter :  https://msdn.microsoft.com/en-us/library/ee390842.aspx

 

Créer la configuration de Test avec Microsoft Test Manager

  1. Dans «Lab Center», aller dans « Paramètres de tests » et cliquer sur nouveau
    1. Etape « Général» : Saisir un nom, une description et choisir le type « Manuel »
    2. Etape « Rôles » : Choisir Serveur Web
    3. Etape « Données et Diagnostics » : image008
    4. Etape « Résumé » : Cliquer sur Terminer

 

Et voilà, la configuration de l’environnement est enfin terminée ! A présent vous allez pouvoir collecter les données dont vous avez besoin aussi bien côté client que côté serveur ! Dans le prochain post nous verrons comment rattacher ces données de tests à un build, ce qui va notamment permettre d’utiliser une fonctionnalité unique de TFS, Test Impact Analysis (un algorithme permettant de calculer les tests à rejoués entre 2 builds !).