Blog Home  Home Feed your aggregator (RSS 2.0)  
artiso Blog
Neues rund um's Thema .Net
 
 Friday, July 03, 2009

Wie in diesem Blog bereits an anderen Stellen erläutert, eignet sich das UIA (UI Automation Framework) sehr gut, um UI-Tests aufzubauen. Wer sich mit dieser Möglichkeit beschäftigt wird aber früher oder später auf das Problem stoßen, dass UIA Support bei WinForms Controls nicht flächendeckend gegeben ist, vor allem bei 3rd Party Controls sieht es da oft eher mau aus.

Ich habe hier beschrieben, wie man mit einem ServerSide Provider diese Lücken selbst schließen kann. Das Standardvorgehen sieht dabei vor, dass man ein eigenes Control erstellt, das man dann von dem Ausgangscontrol ableitet. Diese Vorgehen ist in der Praxis allerdings nicht unproblematisch. Zum einen muss man die abgeleiteten Controls für jedes neue Release der Ausgangscontrols aktualisieren und zum zweiten ist es nicht gerade schön in einer bestehenden Anwendung alle Controls gegen die abgeleitete Variante austauschen zu müssen.

Deshalb möchte ich hier einen alternativen Weg vorstellen. Die Idee beruht darauf, dass die Controls, denen es an Accesibility fehlt jeweils in ein Panel platziert werden und auf diesem Panel dann die entsprechenden Patterns implementiert werden. Das Panel kann die Operationen dann an das Control in seinem Bauch weiterleiten.

image

Ich habe mal ein Beispiel für Janus Calendar Controls gebaut. Zunächst habe ich mir ein UIA-Panel erstellt, von dem ich dann die weiteren Panels für die spezifischen Controls ableiten kann.

   1: using System;
   2: using System.Drawing;
   3: using System.Security.Permissions;
   4: using System.Windows.Automation;
   5: using System.Windows.Automation.Provider;
   6: using System.Windows.Forms;
   7:  
   8: namespace WindowsFormsApplication1
   9: {
  10:     public partial class UIAPanel : Panel, IRawElementProviderSimple
  11:     {
  12:         public UIAPanel()
  13:         {
  14:             this.BackColor = Color.Yellow;
  15:             this.Height = 0;
  16:             this.Width = 0;
  17:             this.AutoSize = true;
  18:         }
  19:  
  20:         [PermissionSetAttribute(SecurityAction.Demand, Unrestricted = true)]
  21:         protected override void WndProc(ref Message m)
  22:         {
  23:             // 0x3D == WM_GETOBJECT
  24:             Int32 param = 0;
  25:             if (Int32.TryParse(m.LParam.ToString(), out param))
  26:             {
  27:                 if ((m.Msg == 0x3D) && (param == AutomationInteropProvider.RootObjectId))
  28:                 {
  29:                     m.Result = AutomationInteropProvider.ReturnRawElementProvider(
  30:                         Handle, m.WParam, m.LParam, (IRawElementProviderSimple)this);
  31:                     return;
  32:                 }
  33:             }
  34:             base.WndProc(ref m);
  35:         }
  36:  
  37:         #region IRawElementProviderSimple Members
  38:  
  39:         public object GetPatternProvider(int patternId)
  40:         {
  41:             if (patternId == ValuePatternIdentifiers.Pattern.Id)
  42:             {
  43:                 return this;
  44:             }
  45:             else
  46:             {
  47:                 return null;
  48:             }
  49:         }
  50:  
  51:         public object GetPropertyValue(int propertyId)
  52:         {
  53:             if (propertyId == AutomationElementIdentifiers.ClassNameProperty.Id)
  54:             {
  55:                 return "CalendarPanel";
  56:             }
  57:             else if (propertyId == AutomationElementIdentifiers.ControlTypeProperty.Id)
  58:             {
  59:                 return ControlType.MenuBar.Id;
  60:             }
  61:  
  62:             if (propertyId == AutomationElementIdentifiers.HelpTextProperty.Id)
  63:             {
  64:                 return "Help for CalendarPanel";
  65:             }
  66:  
  67:             if (propertyId == AutomationElementIdentifiers.AutomationIdProperty.Id)
  68:             {
  69:                 return this.Name; 
  70:             }
  71:  
  72:             if (propertyId == AutomationElementIdentifiers.IsEnabledProperty.Id)
  73:             {
  74:                 return true;
  75:             }
  76:  
  77:             else
  78:             {
  79:                 return null;
  80:             }
  81:         }
  82:  
  83:         public IRawElementProviderSimple HostRawElementProvider
  84:         {
  85:             get
  86:             {
  87:                 return AutomationInteropProvider.HostProviderFromHandle(Handle);
  88:             }
  89:         }
  90:  
  91:         public ProviderOptions ProviderOptions
  92:         {
  93:             get
  94:             {
  95:                 return ProviderOptions.ServerSideProvider;
  96:             }
  97:         }
  98:  
  99:         #endregion
 100:  
 101:     }
 102: }

 

Dieses Panel stellt einen ServerSide Provider zur Verfügung. Wir können nun von diesem Control ableiten und ein entsprechendes Pattern, z.B. das SetValue Pattern implementieren:

   1: using System;
   2: using System.Windows.Automation.Provider;
   3: using System.Windows.Forms;
   4:  
   5: namespace WindowsFormsApplication1
   6: {
   7:     public partial class CalendarPanel : UIAPanel, IValueProvider
   8:     {
   9:         private Janus.Windows.Schedule.Calendar control;
  10:         public Janus.Windows.Schedule.Calendar Control
  11:         {
  12:             get
  13:             {
  14:                 if (control == null)
  15:                 {
  16:                     if (this.Controls.Count > 0 && this.Controls[0].GetType() == typeof(Janus.Windows.Schedule.Calendar))
  17:                         control = (Janus.Windows.Schedule.Calendar)this.Controls[0];
  18:                 }
  19:                 return control;
  20:             }
  21:         }
  22:  
  23:         #region IValueProvider Members
  24:  
  25:         public bool IsReadOnly
  26:         {
  27:             get 
  28:             {
  29:                 return false;
  30:             }
  31:         }
  32:  
  33:         public void SetValue(string value)
  34:         {
  35:             this.BeginInvoke((MethodInvoker)delegate()
  36:             {
  37:                 DateTime date = DateTime.Parse(value);
  38:                 Control.SelectionRange = new Janus.Windows.Schedule.DateRange(date, date);
  39:             });
  40:         }
  41:  
  42:         public string Value
  43:         {
  44:             get 
  45:             {
  46:                 return Control.SelectionRange.End.ToShortDateString(); 
  47:             }
  48:         }
  49:  
  50:         #endregion
  51:     }
  52: }

 

Wenn wir nun das Calendar_Control nicht direkt auf unserer Form platzieren, sondern in einem solchen CalendarPanel ablegen, können wir eine Automatisierung über die UIA gegen dieses Panel implementieren. Was nun noch optimiert werden soll, ist dass die ganzen Controls nicht händisch in die jeweiligen Panels platziert werden sollen, sondern dies soll nach Möglichkeit automatisiert werden. der Ansatz hierbei ist, dass alle Controls auf der Form beim Laden untersucht werden und für die gewünschten Controls dynamisch entsprechende Panels erzeugt werden sollen, in die dann die Controls platziert werden. Dieser Ansatz bietet zudem den Vorteil, dass man die UIA-Panels nur dann nutz, wenn man UI-Test ausführen möchte. Bei der Release-Version sind diese dann nicht enthalten. Zwar unterscheidet sich dadurch Release und Test-Version geringfügig, jedoch sollten diese Implikationen vernachlässigbar sein, vor allem dann, wenn beim Entwickeln komplett auf die Panels verzichtet wird und diese wirklich nur für die UI-Tests genutzt werden.

Der Code dazu sieht dann so aus:

   1: private void PlaceControlsIntoPanel(Control.ControlCollection controls)
   2: {
   3:     Panel uiaPanel;
   4:  
   5:     foreach (Control automationControl in controls.OfType<Control>().ToList())
   6:     {
   7:         switch (automationControl.GetType().ToString())
   8:         {
   9:             case "Janus.Windows.CalendarCombo.CalendarCombo":
  10:                 {
  11:                     uiaPanel = new CalendarComboPanel();
  12:                     break;
  13:                 }
  14:             case "Janus.Windows.Schedule.Calendar":
  15:                 {
  16:                     uiaPanel = new CalendarPanel();
  17:                     break;
  18:                 }
  19:             default:
  20:                 {
  21:                     if (automationControl.HasChildren)
  22:                     {
  23:                         PlaceControlsIntoPanel(automationControl.Controls);
  24:                     }
  25:                     continue;
  26:                 }
  27:         }
  28:         uiaPanel.Name = "p_" + automationControl.Name;
  29:         uiaPanel.Top = automationControl.Top;
  30:         uiaPanel.Left = automationControl.Left;
  31:         uiaPanel.Controls.Add(automationControl);
  32:         automationControl.Top = 0;
  33:         automationControl.Left = 0;
  34:         controls.Add(uiaPanel);
  35:     }
  36: }

 

Wird die Anwendung dann inkl. Test-Client ausgeführt, sieht das so aus:

image

Friday, July 03, 2009 1:10:58 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Wednesday, June 03, 2009

Team System User Group - Virtual Edition

Im Juni werden wir beim EMEA-Meeting der Team System User Group Virtual Edition Ed Blankenship als Sprecher haben. Ed ist MVP für Team System und Release Manager bei Infragistics, dem führenden Hersteller von UI-Komponenten. Er wird in seinem Vortrag über die Erfahrungen bei der Einführung von VSTS bei Infragistics berichten. Dabei werden die verschiedenen Bereiche wie Versionsverwaltung, Build Management, Work Item tracking, das Management globaler Teams, automatisiertes Testen und vieles mehr aus einer Anwendersicht beleuchtet. Ein wirklich sehenswerter Erfahrungsbericht aus der Praxis.

Weitere Informationen unter www.tsug-ve.com.

Wednesday, June 03, 2009 11:02:14 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

Im Team Foundation Server werden Änderungen an den Inhalten der Workitems in einer Historie festgehalten. Diese Historie kann man auf jedem einzelnen Workitem einsehen.

image

Mit einem kostenlosen Excel-Addin können diese Auswertungen auch massenhaft durchgeführt und so über ganze Projekte Auswertungen über die Historie erstellt werden. Dazu wird zunächst ein Zeitraum und ein Intervall ausgewählt (alternativ kann man auch einen bestimmten Zeitpunkt wählen):

Nun werden für jeden gewählten Zeitpunkt die Work Items in dem jeweiligen Zustand in eine Excel-Tabelle eingetragen. Diese kann nun sehr schön über eine Pivot-Tabelle oder ein Pivot-Chart ausgewertet werden um so den zeitlichen Verlauf bestimmter Kennwerte abzubilden.

Natürlich lassen sich solche Ergebnisse auch über das DataWarehouse im TFS ermitteln, jedoch besitzt dieses Tool zwei Vorteile:

  1. Es ist wesentlich einfacher zu bedienen und übersichtlicher, so dass damit auch Ad-Hoc Reporting für Anwender möglich wird.
  2. Es grift auf alle Workitem-Daten zurück, nicht nur auf die, die im DataWareHouse konfigurierten. Einzige Ausnahme sind Links und Attachments, die in beiden Varianten nicht Teil der Historie sind.

Weitere Informationen und den kostenlosen Download gibtes unter http://www.alm-tools.de/?Product=5

Ein Video das die Fuinktionsweise des Tools demonstriert kann hier agezeigt werden.

Wednesday, June 03, 2009 3:06:35 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, June 02, 2009

image

Eigentlich versuche ich meinen Blog weitgehend werbefrei zu halten. Diesesmal möchte ich aber doch kurz auf die Seite www.alm-tools.de hinweisen, die mein Arbeitgeber artiso betreibt. Hier haben wir vor Kurzem eine Reihe neuer Tools rund um das Thema TFS und ALM (Application Lifecycle Management) veröffentlich, zum Teil kostenlos. Zudem gibt es hier inzwischen auch ein kleines Archiv mit Videos rund um das Thema das wir kontinuierlich ausbauen.

Tuesday, June 02, 2009 2:45:30 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

image

Mein Kollege Mark Bulmahn hat in einem Screencast ein Problem näher untersucht, das beim Merge in der TFS Source Countrol auftreten kann. Dabei geht es vor allem darum, dass Verschiebe-Operationen im Visual Studio Solution Explorer in der Source Control nicht als Verschiebe-Operation sondern als Delete und Add ausgeführt wird. Das führt dann zu Problemen bei einem späteren Merge.In dem Screencast sieht man, wie dieses Problem vermieden und auch wieder repariert werden kann.

Tuesday, June 02, 2009 7:39:21 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Saturday, May 23, 2009

Wenn schon mit Pre-Releases arbeiten, dann richtig habe ich mir gedacht und versucht den Team Foundation Server 2010 Beta 1 auf dem Windows 2008 Server R2 RC zu installieren. Nach einer kurzen Recherche im Internet bin ich auf diesen Blog-Post gestoßen. Mit den Informationen dort ist es mir tatsächlich gelungen, den TFS 2010 Beta1 und VSTS 2010 Beta1 auf dem Win2008R2 RC zu installieren. Damit komme ich nun auch auf meiner Demo-Maschine in den Genuss der Desctop-Experience von Win2008R2 :-)

image

Saturday, May 23, 2009 1:27:30 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Wednesday, May 20, 2009

Team System User Group - Virtual Edition

Im Mai haben wir bei der TSUG-VE Ian Ceicis als Sprecher zum Thema Projekt Management mit TFS 2010. Er wird in seinem Vortrag die Neuerungen rund um das Workitem-Tracking in TFS 2010 vorstellen.

Want to get the skinny on the latest enhancements coming in TFS 2010, come see demos of the updated MSF Agile template, the new Agile workbooks, the new Excel reports, and the Microsoft Project client improvements such as Hierarchical work items, rollups, and project summary tasks. This session will be packed with demos from  Beta 1 and will be a great way to start getting familiar with the new tools coming in 2010. Bring your hardest questions, join the conversation, and walk away with the ability to see how your next project will run smoothly if you start using TFS 2010.

This month's meeting is being presented by Ian Ceicys.  Ian is a member of Microsoft's Global ALM Practice and an active member of the VSTS Rangers.

 

Das Treffen findet am Donnerstag, 21.05.2009 um 19:00 statt.

Weitere Infos unter http://www.tsug-ve.com

Wednesday, May 20, 2009 1:42:09 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Tuesday, May 19, 2009

image

Unter http://msdn.microsoft.com/en-us/library/dd831853(VS.100).aspx steht inzwischen auch die Dokumentation für das .Net Framework 4 Beta 1 und Visual Studio 2010 Beta 1 zur Verfügung. Für die Beta 1 wird es nur eine Online-Version der Dokumentation geben, eine lokale Installation wird erst mit einer späteren Version verfügbar sein, was sicher bei einer Beta-Dokumentation auch Sinn macht.

Tuesday, May 19, 2009 7:15:59 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, May 18, 2009

Nachdem es bisher nur Gerüchte gab, nun ist es offiziell. Visual Studio 2010 Beta 1 wird noch heute für MSDN-User verfügbar sein. Für die Öffentlichkeit gibt es den Download dann ab Mittwoch.

Diesmal aus einer verlässlichen Quelle (Soma Somasegar, Corporate Vice President Microsofts)

Visual Studio 2010 and .NET FX 4 Beta 1 ships!

Update: Ich habe die Bits inzwischen runtergeladen. Da haben die Jungs wirklich noch einiges reingepackt gegenüber den früheren CTPs.

Monday, May 18, 2009 3:50:56 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [2]    | 
 Thursday, May 14, 2009

image    &  Untitled

Mit der Version 3 des Design-Tools für WPF und SilverLight, Expression Blend bekommt nun endlich die Unterstützung für den Team Foundation Server um die Source-Dateien in der Versionsverwaltung abzulegen. Hierzu muss ein entsprechendes Hotfix installiert werden. Dann hat man im Project-View zusätzliche Icons die den Auscheck-Status der Dateien anzeigt und im Kontext-Menü befinden sich entsprechende Kommandos für die Versionsverwaltung.

Hinweis: Damit das beim ersten Start auch wirklich funktioniert, muss man im Visual Studio den Team Explorer wenigstens einmal gestartet haben und dort den Server registrieren. Sonst bekommt man die Meldung "Unable to determine workspace" im Expression Blend.

image

Beim Checkin ist auch die sehr nützliche Funktion zur Verknüpfung von Workitems beim Checkin verfügbar.

image

Damit kann Expression Blend nun endlich in den Entwicklungs-Prozess von Software-Anwendungen integriert werden und steht nicht nur als separates Design-Tool bereit.

Thursday, May 14, 2009 11:49:23 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Wednesday, May 13, 2009

.NET Open Space vom 11.07. bis 12.07.2009 in Ulm

Nach rund einer Woche ist bereits die Hälfte der Plätze beim .Net Open Space Süd 2009 vergeben. Stand heute haben wir 33 Anmeldungen und es sind ein paar hochkarätige .Net Experten darunter. Wer also noch dabei sein will, sollte nicht zögern, sondern sich gleich auf die Teilnehmerliste eintragen.

Wir sehen uns am 11/12. Juli in Ulm!

Wednesday, May 13, 2009 3:19:20 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

Auf einer neuen TFS-Instanz hatte ich eben ein seltsames Phänomen. Ich konnte das erste Team-Projekt problemlos anlegen. Dazu verwendete ich einen Team_Explorer mit einer Visual Studio Shell Installation auf dem Server. Als ich allerdings das zweite Projekt anlegen wollte, kam eine Fehlermeldung, dass mir die Berechtigungen auf den Reporting Services fehlen. Seltsam nur, dass es beim ersten Projekt geklappt hat und dazwischen nichts geändert wurde. Mit einem kleinen Trick konnte ich dann doch ein zweites Projekt anlegen, nämlich indem ich alle Projekte aus dem Team-Explorer entfernt habe. Dann konnte ich wieder genau ein neues anlegen.

Die eigentliche Lösung für das Problem brachte aber die Installation des SP1 auf dem Server. Dabei ist zu beachten, dass das SP1 für den Team-Explorer nicht Bestandteil des Team Foundation Server SP1 ist, sondern des Visual Studio SP1. Also das Visual Studio SP1 installiert und danach lief es wunderbar.

Wednesday, May 13, 2009 3:15:29 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, May 12, 2009

clip_image001

 

Letzte Woche habe ich bei der .Net Developer-Group Ulm einen Vortrag zum Thema “10 Gründe warum Software-Projekte fehlschlagen – und was hilft ALM"?” gehalten. Es gab zu diesem Vortrag eine reihe interessanter Diskussionen. Die Folien gibt’s hier zum herunterladen:

Tuesday, May 12, 2009 9:15:05 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

Bei der TeamConf handelt es sich um eine Konferenz mit dem Focus auf Themen rund um VSTS und TFS. Da durfte ich natürlich nicht fehlen ;-)

Leider war mein Vortrag der letzte der Konferenz und dazu noch parallel zum VSTS 2010 Vortrag von Christian Binder. Dennoch fand sich eine interessierte Runde zum Thema “Requirements Management in leichtgewichtigen Prozessen” zusammen. Hier noch meine Folien zum Download:

Download File - TFSRequirementManagement
Tuesday, May 12, 2009 9:04:56 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

clip_image001

Termin: 19.05.2009 - 18:00 Uhr

Veranstaltungsort:

In den Räumen der artiso solutions GmbH Anfahrtsbeschreibung unter www.artiso.com

Referent:


Pedro Castelo Branco Lourenço

Vortrag:


Introducing F#

As Developers, when we see a given demand, we always think on how to solve on a very imperative way (first do this, then this, finally that). Why not starting thinking on a more functional level, where we do not need to break one given task into so small imperative steps? This session will introduce Microsoft's new language F#, a typed functional programming language for the .NET Framework that combines the succinctness, expressivity and compositionality of functional programming with the runtime support, libraries, interoperability, tools, and object model of .NET. We'll take a look at why Microsoft is adding the language to the suite of those available on .NET and at some of simple language constructs that make programming in F# a dream.

Pedro Castelo Branco Lourenço is a Brazilian guy that moved into Germany to work as Innovation manager at Savcor IT GmbH(http://www.savcor.de), MVP (Microsoft Most Valuable Professional) on C#, Microsoft Certified Professional Developer(Web & Windows), independent consultant to companies that build software using .Net platform, speaker in some well known technical events such as Tech Ed 2005, 2008(Brazil), Community Days, Developers On The Road, União.Net. Bachelor degree in computer science, member of moderator’s team of .Net Raptors community (www.dotnetraptors.com.br). During his free-time he is studying German to make his family life easier!

Tuesday, May 12, 2009 8:44:00 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, May 04, 2009

.NET Open Space vom 11.07. bis 12.07.2009 in Ulm

Zusammen mit Alexander Zeitler organisiere ich den .Net Opensapce Süd 2009. Seit heute ist die offizielle Homepage online und ich freue mich, die Veranstaltung hier ankündigen zu dürfen.

Die besten Gespräche hat man fernab von einer festgelegten Agenda, bei einem Kaffee und beim "du". Dort gibt es keine Rollenaufteilung in Sprecher / Zuhörer, Entwickler / Administrator usw. und die Themen finden sich vor Ort ganz von selbst. Das ist die Idee vom .NET Open Space, die sich bereits 2008 in Leipzig bewährt hat. Hier sind alle gleich. Auch die Organisatoren halten sich im Hintergrund und moderieren nur ab und an etwas.

Der .NET Open Space Süd 2009 läuft vom 11.07.2009 bis 12.07.2009. Welche Inhalte in dieser Zeit bearbeitet werden, wird vor Ort bestimmt, denn die Veranstaltung ist Open Space.

Die Teilnahme ist kostenlos. Die Teilnehmer gestalten das Programm selbst. Erfahrungsaustausch ist das A und O und steht im Vordergrund.

Mehr Informationen und Anmeldung unter: http://ulm.netopenspace.de

Ich würde mich natürlich freuen, möglichst viele bekannten Gesichter und den einen oder anderen Leser meines Blogs bei diesem Event begrüßen zu dürfen. Ausdrücklich möchte ich betonen, dass dies nicht nur ein Event für Experten ist, sondern dass natürlich auch Teilnehmer willkommen sind, die sich noch nicht für solche halten.

An dieser Stelle auch ein herzliches Dankeschön an Torsten Weber und Alexander Groß für die Unterstützung bei der Einrichtung der Website für den .NET Open Space Süd 2009.

Monday, May 04, 2009 11:35:53 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Wednesday, April 22, 2009

Im zweiten Teil wurde anhand eines kleinen Demos die konkrete Implementierung von WCF-Anwendungen erläutert. Es wurde ein Chat-System auf Basis der WCF erstellt. Das Demo gibt es hier zum Download. Außerdem möchte ich hier noch auf eine Einführung in die WCF hinweisen die man hier findet

Wednesday, April 22, 2009 6:53:51 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, April 14, 2009

Beim ersten Termin wurden die Grundlagen zu verteilten Anwendungen im allgemeinen und der WCF im speziellen vermittelt.

Tuesday, April 14, 2009 10:41:50 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Wednesday, April 08, 2009

Eines der coolsten Features in Windows 7 ist für mich der Problem Steps Recorder. Damit lassen sich Benutzeraktionen aufzeichnen und als MHT-File mit Screenshoots ausgeben. Diese Funktion eignet sich sehr gut um z.B. Installationsanleitungen oder auch Dokumentationen von Testdurchläufen zu erstellen. Hierzu wird einfach der Problem Steps Recorder über den Befehl PSR gestartet.

image

Nach einem Klick auf Start Record werden nun die Benutzeraktionen aufgezeichnet. Heraus kommt dann ungefähr so etwas:

Problem Step 15: User left double click on "Name (editable text)" in "WorkItem_Manager_Open_1.0.0_Installer[1]"

image

Previous Next

Problem Step 16: User left click on "Run (push button)" in "Open File - Security Warning"

image

Previous Next

Problem Step 17: User left click on "Next > (push button)" in "artiso Workitem Manager Open"

image


Diese Aufzeichnungen funktionieren sowohl mit Web- als auch Windows-Anwendungen. Und natürlich können die erzeugten MHT-Files in Word oder anderen Editoren noch bearbeitet werden. So können z.B. überflüssige Zwischenschritte entfernt und Texte editiert werden. Es können auch währen des Aufzeichnungsvorgangs Kommentare erfasst und diesen ein bestimmter Bildausschnitt zugeordnet werden.

Wednesday, April 08, 2009 1:07:35 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, April 06, 2009

Team System User Group - Virtual Edition

Grade erst wurden die EMEA-Meetings der Team System User Group Virtual Edition ins Leben gerufen, schon können wir mit einem Highlight aufwarten. Für unser April-Meeting konnten wir Brian Harry als Sprecher gewinnen. Brian wird über die Internal Adoption von VSTS sprechen. Brian ist Technical Fellow und Manager der Product Unit für den team Foundation Server.

Also gleich als Mitglied registrieren und am 16. April dabei sein!

Weitere Informationen zum Meeting gibt’s unter www.tsug-ve.com.

Monday, April 06, 2009 10:13:52 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Friday, April 03, 2009

clip_image001

Am 07. April um 18:00 Uhr findet das nächste Treffen der .Net Developer-Group Ulm statt. Diesesmal geht es im Rhamen der Microsoft Usergroup-Tour um das Thema Silverlight.

 

Referent: Philipp Bauknecht

Vortrag: Web & Silverlight

Der Referent Philipp Bauknecht zeigt anhand eines E-Commerce-Szenarios, welche neuen Möglichkeiten in Silverlight und den Microsoft-Webtechnologien stecken. Er gibt Einblicke in die Bildbearbeitung mit Expression Design und in das Arbeiten und Programmieren mit Expression Blend. Weitere Themenschwerpunkte sind die Veröffentlichung von Videos sowie die wesentlichen Silverlight-Entwicklungsgrundlagen in Visual Studio. Anhand praktischer Beispiele demonstriert Philipp Bauknecht, wie sich die letzte Meile zum Anwender mithilfe von Silverlight durch interaktive Methoden überwinden lässt.

Weitere Infos finden Sie  hier…

 

Freue mich auf zahlreiche Teilnehmer. Es gibt diesesmal wieder einen leckeren Imbiss der von der Fa. SOS Software Services gesponsort wird.

Friday, April 03, 2009 1:54:00 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Thursday, April 02, 2009

Der Tatsache, dass Testen eine wichtige Bedeutung in der Software-Entwicklung hat, trägt Microsoft ja bereits seit einiger Zeit Rechnung indem eine spezielle Edition des Visual Studio für Tester generiert wurde. Diese Edition besitzt umfangreiche Funktionenzu verschiedenen Test-Methoden. Das Ranger-Team hat nun einen Quick Reference Guide veröffentlicht der auf 83 Seiten diese Funktionen beschreibt und verschiedene Best Practices anbietet. Hierbei sind die Erfahrungen eingeflossen, die Service Labs, ein großes Test-Center, bei der Adaption von Team Test gemacht hat. Das Dokument enthält viele wertvolle Hinweise, wie VSTT in der Praxis eingesetzt und individuell erweitert werden kann.

Definitiv lesenswert für jeden, der etwas mehr über dieses Toolset erfahren möchte.

Download VSTT 2008 Quick Reference Guide

Thursday, April 02, 2009 7:33:23 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Wednesday, April 01, 2009

Das Thema Test Driven Development oder auch Test First Developent gewinnt immer mehr an Beachtung. Keine Konferenz, keine Zeitschrift, kein Sprecher der was auf sich hält kommt um das Thema herum. Doch nach dem überzeugenden Vortrag sitzt man zu Hause im Büro vor einem leeren Project und wie nun anfangen? Hier scheitern bereits die ersten, weil entsprechende Publikationen oft zwar die Vorteile ausführlich schildern, aber nicht den Einstieg darstellen. Deshalb möchte ich hier einen entsprechenden Einstieg geben und mit einem wirklich leeren Projekt beginnen.

Die Theorie um TDD will ich hier einfach weglassen. Hierzu gibt es bereits Informationen genug. Und wir werden verschiedene Vereinfachung vornehmen, über die Profis etwas die Nase rümpfen werden, aber damit erhalten wir ein einfaches und praktikable Einstiegsszenario.

Zum Einsatz kommen hierbei die Testfunktionen von Visual Studio 2008 die ab der Professional Edition enthalten sind. Wir beginnen mit einer komplett leeren Solution.

image

Die Frage, die nun im Raum steht, ist: Wie schreibe ich einen Test ohne eine Methode zu haben. Ein Unit-Test besteht ja im Prinzip darin, dass wir eine Methode aufrufen und den Rückgabewert mit einem Erwartungswert vergleichen. Der Test wird aber nicht einmal kompilieren, solange die Methode nicht definiert ist. Der Workaround an dieser Stelle sieht dann oft so aus, dass man von der Methode und ihrer Klasse erst einmal einen Stub anlegt der im wesentlichen eine “ThrowNotImplemented”-Exception wirft. Damit haben wir aber eigentlich schon mehr implementiert als nach dem TDD uns lieb ist.

Ein etwas eleganterer Ansatz geht über die Definition von Interfaces. Diese Vorgehensweise eignet sich besonders gut bei einer komponentenorientierten Architektur mit einem Contract First Ansatz. Dabei werden die Schnittstellen der einzelnen Komponenten erst über Contracts (Interfaces) beschrieben bevor diese implementiert werden. Den TDD-Ablauf Rot > Grün > Refactor erweitern wir ein wenig. Damit ergibt sich folgende Abfolge:

Contract definieren > Test implementieren > Rot > Funktion implementieren > Grün > Refactor

D.h. wir erstellen in einem ersten Schritt einen Contract (genau genommen machen wir damit kein TDD sondern ein Test First. Beim TDD ist der Test das erste was erstellt werden muss, aber das ist in meinen Augen eher Haarspalterei, so funktioniert es einfach in der Praxis). Wir erstellen ein neues ClassLibrary-Projekt und erstellen dort ein Interface.

   1: namespace Contracts
   2: {
   3:     public interface IOrderCalculator
   4:     {
   5:         decimal CalculateShippinghCosts(decimal sum, decimal freeShippingMin, decimal shippingCosts);
   6:     }
   7: }

Wir wollen hier ein überschaubares, aber auch nicht zu triviales Beispiel verwenden. Die Methode CalculateShippingCosts soll zu einem gegebenen Rechnungsbetrag Versandkosten hinzuaddieren, wenn ein bestimmter Mindestbetrag nicht erreicht ist. So damit haben wir den Contract erstellt. Nun wollen wir einen Test dazu erstellen. Das geht am schnellsten durch einen Rechts-Klick auf die Methode und dann “Create Unit-Tests”.

image

Hier wird standardmäßig ein neues Test-Projekt angelegt. Darin wird ein entsprechender Unit-Test generiert.

   1: [TestMethod()]
   2: public void CalculateShippinghCostsTest()
   3: {
   4:     IOrderCalculator target = CreateIOrderCalculator(); // TODO: Initialize to an appropriate value
   5:     Decimal sum = new Decimal(); // TODO: Initialize to an appropriate value
   6:     Decimal freeShippingMin = new Decimal(); // TODO: Initialize to an appropriate value
   7:     Decimal shippingCosts = new Decimal(); // TODO: Initialize to an appropriate value
   8:     Decimal expected = new Decimal(); // TODO: Initialize to an appropriate value
   9:     Decimal actual;
  10:     actual = target.CalculateShippinghCosts(sum, freeShippingMin, shippingCosts);
  11:     Assert.AreEqual(expected, actual);
  12:     Assert.Inconclusive("Verify the correctness of this test method.");
  13: }

Damit können wir den Test bereits zum ersten mal ausführen und er geht wie erwartet auf Rot. Aber Moment, wie funktioniert das. Wie kann der Test eine Methode auf einem Interface aufrufen? Es gibt ja noch keine Implementierung des Interfaces und ein Interface selbst lässt sich ja nicht instanziieren. Hier baut Visual Studio einen kleinen Workaround. In Zeile 4 im obigen Code sieht man, dass eine Instanz des target-Objektes über die Methode CreateIOrderCalculator() erstellt wird. Diese Methode wollen wir mal etwas genauer anschauen.

   1: internal virtual IOrderCalculator CreateIOrderCalculator()
   2: {
   3:     // TODO: Instantiate an appropriate concrete class.
   4:     IOrderCalculator target = null;
   5:     return target;
   6: }

Hier wird das Objekt einfach mit null initialisiert. Ein einfacher, aber wirkungsvoller Workaround. Damit erreichen wir unser Ziel, dass der Test kompiliert aber fehlschlägt. Nach der Implementierung ersetzen wir das null einfach durch die entsprechende Initialisierung. Damit können wir nun unsere Testcases Implementieren.

   1: [TestMethod()]
   2: public void CalculateShippinghCosts_Sum_Below_FreeShippingMin()
   3: {
   4:     IOrderCalculator target = CreateIOrderCalculator();
   5:     Decimal sum = 1;
   6:     Decimal freeShippingMin = 10;
   7:     Decimal shippingCosts = 5;
   8:     // We are below min, so we have to add shippingCosts
   9:     Decimal expected = 6;
  10:     Decimal actual;
  11:     actual = target.CalculateShippinghCosts(sum, freeShippingMin, shippingCosts);
  12:     Assert.AreEqual(expected, actual);
  13: }
  14:  
  15: [TestMethod()]
  16: public void CalculateShippinghCosts_Sum_Above_FreeShippingMin()
  17: {
  18:     IOrderCalculator target = CreateIOrderCalculator();
  19:     Decimal sum = 20;
  20:     Decimal freeShippingMin = 10;
  21:     Decimal shippingCosts = 5;
  22:     // We are above min, so we don't add shippingCosts
  23:     Decimal expected = 20;
  24:     Decimal actual;
  25:     actual = target.CalculateShippinghCosts(sum, freeShippingMin, shippingCosts);
  26:     Assert.AreEqual(expected, actual);
  27: }
  28:  
  29: [TestMethod()]
  30: public void CalculateShippinghCosts_Sum_Equal_FreeShippingMin()
  31: {
  32:     IOrderCalculator target = CreateIOrderCalculator();
  33:     Decimal sum = 10;
  34:     Decimal freeShippingMin = 10;
  35:     Decimal shippingCosts = 5;
  36:     // We are equal min, so we don't add shippingCosts
  37:     Decimal expected = 10;
  38:     Decimal actual;
  39:     actual = target.CalculateShippinghCosts(sum, freeShippingMin, shippingCosts);
  40:     Assert.AreEqual(expected, actual);
  41: }

Damit haben wir unser Szenario ausreichend beschrieben. Wir können nun an die Implementierung gehen.Dazu legen wir ein neues Projekt an in dem wir eine Klasse definieren die wir von unserem Interface ableiten.

   1: namespace Components
   2: {
   3:     public class cOrderCalculator : IOrderCalculator
   4:     {
   5:         public decimal CalculateShippinghCosts(decimal sum, decimal freeShippingMin, decimal shippingCosts)
   6:         {
   7:             // If sum is greater than Min then don't add shipping costs
   8:             if (sum > freeShippingMin)
   9:                 return sum;
  10:             else
  11:                 // else add shipping costs
  12:                 return sum + shippingCosts;
  13:         }
  14:     }
  15: }

Nun müssen wir unbedingt noch daran denken, die Initialisierung des Testobjektes in unserer Testmethode anzupassen.

   1: internal virtual IOrderCalculator CreateIOrderCalculator()
   2: {
   3:     IOrderCalculator target = new cOrderCalculator();
   4:     return target;
   5: }

Nun können wir die Tests ausführen.

image

Oh, ein Test schlägt fehl. Bei genauerer Betrachtung stellen wir fest, dass wir bei der Implementierung den Fall dass die Summe gleich der Grenze ist nicht richtig berücksichtigt haben. Also hat sich hier der TDD-Ansatz schon bewährt und wir können den Fehler beheben. Damit sind alle Tests grün und wir können weiter fortfahren. Wir könnten nun z.B. auf unserem Interface weitere Methoden definieren und dafür Tests anlegen.

Also eigentlich gar nicht so schwer das mit dem TDD, oder? Freue mich auf euer Feedback.

Die Solution gibt es zum Download.

Happy Testing!

Wednesday, April 01, 2009 1:10:53 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |  |   | 
 Tuesday, March 31, 2009

002

Letzte Woche war ich als Trainer beim Team System Camp. Eine wirklich bemerkenswerte Veranstaltung! Schon der Veranstaltungsort selbst war bemerkenswert. Das Häckers Kurhotel in Bad Ems stellte einen durchaus würdigen Rahmen für die Veranstaltung dar und auch der Seminarraum hatte durchaus Stil:

002

Die Verpflegung war dem Ambiente angemessen, Mittags und Abends ein vorzügliches 3-Gänge-Menü und auch das Rahmenprogramm passte. Mit Kart-Fahren, Casino-Besuch und weiteren Aktivitäten konnte ein paar Momente entspannt werden. Das war auch dringend nötig. Denn trotz all dieser Annehmlichkeiten kamen natürlich die Inhalte nicht zu kurz. Zwei Trainer auf 5 Teilnehmer ist sicher schon ein ungewöhnlicher Schnitt. Aber dass die Trainings von 9:00 Uhr bis 23:00 gehen ist schon heftig. Also wurde nach dem Kart-Fahren noch was gegessen und dann ging’s im Seminar-Raum weiter. So konnten die Teilnehmer sicher einen sehr guten Überblick über den Team Foundation Server und VSTS bekommen. Und durch die kleine Gruppengröße konnte auch auf individuelle Fragen ausführlich eingegangen werden.

Mir hat’s jedenfalls viel Spaß gemacht und bin beim nächsten mal gerne wieder dabei.

Tuesday, March 31, 2009 11:04:06 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

Für alle die entweder in der Nähe von Wien leben oder die entsprechend großes Interesse am Thema VSTS haben um diese schöne Stadt auch mal zu besuchen, hier eine Ankündigung:

 

Am 8. Mai 2009 wird im Microsoft Innovation Center (MIC) in Wien der Office (VSTO) Community Day statt finden. Hierbei geht es 1 Tag lang rund um Office Business Applications. Die Veranstaltung wird von Lars Keller und Mario Meir-Huber geführt.

 

Die Themen sind:

 

·         Einführung in die VSTO

·         OpenXML: Das neue Office Format

·         VSTO Deployment

·         Sharepoint Workflows und Integration

·         Interaktionen in der "Office-Welt" mit .NET

·         Office plus Services

 

Die Veranstaltung ist frei zugänglich, jedoch gibt es eine Limitierung auf 35 Teilnehmer. Anmelden kann man sich in dem extra für das Event aufgesetzten Wiki (http://www.vsto-taskforce.de/wikis/ocd/teilnehmer.aspx).

Tuesday, March 31, 2009 4:21:45 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

Die Integration von Visual Studio 2005 / 2008 mit dem TFS ist ideal gelöst. Jedoch gibt es auch noch andere Entwicklungs-Plattformen die keine direkte Integration mit dem Team-Explorer erlauben wie z.B. ältere Visual Studio Versionen und leider auch immer noch das SQl Server Management Studio. Diese IDEs überstützen doch recht häufig den sog. MSSCCI-Standard und es gibt bereits seit längerer Zeit einen entsprechenden MSSCCI-Provider für den TFS 2008. Dieser hatte bisher immer noch den nachteil, dass er reine Sourcecontrol Features unterstützt hat und z.B. das Verknüpfen von Workitems beim Checkin nicht möglich war. In der neuesten Version ist dies nun auch möglich und somit ist auch bei IDEs die den Team Explorer nicht integrieren ein komfortables Arbeiten mit dem TFS möglich. Ich habe hier mal ein Beispiel für das SSMS 2008.

Zunächst muss der TFS MSSCCI-Provider unter Optionen eingestellt werden.

image

Legt man nun ein Datenbankprojekt an, dann kann man das in gewohnter Art und Weise mit der Source Control verbinden und man erhält Fenster “Pending Checkins”.

image

Führt man hier nun den Checkin aus, kommt der aus dem Team-Explorer bekannte Dialog

image

Hier können nun z.B. Checkin-Kommentare angegeben oder Workitems verknüpft werden.

image

Sogar die Checkin-Plicies funktionieren hier wie gewohnt.

image

Damit ist ein komfortables und problemloses Arbeiten auch mit solchen Umgebungen möglich, die den Team-Explorer nicht direkt integrieren. Und damit wieder ein Grund mehr, nun endlich auf den TFS zu setzen und SourceSafe und Konsorten endlich in Rente zu schicken.

Tuesday, March 31, 2009 4:18:04 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, March 30, 2009

Team System User Group - Virtual Edition

Bei der Team System Usergroup – Virtual Edition (TSUG-VE) handelt es sich um eine weltweite Online-Community die sich auf die Themen Visual Studio Team System und Team Foundation Server konzentriert hat. Die Treffen finden dabei zeitgleich in SecondLife und LiveMeeting statt. SecondLife bietet den Vorteil, die sozialen Aspekte einer Community besser in der Online-Welt abzubilden, LiveMeeting wird als Präsentationssystem genutzt. Die virtuellen Treffen unterscheiden sich vom Ablauf und Inhalt kaum von denen entsprechender Offline-Communities. Während und nach den Vorträgen können ganz normal Fragen gestellt werden. Die Vorträge werden aufgezeichnet und stehen Mitgliedern im nachhinein im LiveMeeting-Portal zur Verfügung.

Um die Vortragszeiten für die Teilnehmer rund um den Globus komfortabler zu gestalten, wurde nun eine europäische Sektion der TSUG-VE ins Leben gerufen. Diese Sektion organisiert Meetings in einer komfortablen Zeit für die EMEA-Zone (19:00 Uhr deutscher Zeit). Natürlich steht den Mitgliedern jederzeit die Möglichkeit offen, an den Treffen der US-Sektion oder für den Bereich Asian-Pacific (momentan im Aufbau) teilnehmen zu können oder die Videos nachträglich abzurufen ohne sich hierfür separat registrieren zu müssen. Alle Treffen werden in englischer Sprache abgehalten.

Die Leitung der EMEA-Zone habe ich übernommen und würde mich freuen, in Zukunft mehr Mitglieder aus dem Europa begrüßen zu dürfen. Kritik und Anregungen zur Organisation sind sehr willkommen, da wir im Moment noch dabei sind Erfahrungen im Betreiben einer Online-Community sammeln.

Monday, March 30, 2009 7:55:00 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Friday, March 20, 2009

Silverlight 2D Combination Chart

VISfire sit eine Charting-Komponente für Silverlight und WPF. Das coole daran ist, dass die Charts animiert werden können.  Einen schnellen Eindruck bekommnt man über die Silverlight Chart Gallery. Die componente ist unter GPL und einer kommerziellen Lizenz verfügbar.

Friday, March 20, 2009 9:31:45 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Sunday, March 15, 2009

image

Wie so oft lautet die Antwort es kommt darauf an. Un hier bietet die Seite ShineDraw eine gute Vergleichsmöglichkeit. In der Gallery befinden sich zahlreiche Beispiele die sowohl in Silverlight als auch in Flash implementiert sind. Da kann man nicht nur das Ergebnis in beiden Varianten vergleichen sondern auch den Code der in der jeweiligen Technologie erforderlich ist. Darüber hinaus kann man sich den einen oder anderen effekt abschauen und sieht auch gleich wie der implementiert wird. Der Quellcode ist unter der GNU General Public License, Version 3 bereitgestelt.

http://www.shinedraw.com/flash-vs-silverlight-gallery/

Sunday, March 15, 2009 7:41:00 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Saturday, March 14, 2009

Die Initiative Clean Code Developer (CCD) (http://www.clean-code-developer.de/) hat sich zum Ziel gesetzt bestimmte Grundsätze bei der Entwicklung von Software bei den Entwicklern besser zu verankern. Bei diesen Grundsätzen handelt es sich um Prinzipien, Regeln und Praktiken deren Einhaltung zu qualitativ höherwertigem Code führt. Grundsätzlich ist eine Schrittweise Einführung dieser Prinzipien, regeln und Praktiken unterteilt in Grade vorgesehen. Zu jedem Grad gibt es ein farbiges Armband, das den Träger zum Einen als CCD ausweist und ihn zudem stets daran erinnert diese Grundsätze in seiner täglichen Arbeit zu befolgfen. Mit Sefan Lieser und Ralf Westphal stehen hinter diesem Projekt zwei ausgewiesene Experten.

Die .Net Developer-Group Ulm (www.dotnet-ulm.de) möchte diese Aktion unterstützen und ruft seine Mitglieder auf sich zu beteiligen. Beim nächsten Treffen am 19.03.09 wird diese Aktion im Detail vorgestellt und es besteht die Möglichkeit die Armbänder zu einem vergünstigten Preis zu erwerben. Zudem ist angedacht, dass sich die beteiligten regelmäßig nach den UG-Meetings austauschen und gegenseitig über Erfahrungen berichten und die Konzepte des CCD miteinander diskutieren.

Natürlich freue ich mich auf eine rege Teilnahme und natürlich sind Gäste gerne willkommen.

Nähere Infos unter http://www.dotnet-ulm.de/Cleancodedeveloper.aspx

Saturday, March 14, 2009 2:00:33 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Friday, March 13, 2009

 image

Mit diesem Sidebar-Gadget kann man sich den Status seiner Build schnell und einfach anzeigen lassen.

Jim Lamb : Team Build Monitor – Vista Sidebar Gadget

Friday, March 13, 2009 1:34:33 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [2]    | 

clip_image001

Bei unserem nächsten Treffen am 19.03 haben wir Gregor Biswanger und Robert Walter zu Gast. Diese werden in ihrem Vortrag verschiedene Aspekte zu Test Driven Development beleuchten. Nähere Infos gibts hier:

http://www.dotnet-ulm.de/Treffen.aspx#19032009

Friday, March 13, 2009 9:05:18 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

MSDN Webcasts

Am 16.03.09 geht ein neuer Webcast von mir online mit dem Thema "Team Build mit Custom Build Tasks erweitern". Ich möchte hier schon mal die entsprechenden Infos veröffentlichen.

In TeamBuild lassen sich eigene Build-Task integrieren. Diese können sehr einfach erstellt werden. Hierzu wird eine Klasse erstellt und diese von Task abgeleitet. Im folgenden Beispiel wird ein Build-Task erstellt, der im Rahmen des Builds die Version der Anwendung setzt. Und zwar soll hier die Build-Nummer in der Versionsnummer der Assembly abgebildet werden. Dies bietet Vorteile, wenn zu einer bestimmten Anwendungsversion der entsprechende Build identifiziert werden soll.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using Microsoft.Build.Utilities;
   5: using Microsoft.Build.Framework;
   6:  
   7: namespace Artiso.BuildTasks
   8: {
   9:     /// <summary>
  10:     /// Creates a AssemblyVersion out of a BuildNumber
  11:     /// </summary>
  12:     /// <remarks>
  13:     /// AssemblyVersion.Minjor and AssemblyVersion.Minor will be defined fiexed in
  14:     /// the Build-Script. If the BuildNumber is Dev_Versioning_20090305.4 we use 
  15:     /// two digit year and month for AssemblyBuildNumber and day and 3 digit BuildRevision
  16:     /// for AssemblyRevision. BuildRevisio 
  17:     /// </remarks>
  18:     /// <example>
  19:     /// Dev_Versioning_20090305.4 => xx.yy.0903.05004
  20:     /// </example>
  21:     public class ExtractRevision : Task
  22:     {
  23:         #region [rgn] Fields(3)
  24:         private string buildRevision;
  25:         private string buildVersion;
  26:         private string buildNumber;
  27:         #endregion
  28:  
  29:         #region [rgn] Properties(3)
  30:         /// <summary>
  31:         /// Input Build Number
  32:         /// </summary>
  33:         [Required]
  34:         public string BuildNumber
  35:         {
  36:             set { buildNumber = value; }
  37:         }
  38:  
  39:         /// <summary>
  40:         /// Returns the sortened date of the build
  41:         /// </summary>
  42:         [Output]
  43:         public string BuildVersion
  44:         {
  45:             get { return buildVersion; }
  46:         }
  47:  
  48:         /// <summary>
  49:         /// Returns the Build Revision (number of build at this day
  50:         /// </summary>
  51:         [Output]
  52:         public string BuildRevision
  53:         {
  54:             get { return buildRevision; }
  55:         }
  56:         #endregion
  57:  
  58:         #region [rgn] Methods(1)
  59:         public override bool Execute()
  60:         {
  61:             buildVersion = "0";
  62:             buildRevision = "0";
  63:  
  64:             if (buildNumber != null && buildNumber.Contains("."))
  65:             {
  66:                 string[] buildNumberParts = buildNumber.Substring(buildNumber.LastIndexOf('_')+1).Split('.');
  67:  
  68:                 // Dev_Versioning_20090305.4 -> 0903.02005
  69:                 // use year (2 digits) and mont for buildversion
  70:                 buildVersion = buildNumberParts[0].Substring(2, 4);
  71:  
  72:                 // use day and number of build in this day for build revision
  73:                 buildRevision = buildNumberParts[0].Substring(6) + buildNumberParts[1].PadLeft(3, '0');
  74:             }
  75:             return true;
  76:         }
  77:         #endregion
  78:     }
  79: }

Das Property BuildNumber wird als Input-Parameter verwendet und mit dem Attribut [Required] versehen. Darüber kann die BuildNumber in unseren Task übergeben werden. Durch das Attribut [Output] werden die beiden Properties BuildVersion und BuildRevision als Rückgabewerte definiert. Beim Ausführen des Builds wird die Methode Execute aufgerufen. Hier werden nun aus der Build-Number die entsprechenden Informationen extrahiert und diese dann in BuildVersion und BuildRevision zurückgeschrieben. Dies ist natürlich nur ein einfaches Beispiel, aber mit diesen Grundlagen können nun beliebige Build-Tasks definiert werden. Im nächsten Schritt schauen wir uns an, wie wir diesen Custom Build Task nun in unseren Build-Prozess einbinden. Hierzu kopieren wir zunächst die Assembly in einen entsprechenden Ordner. Hier bietet sich an unter c:\Program Files\MSBuild einen entsprechenden Ordner anzulegen und dort die Assemblies abzulegen.

Nun muss das Build-Script entsprechend angepasst werden. Diese liegt in der Quellcode-Verwaltung und muss zum Bearbeiten zuerst aus- und danach wieder eingechecked werden. Um diesen Vorgang zu vereinfachen empfehle ich die TFS Sidekicks (http://www.attrice.info/downloads/index.htm) die direkt im Kontextmenü des TeamExplorers entsprechende Kommandos einfügt. Das nun ausgecheckte PROJ-File kann nun bearbeitet werden.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <!-- DO NOT EDIT the project element - the ToolsVersion specified here does not prevent the solutions 
   3:      and projects in the SolutionToBuild item group from targeting other versions of the .NET framework. 
   4:      -->
   5: <Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
   6:  
   7:   <!-- Do not edit this -->
   8:   <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
   9:   <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
  10:  
  11:   <UsingTask AssemblyFile="$(MSBuildExtensionsPath)\ArtisoBuildTasks\ArtisoBuildTasks.dll"
  12:     TaskName="ExtractRevision"/>
  13:  
  14:   <PropertyGroup>
  15:     <!-- Assembly version properties. Adjust here Major and Minor Version-->
  16:     <AssemblyMajorVersion>1</AssemblyMajorVersion>
  17:     <AssemblyMinorVersion>3</AssemblyMinorVersion>
  18:     <AssemblyBuildNumber>1</AssemblyBuildNumber>
  19:     <AssemblyRevision>1</AssemblyRevision>
  20:   </PropertyGroup>
  21:  
...
In Zeile 11 wird unser BuildTask entsprechend registriert. In Zeile 9 werden noch weitere Build-Tasks registriert. Hier gereicht es uns zum Vorteil, dass Team-Build auf MSBuild basiert. D.h. es können entsprechende Tasks für MSBuild problemlos integriert werden. Diese gibt es in großer Zahl für sehr viele Anwendungsbereiche zum großen Teil frei Verfügbar zum Download. Wir verwenden hier die MSBuild Community Tasks (http://msbuildtasks.tigris.org/). Wir werden aus diesem Paket Aktionen verwenden.
 
In den Zeilen 14 bis 20 wird eine sog. PropertyGroup angelegt. Darin werden einzelne Properties definiert und mit Default-Werten vorbelegt. Diese Properties lassen sich mit Variablen innerhalb eines Software-Codes vergleichen. Die AssemblyMajorVersion und AssemblyMinorVersion werden hier festgelegt. AssemblyBuildNumber und AssemblyRevision werden wir im weiteren Verlauf überschreiben.
 
Am Ende des Scripts direkt vor dem schließenden </Project>-Tag wird nun ein Target-Block eingefügt.
 
   1: ...
   2: <Target Name="AfterGet">
   3:    <ItemGroup>
   4:      <AssemblyInfoFiles Include="$(SolutionRoot)\**\assemblyinfo.cs" />
   5:    </ItemGroup>
   6:  
   7:    <Message Text="Get Revision Number from BuildNumber &quot;$(BuildNumber)&quot;." />
   8:    <ExtractRevision BuildNumber="$(BuildNumber)">
   9:      <Output TaskParameter="BuildRevision" 
  10:              PropertyName="AssemblyRevision" />
  11:      <Output TaskParameter="BuildVersion" 
  12:              PropertyName="AssemblyBuildNumber" />
  13:    </ExtractRevision>
  14:  
  15:    <!-- Update all the assembly info files with generated version info -->
  16:    <Message Text="Modifying AssemblyInfo files under &quot;$(SolutionRoot)&quot;." />
  17:    <Attrib Files="@(AssemblyInfoFiles)" Normal="true" />
  18:    <FileUpdate Files="@(AssemblyInfoFiles)"
  19:                Regex="AssemblyVersion\(&quot;.*&quot;\)\]" 
  20:                ReplacementText="AssemblyVersion(&quot;$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)&quot;)]" />
  21:    <FileUpdate Files="@(AssemblyInfoFiles)"
  22:                Regex="AssemblyFileVersion\(&quot;.*&quot;\)\]" 
  23:                ReplacementText="AssemblyFileVersion(&quot;$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)&quot;)]" />
  24:    <Message Text="AssemblyInfo files updated to version &quot;$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)&quot;" />
  25:  </Target>
  26:  
  27: </Project>
Über den Namen des Target-Blocks mit "AfterGet" wird festgelegt, dass dieser Block ausgeführt wird, nachdem der Build-Prozess die Quelldateien aus der Versionsverwaltung geholt hat. Genau zu diesem Zeitpunkt wollen wir unsere Versionierung anpassen. In den Zeilen 3 bis 5 erstellen wir eine ItemGroup die alle assemblyinfo.cs Dateien unserer Solution enthält. In diesen Dateien wollen wir die Version anpassen. In Zeile 7 wird eine Meldung in das Build-Log geschrieben. Dies ist hilfreich, um Fehler im Ablauf des Scriptes besser einordnen zu können.
In den Zeilen 8 bis 13 wird nun unser Build-Task aufgerufen. Wir übergeben die Buildnummer $(BuildNumber) in den Parameter BuildNumber und lesen die Output-Parameter aus und schreiben diese in AssemblyRevision bzw. AssemblyBuildNumber (die Properties die wir weiter oben definiert hatten). In Zeile 17 heben wir den Schreibschutz der AssemblyInfo-Dateien auf und in den folgenden Zeilen wird mit Hilfe eines Ersetzen-Vorgangs die Version in den AssemblyInfo-Dateien ersetzt. Für diese Aktionen nutzen wir die Community Build Tasks.
Damit können wir nun die Version unserer Anwendung bei jedem Build entsprechend setzen.
In einem nächsten Schritt wollen wir den Build-Task nun noch erweitern um das Build-Result in einer ZIP-Datei zu verpacken und diese anschließend per Mail zu versenden. Auch hierbei greifen wir auf die MSBuild Community Tasks zurück. Das entsprechende Target-Tag fügen wir einfach nach dem zuvor definierten ein. Als Name geben wir "AfterCompile" an so dass diese Aktionen nach dem Kompilieren ausgeführt werden.
   1: <Target Name="AfterCompile">
   2:   <CreateItem Include="..\Binaries\Release\**\*.*" Exclude="..\Binaries\Release\**\*.pdb;..\Binaries\Release\**\*codeanalysis*">
   3:     <Output ItemName="ZipFiles" TaskParameter="Include"/>
   4:   </CreateItem>
   5:  
   6:   <Message Text="Zipping Buildresult to \\tfs\deploy\BuildDemo\BuildDemo_$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision).zip" />
   7:  
   8:   <Zip ZipFileName="\\tfs\deploy\BuildDemo\BuildDemo_$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision).zip" 
   9:        Files="@(ZipFiles)"
  10:        WorkingDirectory="..\Binaries\Release\"/>
  11:  
  12:   <Mail SmtpServer="tfs"
  13:           To="tschissler@tfs"
  14:           From="build@tfs"
  15:           Subject="BuildDemo v$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision) released"
  16:           Body="A new version of the BuildDemo was released. Please find the newest files attached to this mail. You can also download them from the download folder."
  17:           Attachments="\\tfs\deploy\BuildDemo\BuildDemo_$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision).zip"/>
  18: </Target>

Hier sammeln zunächst alle Dateien aus dem Build-Drop-Verzeichnis exklusive der PDB- und Codeanalyse-Dateien In Zeilen 8-10 werden diese Dateien in ein ZIP-File verpackt dem wir im datei-Name die Version mitgeben. Anschließend versenden wir eine e-Mail der wir dieses ZIP-File als Attachment anhängen.

Als zweite Variante wollen wir im Rahmen des Builds ein Click-Once Paket erstellen. Die Herausforderung bei der Erstellung des ClickOnce-Paketes ist dass dort die Deployment-Url hinterlegt werden muss. Vor allem wenn verschiedene Pakete für unterschiedliche Kunden erstellt werden sollen, ist dies nur durch eine Automatisierung im Rahmen des Builds sinnvoll handelbar. Hierzu ersetzen wir den AfterCompile-Target durch folgendes Script:

   1: <Target Name="AfterCompile">
   2:    <!-- Publish using ClickOnce -->
   3:    <Message Text="modify Publish directory for $(SolutionRoot)" />
   4:    <!-- Update directory where to publish the project -->
   5:    <ItemGroup>
   6:      <ProjectFiles Include="$(SolutionRoot)\Source\Dev\BuildDemo\BuildDemo.csproj" />
   7:    </ItemGroup>
   8:    <PropertyGroup>
   9:      <PublishDir>\\tfs\Deploy\BuildDemo\ClickOnce\</PublishDir>
  10:      <InstallUrl>\\tfs\Deploy\BuildDemo\ClickOnce\</InstallUrl>
  11:    </PropertyGroup>
  12:    <Attrib Files="@(ProjectFiles)" Normal="true" />
  13:    <FileUpdate Files="@(ProjectFiles)"
  14:      Regex="&lt;PublishUrl&gt;.*&lt;/PublishUrl&gt;"
  15:        ReplacementText="&lt;PublishUrl&gt;$(PublishDir)&lt;/PublishUrl&gt;" />
  16:    <FileUpdate Files="@(ProjectFiles)"
  17:        Regex="&lt;InstallUrl&gt;.*&lt;/InstallUrl&gt;"
  18:        ReplacementText="&lt;InstallUrl&gt;$(InstallURL)&lt;/InstallUrl&gt;" />
  19:  
  20:    <MSBuild Projects="@(ProjectFiles)"
  21:    Properties="PublishDir=$(PublishDir);ApplicationVersion=$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)"
  22:            Targets="Publish" />
  23:  
  24:  </Target>

In den Zeilen 5 bis 7 lesen wir das csproj-File der Anwendung in eine ItemGroup. Anschließend definieren wir zwei Properties für PublishDir und InstallUrl. Diese werden dann über eine Ersetzung in die csproj-Datei eingefügt. Anschließend wird ein MSBuild-Task gestartet der das ClickOnce-Paket erstellt und an der angegebenen PublishDir und mit der Versionsnummer veröffentlicht.

Das Ganze wird in dem genannten Webcast Live demonstriert. Über Feedback würde ich mich sehr freuen.

Details zur Veranstaltung: Team Build mit Custom Build Tasks erweitern [1032405249] - Microsoft Deutschland GmbH

Friday, March 13, 2009 2:05:16 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |   | 
 Thursday, March 12, 2009

Letzte Woche war ich auf dem MVP-Summit in Seattle. Für mich war es die erste Veranstaltung dieser Art und so wusste ich nicht genau, was mich erwarten würde. Ich wurde aber auf jeden Fall positiv überrascht. Es war für mich eine Woche voller neuer Infos und Eindrücke und es war auch sehr cool, die anderen Team System MVPs persönlich zu treffen und sich mit denen auszutauschen.

Gerade im Bereich Team System tut sich momentan extrem viel und so hatten wir ein Non-Stop Programm und um VSTS 2010. Non Stop heißt, dass es bereits am Sonntag Nachmittag mit einer MVP 2 MVP Session losging, wo einige MVPs Erfahrungen aus ihrer Praxis darstellten. Das war extrem interessant und ich konnte viele neue Ideen mitnehmen. Am Montag und Dienstag hatten wir dann von 8:00 bis 18:00 Uhr volles Programm. Verschiedene Mitglieder der Product-Group stellten die einzelnen Bereiche von VSTS 2010 vor. Volles Programm heißt in diesem Fall Sessions ohne Pause (wir hatten selbst Lunch-Sessions, wo man sich am Buffet etwas zu Essen holte und dann sich setzte um der aktuellen Session zu folgen). Neno hat wirklich ein anspruchsvolles Programm für uns zusammen mit der Product-Group zusammengestellt. Da war wirklich extrem viel Content drin. Am Mittwoch waren dann Key-Notes angesagt, die ich allerdings etwas enttäuschend fand und damit wirklich keine Zeit verschwendet war, hatten wir am Mittwoch Nachmittag nochmals Sessions bei denen wir mit Sam Guckenheimer über die zukünftige Entwicklung diskutierten.

Eine wirklich extrem interessante Woche mit vielen neuen Eindrücken. Es wird wohl etwas dauern, bis ich das alles verarbeitet habe, der geneigte Leser wird aber dann die Ergebnisse an dieser Stelle lesen können ;-) Im Moment kann ich das Ganze nur so zusammenfassen: VSTS 2010 is a realy big, big  thing!

Hier noch ein paar Impressionen:

P1020645

Blick von der Space Needle auf Seattle

P1020686

Die Team-System MVPs

P1020691

Sam Guckenheimer

P1020704

Brian Harry

P1020726 

Karaoke mit Live-Band bei der Party

P1020754

Steve Balmer bei seiner Key-Note

Thursday, March 12, 2009 12:22:12 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Tuesday, February 24, 2009

image

Gestern und heute hatte ich auf der BASTA zwei Vorträge. Hier die Folien dazu:

Tuesday, February 24, 2009 9:52:49 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [1]    | 

MSDN Webcasts 

Zusammen mit Christian Binder habe ich einen WebCast aufgenommen in dem wir PEX vorstellen. Der WebCast wird ab 12.03 online sein.

Details zur Veranstaltung: Unit-Test Generierung mit PEX [1032405246] - Microsoft Deutschland GmbH

Tuesday, February 24, 2009 9:06:26 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Friday, February 20, 2009

Visual Studio, Visual Studio 2005, Konferenz, VS 2005, VS Konferenz, SQL Konferenz, Agile, .NET 2.0, .NET 3.0, .NET, ASP .NET, ASP .NET 2.0, Marquardt, Loje, Dröge, Westphal, ADC, Avanced Developers Conference, ASP konferenz, Business Compact, LINQ, T-SQL, Health Care,  ,NET 3.5 Framework, Windows 2008 Server, Visual Studio 2008, SQL Server 2008, SQL Server, SQL Server 2005, ASP .NET AJAX, AJAX, Business Intelligence, SharePoint 2007, 3D, Windows Forms,  IMAX, ADO .NET, Agile Projekte, Agile, Analysis Services 2008, WPF, WF, WCF, Silverlight, Service Broker 2008, Data Mining, BizTalk Server, XML, Integration Services, VB.NET, XAML,  Blend, Performance-Optimierung 2005, Visual Studio Team System, SCD Transformations,  OLAP, MDX, PowerShell, Web 2.0, Windows Web Server 2008, ppedv AG, Vista, Microsoft, MS, Windows

Ich bin reichlich spät dran, die VSOne ist schon seit einer Woche vorbei. Hier aber nun endlich meine Folien zu meinen Vorträgen

Friday, February 20, 2009 8:03:56 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

MSDN Webcasts

Zusammen mit Christian habe ich einen Webcast zum Thema Testing Practices aufgenommen. In dem Webcast werden zunächst verschiedene Testmethoden vorestellt und anschließend werden verschiedene Aspekte einer Teststrategie diskutiert wie z.B. Methoden zur Testfall-Ermittlung.

Der komplette Abstract lautet:

Qualität spielt in Software-Projekten eine immer größere Rolle. Ein wesentlicher Aspekt für Software-Qualität ist das Testen. Der Webcast stellt zunächst kurz die verfügbaren Testmethoden in Visual Studio vor und zeigt anschließend Aspekte einer Test-Strategie auf. Darüber hinaus wird die Integration mit dem Team Foundation Server kurz beleuchtet und es werden Methoden zur Testfallermittlung beschrieben.

Über ein Feedback zum Webcast würde ich mich freuen.

http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032405240

Friday, February 20, 2009 7:12:30 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |  |   | 

An einem kleinen Beispiel möchte ich kurz erläutern, wie PEX parametrisierte Unit-Tests nutzt und wie man diese nutzen kann um bestimmte Test-Szenarien abzubilden. Wir nehmen einen kleinen Codeausschnitt um uns das mal anzusehen:

   1: public class TotalSum
   2: {
   3:     private double total = 0;
   4:  
   5:     public double CalculateTotals(List<cOrderPosition> OrderPositions, double Rebate)
   6:     {
   7:         if (OrderPositions == null)
   8:             return 0;
   9:  
  10:         foreach (cOrderPosition orderPos in OrderPositions)
  11:         {
  12:             if (orderPos.Amount > 0 && orderPos.SinglePrice > 0)
  13:                 total += orderPos.Amount * orderPos.SinglePrice;                
  14:         }
  15:  
  16:         if (Rebate > 0)
  17:             total = total * (1 - Rebate);
  18:  
  19:         return total;
  20:     }
  21:  
  22:     public class cOrderPosition
  23:     {
  24:         public int ProductID { get; set; }
  25:         public double Amount { get; set; }
  26:         public double SinglePrice { get; set; }
  27:     }
  28: }

 

Auf den ersten Blick scheint da alles OK zu sein. Mal sehen was PEX daraus jetzt macht.

image

Zunächst sehen wir, dass PEX 3 Probleme mit Object Creations hat. Für den ersten Fall lassen wir PEX einfach automatisiert eine Factory erstellen indem wir auf "Accept/Edit factory" klicken. Für die Liste müssen wir ebenfalls eine Factory erstellen. Diese Factory wollen wir jetzt noch anpassen:

   1: [PexFactoryMethod(typeof(List<TotalSum.cOrderPosition>))]
   2: public static List<TotalSum.cOrderPosition> Create(int NumberOfItems)
   3: {
   4:     List<TotalSum.cOrderPosition> list = new List<TotalSum.cOrderPosition>(NumberOfItems);
   5:     if (NumberOfItems > 10)
   6:         NumberOfItems = 10;
   7:  
   8:     for (int i = 0; i < NumberOfItems; i++)
   9:     {
  10:         list.Add(new TotalSum.cOrderPosition()
  11:         {
  12:             ProductID = i + 1,
  13:             SinglePrice = new Random().NextDouble() * 10,
  14:             Amount = new Random().NextDouble() * 10
  15:         });
  16:     }
  17:        
  18:     return list;
  19: }

 

Abhängig von der Anzahl Items die als Parameter übergeben wird, wird die Liste mit entsprechend vielen Elementen befüllt. Nun erhalten wir Ergebnisse bei der Exploration.

image

Und es sind alle grün. Also alles OK? Jetzt kommt der parametrisierte Unit-Test in's Spiel. Dazu müssen wir erst mal die Test generieren. Dazu einfach alle Einträge markieren und rechts auf "Save..." klicken.

image 

   1: [TestMethod]
   2: [PexGeneratedBy(typeof(TotalSumTest))]
   3: public void CalculateTotals04()
   4: {
   5:     TotalSum totalSum;
   6:     List<TotalSum.cOrderPosition> list;
   7:     double d;
   8:     totalSum = TotalSumFactory.Create();
   9:     list = ListFactory.Create(1);
  10:     d = this.CalculateTotals(totalSum, list, 0);
  11:     Assert.AreEqual<double>(42.232177096754121, d);
  12: }

Wenn wir uns eine der generierten Testmethoden mal genauer anschauen, dann erkennen wir dass in Zeile 9 unsere ListFactory aufgerufen wird und in Zeile 10 wird eine Methode CalculateTotals aufgerufen. Bei dieser Methode handelt es sich um unseren parameterisierten Unit-Test der in der .cs-Datei abgelegt ist. Dieser parametrisierte Unit-Test nimmt Input-Werte engegen und ruft damit die eigentliche Funktion auf. Man kann den parametrisierten Unit-Test eigentlich mit einem datengetriebenen Test vergleichen, mit dem Unterschied dass die Daten nicht aus einer Datenquelle kommen sondern von den jeweiligen Testmethoden übergeben werden.

Wir können den parametrisierten Unit-Test selbst anpassen und auch Asserst einfügen. Was wir nun hier tun wollen, ist die eigentliche Test-Methode zwei mal aufzurufen und zu prüfen, ob beide Ergebnisse übereinstimmen. Bei gleichen Eingangswerten sollte dies ja der Fall sein. Der parametrisierte Unit-test sieht dann ungefähr so aus.

   1: [TestClass]
   2: [PexClass(typeof(TotalSum))]
   3: [PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentException), AcceptExceptionSubtypes = true)]
   4: [PexAllowedExceptionFromTypeUnderTest(typeof(InvalidOperationException))]
   5: public partial class TotalSumTest
   6: {
   7:     [PexMethod]
   8:     public double CalculateTotals(
   9:         [PexAssumeUnderTest]TotalSum target,
  10:         List<TotalSum.cOrderPosition> OrderPositions,
  11:         double Rebate
  12:     )
  13:     {
  14:         double result = target.CalculateTotals(OrderPositions, Rebate);
  15:         double result2 = target.CalculateTotals(OrderPositions, Rebate);
  16:         Assert.AreEqual(result, result2);
  17:         return result;
  18:     }
  19: }

 

Diese Prüfung wird nun für alle Testmethoden ausgeführt. Und wie sieht das Ergebnis aus?

image

Wir erhalten nun einen Fehlerfall. Wenn man sich den Code der Test-Methode nochmals genauer anschaut, stellt man fest, dass die lokale Variable total beim erneuten Aufruf nicht zurückgesetzt wird - ein klassischer Fehler. Wenn wir die Variable in der Methode zurücksetzen, dann werden unsere Testfälle auch alle erfolgreich sein.

Somit haben wir mit Hilfe von PEX einen gängigen Fehler gefunden der in Real-World-Projekten sicher im Code selbst nicht so offensichtlich wäre.

Friday, February 20, 2009 1:20:23 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [1]    |  |   | 
 Thursday, February 19, 2009

Ich habe in einem früheren Post bereits einige Beispiele für den Einsatz von PEX beschrieben. ich möchte nun in loser Reihe weitere Erkenntnisse die ich beim Experimentieren mit PEX gewinne hier veröffentlichen. Heute möchte ich mich mit Overflow-Exceptions beschäftigen. Anlass war eine Diskussion mit Nico. Als erstes Beispiel wollen wir uns mal folgenden Code ansehen:

   1: public decimal Calc(decimal Value, bool Increase)
   2: {
   3:     if (Increase)
   4:         return Value+1;
   5:     else
   6:         return Value-1;
   7: }

Für eine komplette Codeabdeckung muss PEX eigentlich nur den Boolean-Parameter Increase berücksichtigen. Der Parameter Value kann eigentlich beliebig gewählt werden, auf die Code-Abdeckung hat der keinen Einfluss. Aber natürlich erkennt man dass es natürlich auch Fälle gibt in denen die Methode eine OverflowException wirft, nämlich bei value = decimal.MaxValue, Increase = true und value = decimal.MinValue, Increase = false.

Das erfreuliche ist, dass mit der aktuellen Version (0.9.40105.0) PEX zusätzlich zur Codeabdeckung auch Grenzwerte berücksichtigt:

image

Bei einem anderen Beispiel funktioniert das leider (noch) nicht.

   1: public decimal ToDecimal(double Value)
   2: {
   3:     return (decimal)Value;
   4: }

Hier wird leider keine Grenzwertbetrachtung gemacht, die ja zu einer Exception führen würde da der Wertebereich von decimal kleiner ist als der von double.

image

Thursday, February 19, 2009 8:54:48 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 

Hier hatte ich beschrieben, wie man die Test-Results aus Visual Studio nach Excel übertragen kann. Heute möchte ich ein Tool vorstellen, das es erlaubt, TRX-Files nach HTML zu konvertieren.

Zunächst speichert man das Test-Result in ein TRX-File. Dies geht über den Button "Export Test Run Results".

image

Anschließend kann man mit dem Tool trx2html das HTML-File erstellen. trx2html ist ein Open-Source Projekt von CodePlex. Es wird als Commandozeilen-Tool ausgeführt und als Parameter wird einfach das TRX-File angegeben. Als Ergebnis wird nun ein HTML-File erstellt das die Testergebnis entsprechend dokumentiert und auch einige Drill-Down-Funktionen bietet:

image

Durch einen Klick auf das rote Kreis-Icon neben einem der Test kann z.B. ein Stack-Trace eingeblendet werden.

image

trx2html - Home

Thursday, February 19, 2009 12:43:08 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Wednesday, February 18, 2009

Bei Unit-Tests bietet die Code-Coverage eine gute und einfache Möglichkeit zu prüfen, ob durch die definierten Test-Cases alle Code-Pfade in einer Methode wirklich durch Tests ausgeführt werden. Dies hilft beispielsweise dabei, noch fehlende Test-Cases zu identifizieren.

Auch mit manuellen Tests ist es möglich, eine Code-Coverage Analyse durchzuführen um auch hier fehlende Test-Cases zu ergänzen. Das folgende Beispiel zeigt eine mögliche Vorgehensweise.

Zunächst wird davon ausgegangen, dass ein maueller Test spezifiziert ist. Dieser kann z.B. so aussehen:

image

Nun wird ein Unit-Test erzeugt. Im Unit-Test wird eine Test-Methode angelegt die der Main-Methode der zu testenden Anwendung entspricht:

   1: [TestMethod()]
   2: [STAThread]
   3: public void FrmMainConstructorTest()
   4: {
   5:     Application.EnableVisualStyles();
   6:     Application.SetCompatibleTextRenderingDefault(false);
   7:     Application.Run(new FrmMain());
   8: }

 

Anschließend muss geprüft werden, ob die Code Coverage analyse für die gewünschten Assemblies aktiviert ist (Menü Test / Edit Test Run Configurations / Local Test Run)

image

Wird nun der Test gestartet, öffnet sich die Testanwendung. Hier werden nun die einzelnen Test-Schritte gemäß Testspezifikation ausgeführt. Anschließend wird die Test-Anwendung beendet. Dies schließt automatisch auch den Test ab. Nun cann die Code-Coverage ausgewertet werden:

image

Und natürlich lassen sich auch die durchlaufenen und nicht durchlaufenen Code-Zeilen farblich kennzeichnen.

image

Den ganzen Ablauf wird in folgendem Video auch nochmals detailliert gezeigt:

Wednesday, February 18, 2009 11:02:18 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [2]    |  |   | 
 Friday, February 13, 2009

clip_image001

Beim nächsten Treffen der .Net Developer-Group Ulm dürfen wir diesesmal Dariusz Parys begrüßen, der zum Thema “Architektur der Datenanbindungsschicht, insbesondere ADO.NET Data Services und Entity Framework” spricht. Der Abstract verspricht schon mal einen sehr spannenden Abend:

LINQ to SQL, ADO.NET, Entity Framework, Entity Data Model, REST mit ADO.NET Data Services oder Serialisierung mit WCF ? – neben einem Überblick über die Alternativen und detailliertere Darstellung des Entity Frameworks wird darauf eingegangen, welche Kriterien beim O/R-Mapping zur Bewertung zur Verfügung stehen und diskutiert, welcher Nutzen darin liegt, die Datenanbindung von einer technischen Ebene auf eine logische zu heben.

Ích glaube das dürfte ein Themengebiet sein mit dem im Moment jeder Entwickler in irgendeiner Weise käpft und so dürfte sich Dariusz schon mal auf eine ganze Reihe von Fragen einstellen (Mir selbst fallen da schon eine ganze Reihe ein).

Wer also Interesse an dem Thema hat, ist herzlich eingeladen am Dienstag 17.02.2008 um 18:00 zu uns zu kommen.

Weitere Infos unter:

http://www.dotnet-ulm.de

 

 

Friday, February 13, 2009 12:13:52 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |  |  |  |   | 
 Wednesday, February 11, 2009

In manchen Fällen ist es wünschenswert, eine Liste mit den Tests aus einem Projekt auszudrucken. Leider gibt es hierzu in Visual Studio keine direkte Funktion, aber ein kleiner Trick hilft hier:

1.) Im TestView die gewünschten Spalten einblenden

image

2.) Gewünschte Tests markieren und dann im Kontext-Menü "Copy" auswählen

image

3.) In Excel einfügen, fertig!

image

Das selbe funktioniert übrigens auch aus den Test Results, leider ohne Icons :-(

image

Wednesday, February 11, 2009 4:38:50 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    |   | 
 Monday, February 09, 2009

Als Blogger freut man sich natürlich immer über Kommentare. Das ist bei diesem Medium eine der wenigen Möglichkeiten Feedback zu bekommen. Und nun musste ich feststellen, dass auf meinem Blog leider seit einger Zeit die Kommentare nicht mehr richtig zugestellt werden. Dafür ein großes Entschuldigung an alle, die in letzte Zeit sich die Mühe gemacht haben und meine Beiträge kommentiert haben. Sorry, das ihr keine Antwort erhalten habt. Lasst euch nicht entmutigen, ich freue mich über jeden Kommentar und jetzt sollten die auch wieder bei mir ankommen.

Monday, February 09, 2009 7:16:13 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [1]    | 
 Friday, February 06, 2009

image

Die Team System User Grroup - VE ist eine virtuelle Usergroup die zwei mal im Monat ein Treffen hat in deren Rahmen Vorträge rund um das Thema Team System gehalten werden. Die Treffen finden virtuell in Second Life und über Live Meeting statt. Für Europäer ist das jeweils zweite Treffen zeitlich günstig am Samstag Nachmittag. 

Team System User Group - Virtual Edition

Friday, February 06, 2009 8:50:50 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 

image

Auf MSDN gibt es einen neuen Bereich zu Team System. Die Seite ist in einer ersten Iteration veröffentlicht und wird nun kontinuierlich mit weiterem Content ergänzt. Hier sind die Inhalte wesentlich übersichtlicher aufbereitet als auf den alten Seiten. Wer also mit Team System arbeitet oder das vorhat, einfach mal vorbeischauen. Feedback zu der Seite ist sehr willkommen und kann hier abgegeben werden.

Team System Home auf MSDN

Friday, February 06, 2009 8:47:08 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [1]    | 
 Wednesday, January 14, 2009

Endlich gibt es von PEX nun auch eine kommerziell nutzbare Lizenz. Bisher stand nur eine Academic License zur Verfügung, mit der nur “gespielt” werden durfte. Aber welche Aussagekraft hat denn eine Bewertung des Tools mit Demo-Projekten? Jetzt kann man PEX nun endlich auch auf Real-World-Projekte loslassen.

http://research.microsoft.com/en-us/projects/pex/downloads.aspx

Wednesday, January 14, 2009 12:05:22 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Monday, January 12, 2009

Bisher war für mich das Pflegen meiner verschiedenen Signaturen im Outlook immer ein Horror. Wenn ein neuer Rechner eingerichtet wurde, musstden die Signaturen wieder mühsam angelegt werden und wenn es Änderungen gab, dann grauste es mich schon davor, diese auf allen Instanzen anzupassen.

Dank Lars kenne ich nun aber einen einfacheren Weg. Die Signaturen werden nämlich einfach im Filesystem abgelegt und zwar unter %UserProfile%\AppData\Roaming\Microsoft\Signatures. Diese Files lassen sich einfach auf einen neuen Rechner kopieren (sogar bei laufendem Outlook sind die Signaturen dann sofort verfüpgbar!) oder sie können zwischen mehreren Rechnern einfach synchronisiert werden.

Super cool. Vielen Dank Lars, du hast mir das Leben wirklich erleichtert!

Monday, January 12, 2009 9:38:45 AM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [1]    | 
 Friday, January 09, 2009

Standardmäßig kann aus einer Hyper-V VM die WLAN-Verbindung des Host-Systems nicht mit genutzt werden. Das ist allerdings gerade bei Notebooks eine Einschränkung. Es gibt allerdings 3 verschiedene Wege, dieses Problem zu umgehen.

Ich selbst komme momentan mit dieser Lösung ganz gut zurecht. Einen ausführlichen Artikel mit den beiden anderen Lösungen gibt es hier.

http://sqlblog.com/blogs/john_paul_cook/archive/2008/03/23/using-wireless-with-hyper-v.aspx

Friday, January 09, 2009 10:12:23 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [2]    | 

Inzwischen gibt es eine verstärkte Diskussion, ob der Windows 2008 Server nicht die bessere Workstation ist. Sicher hängt das vom jeweiligen Einsatzgebiet ab. Bei mir war es so, dass ich für den Team Foundation Server einen Server als Betriebssystem auf meinem Demo-Rechner benötigt habe. Dabei wollte ich aber nicht auf den Komfort und das Design von Vista verzichten und auch Features wie z.B. den Sidebar nutzen. Die erste gute Nachricht ist, dass man Win2008 so anpassen kann, dass es sich optisch kaum von Vista unterscheiden lässt und die zweite gute Nachricht ist, dass es mit Hilfe eines kleinen Tools ganz einfach ist und schnell geht. Selbst Aero ist damit möglich.

Win2008Aero 

http://www.win2008workstation.com/wordpress/2008/07/17/windows-server-2008-workstation-converter/

Friday, January 09, 2009 9:52:32 PM (Mitteleuropäische Zeit, UTC+01:00)  #    Comments [0]    | 
 Friday, December 05, 2008

In den letzten Wochen war ich recht viel mit Vorträgen auf Tour. Inzwischen hat sich eine stattliche Anzahl von Vortragsthemen angesammelt. Unten sieht man eine Übersicht. Wer Interesse hat, dass ich einen Vortrag halte, darf sich gerne bei mir melden. Über das INEATA Speaker Bureau bin ich für INEATA UserGroups auch kostenlos zu buchen. Ansonsten würde ich mich auch über Feedback freuen. Sollte ich noch ein Thema mit aufnehmen, wer hat schon einen Vortrag von mir gehört und wie hat er gefallen etc.

Titel Dauer Abstract
Qualitätsmanagement mit VSTS und TFS 1 Std - 3 Std. Qualität spielt bei Software eine immer stärkere Rolle. Gleichzeitig werden immer effizientere  Entwicklungsprozesse angestrebt. Dies lässt sich nur mit geeigneter Tool-Unterstützung und passenden Lösungen zu Prozessen und Software-Architektur erzielen. Mit Visual Studio Team System und Team Foundation Server stehen Tools zur Verfügung, die nicht nur eine entsprechende Testunterstützung bietet, sondern auch komplette Qualitätsprozesse unterstützt. Der Vortrag zeigt, wie Qualitätsprozesse durch TFS unterstützt werden. Anschließend werden verschiedene Testmethoden vorgestellt und einige Praxis-Tipp für deren Einsatz gegeben.
Agile Development Process - Ein Architekturbasierter Entwicklungsprozess 1 Std Vortrag,
1 Std. Demo
Moderne Software-Anwendungen werden immer komplexer. Dadurch gewinnt auch die Software-Architektur immer mehr an Bedeutung. Wartbarkeit, Testbarkeit, Erweiterbarkeit und Teamentwicklung sind nur einige Aspekte, die eine gute Architektur unterstützen soll. Doch diese Aspekte können nicht durch ein einzelnes Architekturkonzept abgedeckt werden. Dieser Vortrag stellt verschiedene Architektur-Patterns wie Komponentenorientierung, Contract First Design, Service-Orientierung und UI Driven Development vor. Und vor allem wird gezeigt, wie diese Konzepte zu einem praxiserprobten Entwicklungsprozess verbunden werden können. 
Mehrschichtige Architekturen mit .Net 1 Std. Mehrschichtige Architekturen sind heute eigentlich oft Standard, vor allem bei verteilten Anwendungen. Allerdings wird diese Architektur oftmals zu sehr an technischen Belangen ausgerichtet. Die Session zeigt, wie man mehrschichtige Architekturen plant und diese flexibel und leitungsfähig aufbaut. Es werden verschiedene praxiserprobte Patterns vorgestellt.
Build-Management mit Team Foundation Server 1 Std. Mit Team Foundation Server steht ein leistungsfähiges integriertes Buildsystem zur Verfügung. Wie man dieses im Rahmen der Projekte nutzt und welche Vorteile sich daraus ergeen zeigt diese Session. Darüber hinaus wird der Einsatz verschiedener Buildsteps zum Deployment, Versionierung etc. vorgestellt.
Testing Practices mit VSTS und TFS