Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Julien Adam

.NET 2.0 + Team System : développer vite, bien et avec méthode !

Exécuter une requête SQL sur une Connection existante en mode debug

Exécuter une requête SQL sur une Connection existante, en plein milieu d'un debug, voilà une possibilité intéressante. Particulièrement quand on travaille avec des transactions et qu'on ne peut donc pas facilement voir avec d'autres outils l'état de la base à l'intérieur de la transaction puisque celle-ci est isolée.

J'allais dégainer Visual Studio et créer un "Debugger Visualizer" pour que depuis le debugger, en allant inspecter un object de type Connection (SqlConnection, OracleConnection ou autres), on ait une fenêtre custom qui apparaisse dans laquelle on pourrait saisir une requête et voir le résultat dans une grille.

Mais ce n'est pas la peine, puisqu'une bonne âme s'est déja attelée à la tâche. Le résultat s'appelle DbVisualizer et est dispo sur CodePlex ici. Voilà le résultat :

Exemple de visualisation dans le debugger de Visual Studio

PS: aucun rapport avec DbVisualizer, l'outil de gestion / développement de base de données bien connu.

Créer des tests web compatibles AJAX avec Team System et Fiddler

Si vous avez déja essayé de créer des scénarios de test web avec Visual Studio 2005 Team Edition for Testers vous avez peut-être remarqué que le plugin d'enregistrement de session fourni en standard n'est pas capable d'enregistrer les appels AJAX effectués par le browser.

En donnant une formation sur Team System il y a quelques temps, j'ai remarqué une nouvelle fonctionnalité de Fiddler (un analyseur de requètes HTTP gratuit et totalement indispensable). Il est capable d'enregistrer une session et la sauvegarder sous forme de test web Team System ! Et bien entendu, Fiddler travaillant à un niveau plus bas que le plugin d'enregistrement standard, il est capable de capturer tous les appels HTTP qu'ils soient standards ou AJAX.

Pour créer facilement un test web, lancez Fiddler puis naviguez avec votre browser sur votre application. (par défaut IE est configuré pour utiliser Fiddler, pour mozilla il faudra aller changer les paramètres de proxy, je vous laisse regarder la doc de Fiddler à ce sujet). Une fois le scénario joué, sélectionnez les requêtes intéressantes dans Fiddler et faites "Save / Sessions / As Visual Studio Web Test".


Ouvrez ensuite le fichier .webtest créé avec Visual Studio 2005 Team Edition for Testers (ou Team Suite) et vous aurez un test complet avec tous les appels AJAX, prêt à être rejoué.

Attention à un petit détail qui peut être un peu gênant, lorsque Fiddler tourne, les paramètres de proxy d'Internet Explorer sont modifiés et peuvent causer des problèmes de connexion, notamment avec le serveur Team Foundation. Pensez donc à bien le désactiver à la fin d'un enregistrement de session.

Un peu de pub...

... gratuite pour mon site de résolution de sudoku : http://www.solution-sudoku.com. J'ai mis en ligne la nouvelle version la semaine dernière, et cette fois le site est multilingue, français/anglais. J'en profite au passage pour dire que la gestion de l'internationalisation dans ASP.NET 2.0 c'est vraiment très très simple :)

70-553, ça c'est fait.

J'ai passé la certif 70-553 en version beta il y a fort longtemps, fin février si mes souvenirs sont exacts. Les résultats sont tombés il y a 2 semaines. C'est passé ;)

J'ai donc deux nouveaux titres :

Microsoft Certified Technology Specialist .Net Framework 2.0: Web Applications
Microsoft Certified Technology Specialist .Net Framework 2.0: Windows Applications

Et je suis à moitié MCPD, Microsoft Certified Professional Developper (merci à microsoft pour le nom, c'est la classe ... vraiment :)

En route pour la 70-554 !

Se faciliter le débogage avec la classe Debugger

Située dans l'espace de noms System.Diagnostics, cette classe va vous faciliter la vie dans quelques situations de débogage.

Pour commencer, on trouve la méthode Launch qui va attacher un débogueur au processus si il n'y en avait pas déja un. A quoi celà peut-il bien servir, il suffit de lancer le code à déboguer directement avec Visual Studio me direz vous ? Ce n'est pas toujours aussi simple, notamment lorsqu'il s'agit de déboguer un serveur COM+ ou plus généralement du code qui tourne dans un processus différent de celui que l'on débogue dans Visual Studio.

Bien entendu, on peut toujours lancer le premier processus normalement avec VS.NET, puis attendre que le deuxième soit chargé et passer par la commande "Tools/Attach to process..." pour attacher le débugger manuellement au deuxième processus. Mais au bout de 15 sessions de débogage, ça devient un peu répétitif... En ajoutant quelquechose comme :

#if DEBUG
if(!Debugger.IsAttached)
{
  Debugger.Launch();
}
#endif

Bien placé, ce code va automatiquement attacher le debugger au processus, sans opération manuelle ! (autre qu'éventuellement choisir le déboggeur à utiliser)

Ensuite, on a la méthode Break(). Celle-ci va également attacher un debugger au processus courant si il n'y en a pas déja un mais en plus, elle va produire un effet équivalent à celui d'un point d'arrêt. L'exécution va s'arréter et on aura accès aux fonctionnalités habituelles du débogueur pour inspecter l'état de l'application. Bien pratique pour mettre des "points d'arrêts" dans des processus que l'on a pas forcément envie de déboguer tout le temps mais dans lesquels on voudrait quand même s'arrêter dans certains cas.

Et pour terminer, la méthode Log envoie un message au debogueur qui le présentera au développeur. Dans le cas de Visual Studio.NET par exemple, le message sera affiché dans la fenètre "Sortie". Pratique quand Debug/Trace ne sont pas accessibles.

Bug sur le CommandField et le ButtonField ASP.NET 2.0

Je viens de passer un bon moment à traquer un bug vraiment vilain dans la GridView ASP.NET 2.0.

Si vous mettez un CommandField ou un TemplateField de type Image dans une GridView, le postback sera fait 2 fois au lieu d'une normalement mais seulement si le navigateur est IE. Apparemment il s'agit d'un bug connu, en tous cas j'ai trouvé plusieurs fils sur des forums qui en parlent dont celui-ci (en anglais).

Comme je suis curieux j'ai regardé avec Fiddler ce qui se passe. IE fait 2 requètes identiques sauf qu'a la fin de la deuxième il a ajouté les coordonnées du click de la souris sur l'image (ex. x=3&y=5). Je soupçonne un bug dans les librairies javascript ASP.NET 2.0 qui gèrent le postback mais je laisse ça aux gens qui lisent couramment le javascript :)

La solution de contournement est d'utiliser un TemplateField avec un ImageButton dont l'attribut CommandName aura la valeur appropriée ("Select" pour un bouton select, etc).

Resharper 2.0 en version finale

JetBrains vient de sortir la version finale de ReSharper 2.0. Pour ceux qui découvriraient ce produit, c'est un addin (payant, 200$ la license) de refactoring pour VS.NET 2003 et 2005. Rien à voir avec les fonctionnalités de refactoring de VS.NET 2005 qui sont inutilisables. Avec ReSharper on peut réellement faire du refactoring et profiter d'un tas d'autres améliorations de l'IDE. Je vous laisse découvrir tout ça avec la démo 30 jours. Si c'est aussi bien que la v1.0 j'achète !

Edit: après quelques jours d'utilisation je l'ai désinstallé. Les fonctionnalités sont excellentes mais les performances sont très décevantes. Sur un projet un peu conséquent on sent vraiment une grosse différence avec et sans ReSharper. Si bien que le temps gagné en écriture de code est perdu dans des temps de latence dus aux lenteurs plugin. Dommage.

Tester une couche d'accès aux données : une approche

Le problème

Appliquer des tests unitaires à une couche d'accès aux données peut se révéler être une tâche plus ardue qu'il n'y parait au premier abord. Dans la plupart des cas, il va s'agir d'amener la base de données dans un état présentant l'ensemble des conditions de départ du test, puis de lancer le code à tester et enfin de vérifier les conditions finales.

Pour que ces tests soient répétables, il faut évidemment que les conditions soient similaires à chaque lancement du test. On peut imaginer plusieurs solutions pour répondre à ce besoin (liste non exhaustive):

  • Réinitialiser la base de données avant chaque test, en la remplissant avec un jeu de données aussi exhaustif que possible. On s'arrange dans ce cas pour que les conditions de départ des tests soient remplies directement par ce jeu de données et on maintient le jeu de données en même temps que le code et les tests.
  • Créer un nouveau jeu de données (de nouvelles lignes avec de nouveaux identifiants) avant chaque test à l'aide d'un script SQL. Nettoyer la base après les tests en priant pour que le code de cleanup ne soit pas buggé (ou créer des tests unitaires pour tester le code de cleanup des tests unitaires :)
  • Combiner les deux approches

Dans tous les cas, on se trouve dans une situation assez difficile à maintenir. Soit on maintient une base avec un jeu de test exhaustif, soit on maintient des scripts et du code de cleanup. Or, c'est un fait, le développeur n'aime pas maintenir. C'est long, fastidieux et franchement pas très intéressant. La question est donc de savoir si on ne pourrait pas faire sans, tout en conservant les qualités intrinsèques d'un bon test unitaire.

Pour résumer, on voudrait pouvoir se mettre dans des conditions de test et garder l'environnement propre avec le minimum d'effort.

Une solution

En attendant de trouver mieux, l'approche que j'ai retenue pour mes tests avec le framework de tests unitaires de Visual Studio 2005 , c'est ça :

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.EnterpriseServices;
namespace MesTests
{
  [TestClass]
  [Transaction(TransactionOption.Required, Timeout = 300)]
  public class TestMaClasse : ServicedComponent
  {
    public TestMaClasse()
    {
    }

    [TestInitialize()]
    public void Initialize()
    {
    }

    [TestCleanup()]
    public void Cleanup()
    {
      ContextUtil.SetAbort();
    }

    [TestMethod]
    public void MethodeDeTest()
    {
      DAL.EcritDesDonnees();
      DAL.LitDesDonnees();
      Assert.IsTrue(...);
      // Autres vérifications...
    }
   
    ...
  }
}

Ma classe de test dérive de ServicedComponent, c'est donc un composant COM+. Avec l'attribut TransactionAttribute, j'indique que je travaille en mode transactionnel. Dans le TestCleanup, j'annule la transaction. En pratique donc mes tests travaillent sur la base de données autant qu'ils le souhaitent. A la fin tout est annulé "magiquement" par le rollback de la transaction COM+ et on revient à l'état initial avant les tests. Pour éviter d'utiliser des scripts SQL, j'utilise ma couche d'accès aux données pour écrire les données requises pour le test. Si vraiment ce n'est pas possible, je passe par un script SQL mais dans la majorité des cas, ce n'est pas nécessaire.

Notez aussi le "Timeout=300" qui laisse le temps de debugger tranquillement avant la fin automatique de la transaction. Le délai par défaut est un peu court et la transaction est souvent annulée alors qu'on est en plein debug, c'est assez pénible.

Ca pourrait peut-être marcher avec NUnit, mbUnit,

Nouveaux problèmes

La solution n'est pas parfaite pour plusieurs raisons :

D'abord parce que l'environnement de l'application n'est pas le même pendant les tests et au runtime, puisque dans un cas on est dans COM+, dans une transaction et dans l'autre pas forcément, et même si c'est le cas, il peut y avoir des effets de bord, soyez vigilants.

Ensuite, on a couplé dans un seul test plusieurs appels de méthodes. En théorie c'est mal, car les tests ne sont plus vraiment unitaires. J'ai tendance à négliger ce problème puisque au final les données seront de toutes manières écrites et lues par ma couche d'accès aux données. Tester les 2 en même temps ne me parait pas si hérétique que ça.

Et bien entendu, si la solution de stockage des données ne supporte pas les transactions COM+ ça ne fonctionnera pas.

Et vous quelle solution utilisez-vous pour tester vos couches d'accès aux données ? Bien évidemment si vous ne faites pas de tests unitaires la question ne se pose pas...


    ...mais c'est très mal !

Chemins relatifs dans les chaînes de connexion ADO.NET 2.0
Pour créer un test unitaire lié à une source de données avec Visual Studio Team System, il est préférable de se baser sur une source de données indépendante, utilisée uniquement pour les tests. On aimerait bien dans ce cas pouvoir se connecter à un fichier .mdf local par exemple. Et tant qu'à faire, on aimerait bien aussi pouvoir spécifier un chemin relatif dans notre chaîne de connexion.

Or, avant ADO.NET 2.0, il n'était pas possible de spécifier un chemin relatif dans une chaîne de connexion pour pointer vers ce fichier .mdf. Il fallait donc utiliser des chemins absolus... Microsoft a remédié à ce problème dans la version 2.0. On a maintenant à notre disposition des chaînes de substitution comme ceci par exemple :
"Data Source=.\SQLEXPRESS; Integrated Security=True;AttachDbFilename=|DataDirectory|\Company.mdf;Initial Catalog=Company"

Notez le "|DataDirectory|" qui viendra automatiquement être remplacé par le répertoire dans lequel l'assembly appellante s'exécute. Et le tour est joué.

Et comme une bonne nouvelle ne vient jamais seule, vous pouvez modifier la valeur qui sera substituée au runtime par ce type de code :
AppDomain.CurrentDomain.setData("DataDirectory", "C:\MesTests\");

(Merci à Sushil Chordia pour l'info qui était bien cachée dans MSDN.)

 
Consolas disponible en téléchargement
Consolas, la police de caractères de taille fixe qui sera livrée avec Vista, est disponible en download pour tous. Si comme moi vous trouvez Courier New vraiment pas terrible et Lucida Console moyenne, essayez cette police, elle est nickel pour développer : les zéros sont barrés pour les différencier des 'o' majuscules, les parenthèses, accollades et autres crochets sont bien hauts pour ressortir un peu plus, idem pour la virgule, bien différentiable du point etc. Bref, pas mal de petites améliorations bien confortables.

3 remarques tout de même :
  • Cette police est faite pour ClearType. Il faudra donc l'activer pour en profiter pleinement.
  • Le programme d'install définit Consolas comme police par défaut dans Visual Studio 2005. A priori on l'installe pour ça mais bon, vous serez prévenus !
  • La page de download indique qu'il faut une license de Visual Studio 2006 (vous avez bien lu) ... :)
Si ça vous dérange, il reste toujours d'autres polices tout à fait appropriées au développement (Proggy par exemple qui était jusqu'à voici 5 minutes ma police de référence).
Nouveau blog, en français dans le texte !
Hello tous,

Ca faisait un moment que je voulais transférer mon blog anglais en français. Merci donc à Nix et Florent pour cet espace dans la communauté que je vais essayer de tenir plus à jour que l'ancien... Ca sera pas difficile.

Bon c'est l'heure des présentations : moi c'est Julien Adam, aka Nidhogg (des fois). Je suis consultant et formateur chez Winwise (salut les collègues !) sur pas mal de sujets tournant autour de .NET, le plus récent en date étant Visual Studio Team System. Je travaille sur .NET depuis 2001, l'époque glorieuse de la beta1 et de la doc MSDN façon gruyère.

Ici, je devrais normalement parler de .NET, de méthodo et de développement en général. En pratique, on va essayer de ne pas trop déborder le sujet mais c'est pas facile. Surtout quand ces satanés développeurs de jeux vidéo sortent des trucs comme Oblivion. C'est pas fair play j'arrive pas à ne pas en parler :)

  Julien



Les 10 derniers blogs postés

- Les pièges de l’installation de Visual Studio 2017 par Blog de Jérémy Jeanson le 03-24-2017, 13:05

- UWP or not UWP sur Visual Studio 2015 ? par Blog de Jérémy Jeanson le 03-08-2017, 19:12

- Désinstallation de .net Core RC1 Update 1 ou SDK de Core 1 Preview 2 par Blog de Jérémy Jeanson le 03-07-2017, 19:29

- Office 365: Ajouter un utilisateur ou groupe dans la liste des Site collection Administrator d’un site SharePoint Online via PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-24-2017, 18:52

- Office 365: Comment créer une document library qui utilise les ContentTypeHub avec PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-22-2017, 17:06

- [TFS] Supprimer en masse les dépendances à SQL Enterprise ou Developer avant de procéder à une migration par Blog de Jérémy Jeanson le 02-20-2017, 20:30

- Office 365: Attention au volume utilisé par les fichiers de Thèmes de SharePoint Online par Blog Technique de Romelard Fabrice le 02-07-2017, 18:19

- [SCVMM] Supprimer une machine bloquée par Blog de Jérémy Jeanson le 01-31-2017, 21:22

- Microsoft .Net Challenge 2017 par Le Blog (Vert) d'Arnaud JUND le 01-30-2017, 15:25

- Office 365: Utiliser le bouton Export to Excel depuis un teamsite SharePoint Online et avec le client Office 2007 par Blog Technique de Romelard Fabrice le 01-27-2017, 18:58