mardi 8 mai 2012

Intégration des tests dans le cycle projet scrum et l'équipe

Bonjour à tous,

Aujourd'hui je vous propose un article que j'ai co-écrit avec un de mes collègues (Fabien Guede), et qui concerne l'organisation des tests dans nos projets Scrum.
Cet article indique l'organisation mise en place à ce jour sur nos projets de développement asp.net Mvc. Vous remarquerez que nous adressons plusieurs types de tests qu'ils soient automatisés ou manuels : tests unitaires, tests de navigation, tests d'interface et tests exploratoires.

Ces pratiques ont émergées au fil des itérations et des projets, à la lecture de divers blogs, participations à des conférences sur l'agilité (Scrumday, XP days, Journée agile...) et de différents ouvrages sur l'agilité ("Agile Testing" de Lisa Cispin et Janet Gregory...).

Bonne lecture et à vos commentaires !
Lien vers l'article: http://fabienguede.blogspot.be/2012/04/integration-des-tests-dans-le-cycle.html

vendredi 30 mars 2012

Introduction à Microsoft Code Contracts

Hello world,

I just saw a very great video where Greg Young made an introduction to Microsoft Code Contracts. I recommand it for every .net users who want to improve their skills.

Enjoy.

http://www.infoq.com/presentations/Contracts-Library

jeudi 31 mars 2011

Scrumday 2011 : retours à chaud

lien vers le site scrumday : http://www.scrumday.fr/

Aujourd'hui je suis allé à Paris (Issy les Moulinaux très exactement) dans les locaux de Microsoft pour assister au Scrumday 2011, organisé par Microsoft et le French Scrum User Group.
Mes objectifs étaient d'une part de me faire une idée sur l'adoption de l'agilité dans les DSI et les SSII, et d'autre part de voir quelles pratiques étaient utiliser et celles qui ne le sont pas ou peu. Tout ça bien sûr dans l'optique très altruiste de situer et tenter d'évaluer -avec toute l'objectivité qui s'impose, :)- l'implémentation de l'agilité dans notre service de développement.
Rassurez-vous l'objet de mon billet n'est pas de vous parler du résultat de mon introspection mais plutôt de vous mettre en avant les sessions auxquelles j'ai assistées et qui ont vraiment attirés mon attention.
Je parlerai donc de deux :
- "ScrumMasters, devenez le coach de votre équipe agile" animé par Véronique Messager, dans le track ADOPTION.
- "Quarante ans de crise, dix ans d'agilité" présenté par Laurent Bossavit, Directeur de l'Institut Agile, dans le track PRATIQUES AGILES.

Dans sa présentation, Véronique Messager a aborder les missions de coaching qu'un Scrum master doit ou devrait adresser. Son message, auquel j'adhère complètement, est qu'être scrum master demande des connaissances en management et en "psychologie" pour pouvoir correctement faire ce travail de coaching. Wow ! Quel changement de mentalité cela demande à nos chefs de projets.  Devoir se soucier des relations humaines là où on leur avait toujours fait comprendre que ce qui compte c’est le respect des délais et des spécifications !
Je ne sais pas si cette présentation a été filmée et sera diffusée sur un site ou un autre mais si c’est le cas je la conseille à tous celles et ceux qui s’intéressent à scrum et en particulier au rôle de scrum master.
Par ailleurs et pour soumettre mon point de vue à ceux qui liraient ce billet (n’hésitez pas à laisser un commentaire), je pense que même si l’adoption de Scrum, pour des raisons de ressources humaines, passe naturellement par des équivalences MOA devient Product Owner et chef de projet devient scrum master, il apparait assez clairement que l’on parle ici de nouveaux métier ou de mutation très forte de ces métiers. Et ce à un point tel que tous les  chefs de projet ne pourront pas ou n’auront pas envie de devenir scrum master. Il faudra donc créer ces nouveaux spécialistes de ces métiers, ce qui nous amène à la deuxième session que je recommande.

Ayant découvert récemment l'institut agile (cf mon billet précédent) j’ai recherché un peu plus d’informations à son sujet et je suis tombé en début de semaine sur un podcast sur Visual Studio Talk Show où Laurent Bossavit le créateur de l’institut agile, était l’invité. Je vous le conseil vivement et il vous apportera des réponses sur les missions de cet institut.
Pour en revenir à la session, Laurent Bossavit nous livre une partie d’histoire sur l’ingénierie logicielle pour aider à comprendre pourquoi un tel engouement pour les méthodes agiles mais aussi pourquoi leur mauvaise transmission et compréhension pourrait leur être préjudiciable à moyen terme. Si toutefois la présentation d’aujourd’hui n’est pas téléchargeable dans les prochaines semaines, Laurent Bossavit a annoncé qu’il y aurait fin avril, probablement à Paris, une conférence organisée par l’institut agile pour le présenter. Ce sera donc probablement l’occasion pour lui de reparler de ce qu’il a présenté aujourd’hui et pour vous d'aller le rencontrer.

Globalement cet événement était vraiment bien préparé et les sujets couverts étaient intéressants et comme souvent on aimerait pouvoir se dédoubler pour suivre 2 ou 3 sessions positionnées sur le même créneau horaire. Mon seul regret, dommage pour la session « Mode Forfait et Méthode Scrum : Les frères ennemis ? » que je n’ai pas pu suivre car la salle était plus que pleine.

Bonne continuation à toutes et tous.

lundi 28 mars 2011

L'agilité dans un monde commercial

En 2009 lorsque j'ai commencé à m'intéresser sérieusement à l'agilité j'étais aller aux xpdays à Vincennes (devenue conf agileen 2010). J'y avais rencontré un monde d'extra-terrestres où les projets informatiques n'étaient pas que des aventures techniques et des délais, mais aussi des aventures humaines... J'ai découvert et redécouvert les concepts d'équipe, d'informatique hédoniste et d'autres sujets qui m'étaient apparus tabou dans le monde de l'entreprise.

Une session était co animée par Eric Lefevre Ardant et Laurent Bossavit : "Is Srcum Evil ?". De la, plusieurs questions autour de la certification à grande échelle, le galvaudage des mots clés de l'agilité, les abus prévisibles de certaines sociétés de services autour de l'agilité, l'identité des faussaires et des "vrais" praticiens de l'agilité... On pourrait parler ici de déontologie.

Laurent Bossavit à justement créer "l'Institut agile" qui semble tout à fait adresser ces sujets. Ceci peuvent paraitres idéalistes mais dans un contexte où tout est du commerce pour certains et que les projets informatiques sont vitaux pour d'autres il ne faudrait pas qu'une des valeurs, à mon avis phare de l'agilité qu'est la confiance perde en crédibilité. Il fallait essayer quelque chose et je crois que c'est ce que Laurent Bossavit a fait.

Je salue cette initiative en espérant qu'elle ne sera pas perçue comme une lubie d'élitiste et qu'elle permettra aux "clients de l'agilité" de mieux s'y retrouver parmis les prestataires dont le nombre ne cessent de croître.

mercredi 12 janvier 2011

Only parameterless constructors and initializers are supported in LINQ to Entities.

Linq to Entities est parfois un peu déconcertant, voici donc une déconvenue que j'ai rencontré sur un de mes récents développements.
"Only parameterless constructors and initializers are supported in LINQ to Entities."

Le code qui déclenche cette erreur est le suivant :

var events = (from c in _articleRepository.FindEvenementArticles()
orderby c.DatePublication descending
select new ArticleDto(c)
).Take(10);

une correction possible :
var events = (from c in _articleRepository.FindEvenementArticles()
orderby c.DatePublication descending
select new ArticleDto()
{
  Id = c.IdArticle,
  ContenuHtml = c.ContenuHTML
  }
).Take(10);

une autre correction possible :


var retList = new IEnumerable();


var events = (from c in _articleRepository.FindEvenementArticles()
orderby c.DatePublication descending
select c
).Take(10);


foreach (var e in events)
{
   retList.Add(new ArticleDto(e);
}

mardi 4 mai 2010

My WCF application is not called by TFS 2010 Event Service

For TFS 2010 be able to contact your WCF you have to use the WSHttpBinding and you have to specify a bindingConfiguration that disable the security. You can see below what I use for mine.

I hope that will help someone (at least Nicolas M).


ITfsEventSubscriber.cs :


...
[ServiceContract(Namespace = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03")]
public interface ITfsEventSubscriber
{
    [OperationContract(Action = "http://schemas.microsoft.com/TeamFoundation/2005/06/Services/Notification/03/Notify")]
    void Notify(String eventXml, String tfsIdentityXml);
}
...



TfsEventSubscriber.cs :

...
public class TfsEventSubscriber : ITfsEventSubscriber
{
    void ITfsEventSubscriber.Notify(String eventXml, String tfsIdentityXml)
    {
        // My notify code
    }
}
...



Web.config :


...
<system.serviceModel>
    <bindings>
     <wsHttpBinding>
        <binding name="NoSecurity">
         <security mode="None">
         </security>
        </binding>
     </wsHttpBinding>
    </bindings>
    
    <services>
     <service behaviorConfiguration="WcfTfsDeployer.Behavior" name="WcfTfsDeployer.TfsEventSubscriber">
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="NoSecurity" contract="WcfTfsDeployer.ITfsEventSubscriber" />
     </service>
    
    </services>

    <behaviors>
     <serviceBehaviors>
        <behavior name="WcfTfsDeployer.Behavior">
         <serviceMetadata httpGetEnabled="true"/>
         <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
     </serviceBehaviors>
    </behaviors>
</system.serviceModel>



...

lundi 3 mai 2010

What's new with BisSubscribe in TFS 2010

Hi all,

We currently migrating our Team Foundation Server 2008 to TFS 2010 and have some little issues, so I found a solution around BisSubscribe.exe that I want to share with all.

I tried to subscribe our WCF service that intercept the build quality change event to deploy our web sites on diffrent severs. But with using the BisSubscribe.exe syntax I knew with TFS 2008 it's failed with this message :


....
Exception Message: Event type BuildStatusChangeEvent does not exist. (type TeamFoundationServiceException)
...



With TFS 2008 a subscription looked like :

bissubscribe /eventType BuildStatusChangeEvent /address http://myWebServer/MyService/myNotificationService.asmx /deliveryType Soap /server http://tfsserver:8080


For TFS 2010 due to the Team Project Collection the url of the parameter /server is not functionnal and you have to use /collection instead, like this sample :

C:\Program Files\Microsoft Team Foundation Server 2010\Tools>BisSubscribe.exe /eventType BuildStatusChangeEvent /address http://myWebServer/MyService/myNotificationService.asmx /deliveryType Soap /collection http://tfsServer:8080/tfs/MyCollection


Where MyCollection is the Team Project Collection where you want to subscribe. It's appear the /server doesn't work well with all events (like BuildStatusChangeEvent).

I hope that could help someone !

mardi 9 mars 2010

Retour d'expérience sur notre implémentation de Scrum

Il y a un an j'ai démarré des recherches sur comment améliorer la gestion de nos projets informatiques dans notre pôle de développement, sans amener de rigidité et sans altérer la fluidité existante. Je me suis rapidement tourné vers les méthodes agiles et plus particulièrement Scrum et XP. Scrum pour l'apparente simplicité à "contenir" un projet (je reviendrai plus tard cette "apparente simplicité") et XP pour les bonnes pratiques purement liées au développement informatique.
Sur ces deux sujets il est aisé de trouver de l'information théorique et gratuite sur le web. Pour XP on trouve aussi des tutoriels et autres exemples sur comment faire du TDD ou sur comment se passe en pratique le pair programming. Je remercie d'ailleurs toutes ces personnes qui se donnent la peine de partager des informations car elles me servent quotidiennement.
Mais sur Scrum on trouvais à l'époque plus difficilement des exemples d'implémentation, des retours d'expériences, des bases factuelles sur lesquelles démarrer une implémentation de scrum. Il en existe quelque uns et pas des moindres qui m'ont beaucoup inspirés :
- http://www.aubryconseil.com/
- http://www.fredericdoillon.com/
- http://brunosbille.com/ que j'ai découvert récemment.

Ici j'aimerai faire part de mon expérience en tant que scrum master et de celle de notre équipe de développement pour donner un éclairage supplémentaire à celles et ceux qui envisage de se lancer dans la mise en place de méthodes agiles.

Je prépare donc une série d'articles sur l'implémentation de Scrum dans notre DSI en ce sens.

En attendant je vous livre le contexte dans lequel nous évoluons:
Nous faisons partie d'une institution de l'état français implantée à l'étranger. Nos activités informatiques se concentrent sur la réalisations d'outils métiers (full web) qui gravitent autour d'un portail intranet style netvibes. Nous travaillons avec notre DSI et la MOA qui sont en France.
Nous sommes organisés en 2 équipes de projets Scrum, composées de 3 développeurs chacune et se partageant un testeur. Pour le moment il y a un scrum master et un product owner pour les deux équipes.

A bientôt pour la suite.

Review après deux ans de blog

Un petit bilan après 2 ans de vie pour ce blog...
Bon ok 8 articles en 2 ans ce n’est pas forcément la panacée et il est vrai qu'être assidu à l'écriture n'est pas forcément chose aisée. Le plus difficile est de ne pas écrire une information qui n'est pas déjà sur 10 autres blogs ou sites web. J'espère cependant avoir pu aider quelques personnes avec ces retours d'expériences.

Parlons un peu d'actualité à présent.
Pendant les deux dernières années mon activité à quelque peut évoluée ce qui m'a amené à m'intéresser à de nouveaux sujets :
- l'agilité : Scrum en tête car j'ai introduit l'utilisation de scrum dans mon entreprise depuis 9 mois. Convaincus des apports bénéfiques de l'agilité, nous généralisons depuis l'utilisation de scrum à tous nos projets.
- l'outillage et les méthodes qui sont nées dans les méthodes agiles : intégration continue, tests unitaires, tests automatisés...
- le facteur humain dans les projets : travail en équipe, développement personnel, efficacité individuelle au profit du groupe, organisation et relations entre testeurs, développeur, MOA, DSI...

Je publierais donc des articles sur ces sujets qui me passionnent en plus de parler de .net.

Bonne continuation à toutes et tous.

mercredi 6 mai 2009

Linq to Sql - SqlException : "The transaction operation cannot be performed because there are pending requests working on this transaction."

Bonjour à toutes et tous,

Je fais l'impasse sur le fait que je n'ai pas alimenté ce blog depuis un certain temps...

Concentrons nous sur le sujet de ce billet : une déconvenue (de plus) avec Linq To Sql.

Dans une de nos applications nous utilisons Linq To Sql pour notre couche Dal (Data Access Layer).
Le problème que j'ai rencontré dernièrement et que j'expose ici, est lié à l'utilisation de Linq to Sql en utilisant des transactions (IDbTransaction), avec une de nos procédures stockées qui fait un update de record en base après avoir fait un select de controle de cohérence.
Exemple :
create procedure UpdateCommande(@idCommande int, @idUtilisateur int, @nomCommande as varchar(20))
begin
-- Vérifit que l'utilisateur à le droit de modifier la commande
declare @isUserAuthorise int
select @isUserAuthorise = id from TablePermissions where idCommande = @idCommande and @idUtilisateur = utilisateur and action = 'Modification'

-- Fait l'update si possible
if @isUserAuthorise != null
begin
update commande set name = @nomCommande where idCommande = @idCommande
end
end


Après avoir écrit ma procédure stockée et l'avoir "drag and droppé" dans le designer Linq To Sql, j'utilise la méthode générée par le designer pour faire mon UpdateCommande() depuis ma couche métier, puis je commit la transaction. Bing ! Ici une exception est levée : "SqlException : "The transaction operation cannot be performed because there are pending requests working on this transaction.".
Ici je n'ai pas compris tout de suite ce qui était en déaut, je dirai même que ça m'a pris une demi journée pour retrouver l'origine du problème.

J'ai finalement pensé qu'une fois de plus le designer linq to Sql avait peut être trouver moyen de générer du code non adapté à ma procédure stockée. En effet le designer m'avait généré un type de retour sur la fonction d'appel à mon update en base. Du coup à chaque appel à ma fonction UpdateCommande(), linq to sql émet une requete du type ExecuteReader() au lieu de ExecuteScalar(). Et comme je ne consomme pas les données renvoyées par le ExecuteReader(), le reader reste ouvert !

Résolution du problème :
1- Modifier la procédure stockée en retirant le select qui induit en erreur le designer
2- Supprimer puis ajouter à nouveau la procédure stockée dans le .dbml avec le designer : constater qu'il n'ya pas de type de retour généré par le designer.
3- Restaurer le select dans la procédure stockée.

Conclusion :
Ce problème lié au designer n'est pas un cas isolé car il arrive fréquemment qu'une procédure stockée un peu complexe (création de table temporaire, if-else trop nombreux) qui renvoi des données, mette en défaut le designer, qui n'est alors pas capable de générer un type de retour à cette procédure stockée. Dans ce cas il faut faire comme vu précédemment, en remplaçant le code complexe par un code simple à partir duquel le designer sera capable d'interpréter les colonnes de retour et ensuite restaurer le code de la procédure stockée.

Encore une chose... J'ai entendu à plusieurs reprises ces temps-ci qu'il était préférable de passer à Linq to Entities et arrêter d'utiliser Linq To Sql car il sera rapidement obsolète chez Microsoft (plus de mise à jour du composant hors gros bugs bien sur)

Voilà j'espère que ça pourra vous aidez sur votre problème.

vendredi 24 octobre 2008

Failure adding assembly to the cache: Access denied.

Petite astuce du jour...

Ce matin j'ai eu besoin d'enregistrer ma Dll signée dansle GAC de notre serveur de build qui est sous Windows 2008.

Manipulation super simple en principe puisque qu'un simple drag and drop de la Dll dans le répertoire %WINDIR%\Assembly\ et hop ! Ou alors, on peut aussi utiliser (et c'est recommandé) l'utilitaire gacutil.

Mais avec Windows 2008 (il semble qu'on observe la même chose sous Vista) le drag and drop tout comme le gacutil vous renvoi un message d'erreur Failure adding assembly to the cache: Access denied. Très désagréable et surprenant au premier abord lorsqu'on a les droits d'administrateur.

L'astuce est donc de démarrer la ligne de commande MS-DOS en faisant "clique droit -> run as Administrator" pour utiliser gacutil. Et la c'est tout bon, la dll est enregistrée dans le GAC.

Je n'ai pas le temps aujourd'hui de fouiller plus que ça les principes qui régissent ce fonctionnement mais si quelqu'un a une explication ou un lien pour aider à la compréhension, n'hésitez pas à laisser un commentaire.

Edit le 24/10/2008 à 15:00 :
En posant la question à des collègues de l'exploitation j'ai eu une réponse. En fait c'est lié au "nouveau " fonctionnement de la sécurité dans Windows Vista et 2008. Tout utilisateur ayant les droits d'administration, peut accéder aux fonctionnalités des administrateurs mais doivent explicitement indiquer qu'ils souhaitent réaliser une action en tant qu'administrateur en utlilisant le menu "clique droit -> Run as Administrator".
C'est plus clair comme ça, non ?

vendredi 19 septembre 2008

Petite introduction sur DbPro de Visual Studio Team System

Me voici sur un nouveau sujet, assez palpitant puisqu'enfin les développeurs vont pouvoir gérer leurs scripts de bases de données en même temps et au même endroit (Visual Studio) que les sources de leur application. Ce sujet est donc DbPro disponible dans la version Team System de Visual Studio.

Voici, après quelques heures d'utilisation, ce que propose DbPro.
Grace à DbPro nous pouvons "aspirer" le modèle de notre base de données existante et Visual Studio nous créer un projet DbPro qui cohabite avec nos autres projets de la solution et qui contient les scripts de tous les objets de notre base de données (table, vues, user, procédures...). Assez génial ! Du coup tous les scripts de la base de données sont sauvegardés dans le serveur de code source de la même manière qu'un fichier CS ou VB. Fini l'écrasement accidentel et la perte définitive d'une procédure stockée qui à prit 5 jours de réalisation, tout est dans le serveur de code source !

DbPro va encore plus loin car il permet d'éditer tous les objets de la base de données dans Visual Studio (plus besoin de Sql Manager Studio, ou presque) et surtout, génère le script de déploiement vers la base de données cible. Ici Microsoft facilite un autre point crucial dans le cycle de développement qu'est le recensement des modifications apportées à une base de données durant une phase de développement.

Dans un contexte d'intégration continu on peut bien sur envisager le déploiement automatique des modifications de base de données à chaque check-in. Il suffit de modifier un peu la déclaration de son serveur de build Team System pour que ce dernier compile le projet Dbpro et déploie les modifications sur le serveur d'intégration ! C'est exactement ce que je mets en place actuellement. C'est plutôt simple à réaliser et les MSDN documentent assez bien le sujet.
Dans mon prochain article je vais ajouter quelques liens pour la mise en oeuvre de DbPro avec Team Build, plus quelques petit tips que j'aurais découvert.

Bien à vous.

lundi 4 août 2008

Déploiement de clé de registre avec valeur par défaut dans un MSI

Le template de projet Setup Project de Visual Studio, permet aisément de créer des clés de base de registre et c'est tant mieux. Par contre là où c'est moins bien, c'est que le designer ne permet pas de définir la valeur par défaut de la clé de registre.

Exemple :
Je veux créer une clé de registre avec comme valeur par défaut "toto va au marcher".
Si j'ajoute simplement une string value à ma clé et que je lui donne comme nom (Default), on pourrait croire que ça marchera mais en fait non. Le MSI va créer 2 clés de registre avec le nom (Default), une avec ma valeur "toto va au marcher" et une sans valeur.

Résolution :
Et la où c'est pas terrible c'est que le designer ne propose pas de solution évidente à part une manipulation sordide trouvé dans les MSDN : http://msdn.microsoft.com/fr-fr/library/xkfz6802(en-us).aspx. En voici un extrait au cas où Microsoft décide de fermer la page... par honte du contenu :
...
To specify a default value :
- Select a value name in the right-hand
pane of Registry Editor.
- Right-click the value name and then click Rename.
- On the Edit menu, click Delete.
- Press ENTER. The name is replaced
with '(Default)'.
...

Le plus moche c'est que cette manipulation n'a pas fonctionné pour moi...

La solution qui a marcher pour moi c'est de créer un fichier .reg à partir de l'éditeur de base de registre et de l'importer ensuite dans le designer de Visual Studio. (Clique droit sur Registry Target Machine -> Import)


Bonne programmation à tous.

mercredi 30 juillet 2008

Créer des tâches personnalisées pour un Team Build

But

Créer une tâche personnalisée qui sera exécutable par un serveur de build Team System.

Pré requis

Configuration de la machine de développement :
La création de build custom task se fait en VB ou en C# dans Visual Studio et se base sur l'API de Team System. Donc il faut un Visual Studio + l'installation du SDK Team System ou plus simple, Visual Studio Team System.

Configuration du serveur de build (Team Build) :
Pour que le serveur de build puisse compiler la documentation du code en se basant sur SandCastle, il faut bien sur installer SandCastle... Logique non ? Allez voir sur http://www.codeplex.com pour avoir la dernière version.
Ensuite il faut installer SandCastleBuilder sur le serveur de build (l'application qui permettra de compiler l'aide grâce à des projets de documentation), voir aussi sur http://www.codeplex.com pour le téléchargement.


Scénario 1 :
Le serveur de build exécute les tâches qui sont définies dans le fichier tfsbuild.proj. Le format de ce fichier de projet est écrit dans le standard MSBuild et propose différentes choses, dont notamment la possibilité d'exécuter une ligne de commande. On va donc pouvoir compiler la documentation de notre code avec SandCastleBuilder (voir pré requis dans le scénario 2) en l'appelant depuis le fichier de projet du team build.

Le code de l'exemple :

<target name="GenerateDocumentation">
<propertygroup>
<sandcastlebuidlerpath>C:\Program Files\EWSoftware\Sandcastle Help File Builder\SandcastleBuilderConsole.exe</sandcastlebuidlerpath>
<sandcastlebuilderprojectfile>..\Sources\DemoDocumentation\DemoDocumentation.shfb</sandcastlebuilderprojectfile>
<sandcastlebuilderarguments>-OutputPath="$(OutDir)\"</sandcastlebuilderarguments>
</propertygroup>
<exec command="">
</exec>

Scénario 2 :
On étudie ici l'ajout d'une tâche qui consiste à compiler la documentation du code avec SandCastleBuilder, après la compilation du code.
Le serveur de build va donc exécuter les tâches dans l'ordre suivant :

  1. prendre la dernière version des sources
  2. compiler la solution (sln)
  3. exécuter les tests unitaires existants
  4. compiler la documentation du code compilé en 1

Création de la custom task :
Une custom task est encapsulée dans une Dll .Net qui sera référencée dans le fichier de projet du Team Build (tfsbuild.proj). Pour rappel ce fichier de projet est un fichier type MSBuild, donc pour plus d'informations sur ce format rechercher MSBuild dans Google.

  1. Nous créons un projet de type ClassLibrary dans Visual Studio
  2. Nous lui ajoutons les références aux assemblies de Team System :
    • . Microsoft.Build.Framework
    • . Microsoft.TeamFoundation.Client
    • . Microsoft.TeamFoundation.Build.Common
  3. On supprime Class1.cs qui ne sert à rien...
  4. On ajoute notre nouvelle classe qui va nous permettre de compiler la documentation de code. Je vais l'appeler BuildHelp.
  5. Microsoft nous propose 2 manières d'implémenter une classe tâche de build. Soit hériter de la classe Microsoft.Build.Utilities.Task ou alors implémenter l'interface Microsoft.Build.Framework.ITask. Dans notre exemple nous prendrons la première solution, plus rapide à implémenter.
  6. La classe Task est une classe abstraite et définie la méthode Execute() comme abstraite, nous la surchargeons donc dans notre classe BuildHelp. C'est cette méthode qui sera invoquée par le serveur de build pour déclencher le travail de notre custom task.
  7. Le code de notre fonction Execute() est plutôt simple puisqu'il consiste à appeler le programme SandCastleBuilderConsole.exe en lui passant en paramètres, le projet SandCastleBuilder qui contient tous les paramètres de génération de documentation.

Voici du code simple (pour l'exemple) pour faire ceci :


public override bool Execute()
{
// Création du processInfo
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(@"SandcastleBuilderConsole.exe");
psi.Arguments = "monProjet.shfb";
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
System.Diagnostics.Process sandCastleBuilder = null;

// La fonction Log.LogCommandLine() est fournie par Team System et permet d'écrire dans le journal de build
Log.LogCommandLine(MessageImportance.Low, @"SandcastleBuilderConsole.exe" + " " + "monProjet.shfb");
sandCastleBuilder = System.Diagnostics.Process.Start(psi); // Démarre le programme de compilation de la documentation
sandCastleBuilder.WaitForExit(MAX_WAITING_TIME);

return true;
}

La valeur que retourne la fonction Execute() permet au serveur de build de connaitre le résultat de la tâche qu'il a démarré. True la tâche s'est déroulée avec succès, sinon false.

8- On compile la Dll.
9- Pour ajouter la custom task au serveur de build, on édite le fichier projet du serveur de build, le fameux fichier tfsbuild.proj. On lui ajoute notre tâche à la fin après la dernière balise <ItemGroup>:
<usingtask taskname="Reseaux.TeamSystem.Build.CustomTask.BuildHelp" assemblyfile="$(SolutionRoot)\\DemoDocumentation\\Reseaux.TeamSystem.Build.CustomTasks.dll">
<target name="GenerateDocumentation">
<buildhelp>
</buildhelp>
10- Pour pouvoir exécuter notre custom task, le serveur de build doit pourvoir la trouver, donc on peut la mettre dans le répertoire de la solution (il y a d'autres méthodes, voir dans Google et/ou les MSDN). On ajoute donc la Dll générée qui contient notre custom task, dans le contrôle de code source Team System, à coté du fichier sln que notre serveur de build compile.
11- On archive tout (le fichier projet du TeamBuild, la Dll de la customTask) et on démarre un nouveau build.

En principe dans le répertoire de sortie définit par le projet SandCastleBuilder, vous devriez y trouver l'aide compilée.
Si ce n'est pas le cas aller voir dans le fichier de log du serveur de build et rechercher l'appel à votre custom task pour voir si une erreur est remontée.

Ajouter l'output de SandCastleBuilder : Bon aller il y a de grandes chances pour que le shfb qui tourne en local se comporte autrement sur le serveur de build, donc ça serait cool d'avoir l'output de SansCastleBuilderConsole dans le fichier de log du serveur de build. Pour faire ça, on remplace le code de notre Custom Task pour obtenir ceci :

public override bool Execute()
{
bool result = false;
string applicationName = @"SandcastleBuilderConsole.exe";
string parameters = "monProjet.shfb";
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(applicationName);
psi.Arguments = parameters;
psi.RedirectStandardOutput = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
System.Diagnostics.Process sandCastleBuilder = null;

try
{
Log.LogCommandLine(MessageImportance.Low, applicationName + " " + parameters);
sandCastleBuilder = System.Diagnostics.Process.Start(psi);
}
catch (ObjectDisposedException e)
{
Log.LogErrorFromException(e, true);
}
catch (InvalidOperationException e)
{
Log.LogErrorFromException(e, true);
}
catch (ArgumentNullException e)
{
Log.LogErrorFromException(e, true);
}
catch (Win32Exception e)
{
Log.LogErrorFromException(e, true);
}
finally
{
if (sandCastleBuilder != null)
sandCastleBuilder.WaitForExit(MAX_WAITING_TIME);
}

try
{
string errorMessage = string.Empty;
string logMessage = string.Format("No output available for {0}", applicationName);
if (sandCastleBuilder.HasExited)
{
string applicationOutput = sandCastleBuilder.StandardOutput.ReadToEnd();
if (sandCastleBuilder.StandardOutput != null)
logMessage = string.Format("See {0} output bellow :\r\n{1}", applicationName, applicationOutput);

if (applicationOutput.IndexOf("Fatal error") != -1)
errorMessage = "See previous error in application output";
else
result = true;
}

Log.LogMessage(logMessage); // Affiche la sortie de l'outil
if (errorMessage.Length > 0)
Log.LogError(errorMessage, null);
}
catch (InvalidOperationException e)
{
Log.LogErrorFromException(e, true);
}
catch (Win32Exception e)
{
Log.LogErrorFromException(e, true);
}
catch (NotSupportedException e)
{
Log.LogErrorFromException(e, true);
}

return result;
}

Rendre les arguments de notre custom task paramétrables, dans le fichier projet Team Build :
Ce qui est pratique c'est qu'on peut facilement définir des paramètres à notre classe custom task. Ces paramètres sont automatiquement lus dans le fichier projet et envoyé à notre custom task par le serveur de build.

Il faut donc ajouter une propriété publique à notre classe BuildHelp. Cette propriété doit portée l'attribut [Required].
Par exemple on peut définir le nom et l'emplacement du fichier projet de documentation à compiler (.shfb)

[Required]
public string SandCastleBuilderProjectFile
{
get { return _sandCastleBuilderProjectFile; }
set { _sandCastleBuilderProjectFile = value; }
}

Et dans le fichier projet, on ajoute le paramètre :

<buildhelp sandcastlebuilderprojectfile=""..\Sources\DemoDocumentation\DemoDocumentation.shfb" ">
</buildhelp></target>/<usingtask></target>

Voilà pour l'essentiel.

Sur mes projets, à ce jour j'ai préféré n'utiliser que la configuraion du fichier TFSBuild.proj en faisant appel aux outils externes via la commande <exec.../> utilisable dans les fichiers MSBUILD. Ca me permet de faire ce dont j'ai besoin (compilation de la documentation de code, regroupement de Dll en une seule et packaging dans un MSI) sans avoir à maintenir de code supplémentaire qui serait induit par l'utilisation de custom task codée en C# ou VB.

J'espère que ça vous aidera à démarrer sur le sujet.

Bien sur, Google est très parlant sur le sujet.

Bon codage à toutes et tous...

jeudi 17 juillet 2008

TeamSystem : Comment supprimer définitivement un WorkItem

Aller sur le serveur TeamSystem et exécuter la commande qui suit :
tfpt destroywi /server:SERVERNAME /workitemid:IDWORKITEM

La commande tfpt.exe fait partie des PowerTools de Team System :
Télécharger les ici http://msdn2.microsoft.com/en-us/tfs2008/bb980963.aspx

Ajouter vos assemblies dans la boite de dialogue "Add References" de Visual Studio


Quoi de plus chouette lorsqu'on distribue sa/ses Dll, que de la voir apparaitre dans la fenêtre "Add References" de Visual Studio ?
Certainement plein de choses, mais ce petit tips fait bon effet et peut faciliter la vie des clients de votre Dll.

Il suffit d'ajouter une clé de registre ici HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\ avec comme valeur le chemin vers le répertoire contenant votre / vos Dll.

Exemple :
- je veux ajouter les Dll contenues dans le dossier C:\Program Files\Common Files\MonProduit, il faut ajouter la clé suivante dans la base de registre :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\MonProduit
@="C:\\Program Files\\Common Files\\MonProduit"

La modification sera prise en compte lors du démarrage d'une nouvelle instance de Visual Studio.

Voilà ! Et bon codage.

mercredi 23 avril 2008

Ouverture du blog

Update le 09/03/2010
Un petit bilan après 2 ans de vie pour ce blog... Bon ok 8 articles en 2 ans ce n'est pas forcément la panaccée et il est vrai qu'être assidu à l'écriture n'est pas forcément chose aisée. Le plus difficile est de ne pas écrire une information qui n'est pas déjà sur 10 autres blogs ou sites web. J'espère cependant avoir pu aider quelques personnes avec mes retours d'expériences.
Pendant les deux dernières années mon activité à quelque peut évoluée ce qui m'a amené à m'intéresser à de nouveaux sujets :
- l'agilité : Scrum en tête car j'ai introduit l'utilisation de scrum dans mon entreprise depuis 9 mois. Convaincus des apports bénéfiques de l'agilité, nous généralisons depuis l'utilisation de scrum à tout nos projets.
- l'outillage et les méthodes qui sont nées dans les méthodes agiles : intégration continue, tests unitaires, tests automatisés...
- le facteur humain dans les projets : travail en équipe, développement personnel, efficacité individuelle au profit du groupe, organisation et relations entre testeurs, développeur, MOA, DSI...
Je publierais donc des articles sur ces sujets qui me passionnent en plus de parler de .net.
Bonne continuation à toutes et tous.
___________________________________________________________________
Bonjour à toutes et à tous !

Voici quelques temps déjà que je réfléchi à faire un blog. En effet un blog c'est bien mais il s'agit d'y mettre un peu de contenu attrayant. Alors après avoir pensé à diverses sujets (toujours autour de l'informatique bien sûr) j'ai décidé de limiter le champ et de le consacrer au développement Miscrosoft .NET.
C'est un sujet déjà très vaste en soit et il y aura toujours pleins de choses intéressantes à en dire, sans compter que c'est un des sujets que je maîtrise le mieux. Quitte à partager de l'information autant qu'elle soit de bonne qualité et éclairé par un point de vue (certe subjectif) mais expérimenté.
J'en profite pour me présenter ce qui vous aidera à mieux me connaitre : je fais du développement depuis plus de 6 ans dont 4 en C\C++ et 3 en .Net.
Je compte publier :
- évidemment des articles sur .net
- sur les outils gravitant autour de .net
- mes productions personnelles
- un peu d'actualité autour de .net même si d'autres sites le font bien mieux que je ne le ferai.
Bonne visite !