Der Team Foundation Server bietet ein extrem flexibles und leistungsfähiges Konzept zur Definition von Work Items. Damit lassen sich viele Szenarien über eine reine Konfiguration abbilden. Um die Mächtigkeit zu demonstrieren, hier ein paar Beispiele. Diese Beispiele nutzen den Process Template Editor der Bestandteil der kostenlosen Team Foundation Server 2010 Power Tools ist. 1.) Nur bestimmte Benutzer sollen ein Workitem eines bestimmten Typs anlegen dürfen Ein verbreitetes Szenario ist, dass nur ein bestimmter Personenkreis Workitems eines bestimmten Typs (in diesem Beispiel der Typ Bug) anlegen dürfen, andere Benutzer sollen diese aber weiter bearbeiten können. Auch wenn die Umsetzung nicht ganz ideal ist lässt sich diese Funktion mit dem TFS relativ einfach erreichen. Wie im Screenshot zu sehen, ist der Status Active für diesen Benutzer ungültig. Damit kann er das Workitem nicht speichern. Wie gesagt, nicht gerade schön aber wirkungsvoll. Wie erreichen wir nun diese Funktion? Im Process Template Editor sehen wir im Workflow des Bug-WIT eine Transition von nirgendwo nach Active Diese Transition wird verwendet wenn ein neues Workitem angelegt wird. Auf dieser Transition können wir nun eine Berechtigung einstellen. Dazu geben wir in das Feld “For” eine TFS Gruppe ein die diese Funktion ausführen darf. Alternativ kann bei “Not” eine Gruppe angeben die diese Transition nicht nutzen darf. Dieses Feature kann natürlich auch für Transitions zwischen zwei Status genutzt werden, also z.B. um zu steuern wer den Bug schließen darf. 2.) Ein Feld muss gefüllt sein wenn ein anderes einen bestimmten Wert hat In der Praxis kommt es häufiger vor, dass iin Abhängigkeit eines Wertes ein anderes Feld ausgefüllt sein muss. In unserem Beispiel nehmen wir mal an, dass auf dem Bug die Repro-Stepsausgefüllt sein müssen wenn der Bug die Priorität 1 hat. Dazu stellen wir auf dem Feld Repro Steps eine WHEN-Regel ein Und sagen wenn diese Bedingung erfüllt ist, dann soll das Feld ein Pflichtfeld sein 3.) Befüllen einer Auswahlliste in Abhängigkeit eines anderen Feldes Das dritte Beispiel soll uns die Auswahlliste eines Feldes in Abhängigkeit eines anderen Feldes befüllen. In unserem Beispiel soll das Feld Team in Abhängigkeit der Area befüllt werden. Dazu definieren wir für das Feld Team das wir zuvor hinzugefügt haben 2 When-Regeln An dieser Stelle verwenden wir für die Regel nicht das Feld AreaPath da hierarchische Felder in Regeln nicht richtig unterstützt werden. Diese produzieren dann beim Import des WIT den Fehler "TF26204: The account you entered is not recognized". Der Umweg über die AreaID umgeht diese Problem. Dann stellen wir einfach die AllowedValues für die beiden Fälle ein. Man sieht also, dass der TFS einiges an Flexibiölität zu beieten hat. Es lohnt sich damit mal etwas zu experimentieren. Generell möchte ich aber vor Überregulierung warnen weil dies in der Praxis meist dazu führt, dass die Anwender behindert werden und somit die Akzeptanz des Tools sinkt.
Tritt beim Konfigurieren eines Labs das in einer Workgroup betrieben wird (keine Domänenintegration der VMs) folgender Fehler auf, dann fehlt ggf. ein Shadow-Account:
-------------------------------------------------- Environment message: Type=Warning; Message=TF267042: One or more machines are not ready to run tests. For more information, see the individual machine errors.; Machine messages: Machine name: Windows 7 x64 en Machine message: Type=Error; Message=TF267055: The machine is not ready to run tests because of the following error: Unable to connect to the controller on ---. The agent can connect to the controller but the controller cannot connect to the agent because of following reason: The server has rejected the client credentials. The logon attempt failed.; -------------------------------------------------- Damit der Testagent mit dem Testcontroller korrekt zusammenarbeitet, müssen beide mit unterschiedlichen Accounts laufen. Der Testcontroller verwendet dabei typischerweise einen Domänen-Account, der Testagent arbeitet mit einem lokalen Account. Die jeweiligen Accounts müssen als Shadow-Accounts (gleicher Name und Kennwort) lokal bzw. in der Domäne angelegt werden, also für den lokalen Account ein Shadow-Account in der Domäne und für den Domänen-Account ein lokaler Shadow-Account. Beispiel: | | Account | Shadow-Account | | Testagent | labmachine\Labuser | domain\Labuser | | TestController | domain\TestController | labmachine\TestController | Die oben beschriebene Meldung erhält man, wenn auf der Labmaschine kein lokaler Shadow-Account angelegt wurde. Wenn man das nachholt und dann auf “Repaiur testing capabilities” klickt, dann sollte das Problem behoben sein. 
Im Team Foundation Server lassen sich die Work Items sehr einfach anpassen, neue Work Item Types lassen sich erzeugen und damit ein individuelles Process Template erzeugen. Das ganze geht sehr einfach und intuitive wenn mann den Process Template Editor aus den Team Foundation Server Power Tools verwendet (http://visualstudiogallery.msdn.microsoft.com/en-us/3e8c9b68-6e39-4577-b9b7-78489b5cb1da) Wer mal auf den Geschmack gekommen ist, das Process Template im TFS anzupassen, wird durch ausprobieren und rumspielen schnell vor der Frage stehen, wie kann ich nun in einem bestehenden Projekt einen Work Item Type wieder löschen den ich nicht mehr brauche? Hier hilft das Kommandozeilentool witadmin weiter das sich dirckt über die Visual Studio Eingabeaufforderung ausführen lässt. witadmin destroywitd /collection:http://<Servername>:8080/tfs/<Team Project Collection> /p:<Team Projekt Name> /n:<Name des Work Item Types> löscht den angegebenen Work Item Type. Vorsicht, mit diesem Kommando werden aber auch alle Work Items gelöscht, die diesen Typ verwenden, diese können ja vom System nach löschen der WITD nicht mehr verwaltet werden. Wenn man also den WIT bestehender Work Items verändern möchte, dann sollte man diesen umbenennen und anschließend so anpassen dass er den neuen Anforderungen entspricht. Zum Umbenennen eines WIT hilft ebenfalls witadmin witadmin renamewitd /collection:http://<Servername>:8080/tfs/<Team Project Collection> /p:<Team Projekt Name> /n:<Alter Name des Work Item Types> /new:<Neuer Name des Work Item Types>
Bei der weltweiten Usergroup Team System User Group Virtual Edition hat sich in den letzten Tagen einiges geändert, z.B. der Name. Wie das Produkt das im Zentrum unserer Aktivitäten steht, wurde die Gruppe in Visual Stuido ALM User Group umbenannt. Gleichzeitig haben wir eine neue Website online geschaltet. Sie finden uns jetzt unter http://www.vsalmug.com/default.aspx In diesem Zuge werden wir zukünftig die Benachrichtigungen für unsere Meetings nicht mehr per E-Mail zustellen, sondern sie können sich Neuigkeiten unseren Blog mit den Ankündigungen per RSS abrufen (http://www.vsalmug.com/CMSPages/BlogRss.aspx?aliaspath=/Meetings/Announcements). Zusätzlich ahben wir auf LinkedIn eine Gruppe eingerichtet über die sich die Mitglieder besser untereinander vernetzen können: http://www.linkedin.com/groups?home=&gid=2860483&trk=anet_ug_hm Abschließend möchte ich auf unseren nächsten Vortrag noch hinweisen. Am Donnerstag, 06.05.2010 ab 19:00 wird Martin Woodward vorstellen wie die Integration mit nicht Microsoft-Plattformen über den Team Explorer Everywhere (vormals Teamprise) gelingt.  Team Explorer Everywhere 2010 Meeting Date: Thursday, May 6th, 2010 Time: 10:00AM PT (UTC-0700) [Add to Calendar] [Join Meeting] Did you know that Team Foundation Server can be used for software development by your entire organization - not just the team using Microsoft platforms and technologies? In this session Martin Woodward will show you how you can get your Java, Mac, Linux, and Eclipse developers on board using Team Explorer Everywhere 2010. This session shows you how you can standardize on Team Foundation Server for the Application Lifecycle Management of your entire enterprise. See how to manage work items, version control, and build automation across technology and platform boundaries in your company and understand the features and functionality available to the people in your organization. Speaker: Martin Woodward Martin Woodward is the Program Manager for the Microsoft Visual Studio Team Foundation Server Cross-Platform Tools Team and co-author of the book "Professional Application Lifecycle Management with Visual Studio 2010". Before joining Microsoft, Martin was voted Team System MVP of the Year and has spoken about Team Foundation Server at events internationally. Not only does Martin bring a unique insight into the inner workings of the product he has experience from over a half-decade of real world use at companies big and small that he is always happy to share. When not working or speaking, Martin can be found at his blog http://www.woodwardweb.com.
So langsam reift bei den letzten Source Safe Moikanern die Erkenntniss, dass es nun langsam Zeit wird sich nach einer anderen Quellcodeverwaltung umzusehen und eigentlich liegt da inzwischen nichts näher als der Team Foundation Server 2010 der nicht nur eine erstklassige Versionsverwaltung mit bringt sondern der acuh eine Vielzahl weiterer ALM-Funktionen beinhaltet und vor allem inzwischen in der MSDN Subscription kostenloas enthalten ist. Wer wissen will, wie er schnell und einfach von Source Safe auf TFS migriert, findet alle notwendigen Infos hier : http://msdn.microsoft.com/en-us/library/ms253060.aspx
In der TFS Adminconsole oder im TFS Configuration Wizard können die Reporting Services für den TFS konfiguriert werden.  Man gibt hier den Server und ggf. die Instanz der Reporting Services an und klickt auf “Populate URLs”, dann werden die entsprechenden URLs automatisch ausgefüllt – normalerweise zumindest. Ich hatte die Situation, dass der User mit dem ich den TFS installiert habe auf dem Server auf dem die Reporting Services liefen kein Administrator war. Normalerweise ist das der einfachste Weg, den TFS Account auf dem Reporting Server als lokalen Administrator einzutragen, das ist aber nicht in allen Fällen erwünscht. Dann bekommt man die Fehlermeldung TF255050: A connection cannot be made to the Report Server WMI provider. Verify the following: 1. You have entered the correct name for the server, including the instance name. 2. The Windows Management Instrumentation service is running on vs2010rcdemo. 3. The service is not blocked by Windows Firewall. 4. You have the required permissions to connect. Details: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) Eine damit verwandte Fehlermeldung ist TF255186: The following SQL Server Reporting Services Instance could not be found: MSSQLSERVER. The server name is: vs2010rcdemo. In beiden Fälle fehlen dem User WMI-Berechtigungen auf dem Reporting Server. Im ersten Fall der Remote-Zugriff auf die WMI generell, im zweiten Fall auf den Remote-Zugriff für die Reporting Services in der WMI. Um die gewünschte Operation ausführen zu können muss dem User zunächst Remote-Zugriff auf WMI gegeben werden: - Auf dem Reporting Server dcomcnfg.exe starten
- Im linken Bereich Console Root\Component Services\Computers\My Computer öffnen
- Aus dem Kontextmenü von “My Computer” den Eintrag “Properties” öffnen
- Im Bereich “Launch and Activation Permissions” auf “Edit Limits” klicken
- Den Benutzer mit “Add hinzufügen und ihm “Remote Launch” und “Remote Activation” vergeben
Anschließend kann der Remote-Zugriff per WMI auf die Reporting Services konfiguriert werden. - Auf dem Reporting Server wmimgmt.msc starten
- Im linken Bereich auf WMI Control (Local) aus dem Kontext-Menü “Properties” auswählen
- Auf den Reiter Security wechseln und im Baum Root\Microsoft\SqlServer\ReportServer auswählen
- Auf den Button “Security” klicken und den gewünschten benutzer mit “Add” einfügen
- Dem Benutzer “Enable Account” und “Remote Enable” als Rechte vergeben
- Auf “Advanced” clicken, den Benutzer auswählen und dann auf “Edit” klicken
- Bei “Apply to” “This namespace and subnamespaces” wählen
Mit diesen Einstellungen sollte nun das “Populate URLs” in der TFS Administration Console funktionieren.
Wer sich eine Trial-Version von Visual Studio 2010 oder Team Foundation Server 2010 installiert benötigt einen Key um diese freizuschalten. Wer nun über eine MSDN-Subscription verfügt, kann sich die Vollversion dort herunterladen, jedoch man bekommt keinen Key. Nun kann man entweder neu installieren oder man greift zu einem kleinen Trick: - ISO-File vom MSDN herunterladen
- Im ISO-Image nach der Datei setup.sdb suchen
- Die Datei mit einem Texteditor öffnen
- Der Key steht unter dem Eintrag [Product Key] und kann von hier einfach in das Registrierungsformular übertragen werden. Dazu im TFS einfach die Admin-Console öffnen und im Visual Studio unter Help / Register Product aufrufen
Update: Inzwischen hatte MS ein Einsehen und die Keys bei den MSDN Subscriber Downloads veröffentlicht 
Beim Deployment einer Environment auf meinen Host bekam ich den Fehler TF259115:  Speicher war eigentlich genug frei auf meinem Host und so war ich zunächst erstaunt, warum er das nicht deployen wollte. Des Rätsels Lösung liegt darin, dass die Placement Policy standardmäßig auf “Conservative” eingestellt ist. Das bedeutet, dass der Host beim Deployment den Speicherbedarf aller VMs auf dem Host ermittelt, unabhängig davon ob diese gestartet sind oder nicht. Im Betrieb könnten ja dann alle gleichzeitig gestartet werden was dann zu Problemen führt. D.h. im Idealfall hat man immer soviel Ressourcen, dass alle Environments die deployed sind gleichzeitig laufen können, momentan nicht benötigte Environments werden in der Library abgelegt. Da ich aber auf meinem Demo-Notebook nicht soviel Speicher habe und dabei nie alle Environments gleichzeitig laufen sollen, wollte ich diese Limitierung umgehen. Dies kann man erreichen, indem man die Placement Policy auf Aggresive stellt. Dies erreicht man am besten durch einen TFSConfig-Aufruf: TfsConfig Lab /hostgroup /CollectionName:labcollection /Edit /Name:"All Hosts" /LabEnvironmentPlacementPolicy:Aggressive Logging sent to file C:\ProgramData\Microsoft\Team Foundation\Server Configuration\Logs\CFG_SET_URL_0413_225508.log Command: lab TfsConfig - Team Foundation Server Configuration Tool Copyright (c) Microsoft Corporation. All rights reserved. Are you sure you want to update the settings for this host group ? (Yes/No) y The requested changes were successfully applied. Die TFSConfig findet befindet sich im Pfad C:\Program Files\Microsoft Team Foundation Server 2010\Tools Weitere Infos unter http://msdn.microsoft.com/en-us/library/dd547199(VS.100).aspx
Heute wurden Visual Studio 2010 und Team Foundation Server 2010 gelauncht. Microsoft neueste ALM Plattform bietet eine große Anzahl neuer Features, so dass sich ein näherer Blick auf jeden Fall lohnt, unter anderem: - Testmanagement und Testausführung
- automatisierte GUI-Tests
- Virtualisierte Testumgebungen
- Erweiterte Tracking-Funktionen für Versionsverwaltung
- Agile Planungsmethoden
- Build Workflows auf Basis von WF 4.0
- Architektur-Features und UML-Diagramme
- Integrierte SharePoint-Entwicklung
- uvm
Ich werde in den folgenden Wochen in einzelnen Blogbeiträgen verschiedene Funktionen vorstellen, also vorbeischauen lohnt sich … Weitere Informationen und den Download Link für Inhaber einer MSDN Subscription finden sich hier: http://msdn.microsoft.com/de-de/vstudio/2010.aspx Testversionen können hier heruntergeladen werden: http://www.microsoft.com/germany/visualstudio/try/download.aspx
Team Foundation Server 2010 bietet nun eine verbesserte Integration mit SharePoint. Für die einzelnen Team-Projekte wird die Verbindung zu einer SharePoint Site typischerweise beim Anlegen des Projektes einrichten, alternativ kann man das auch im Nachhinein konfigurieren. Dazu einfach im TeamExplorer auf dem Team Projekt rechte Maustaste und dann unter “Team Project Setting” “Portal Settings” auswählen. Hier wählt man dann unter “Configure URL” eine der konfigurierten Web Applications aus. Bekommt mann beim Bestätigen des Fensters folgen Meldung, dann hat der aktuelle Benutzer nicht ausreichen Berechtigungen auf die Site / SiteCollection: Server was unable to process request. ---> Failed to activate feature 'TeamFoundationWeb' (ID: 310284e3-35d9-4b5d-99b5-c42147379877) at scope 'http://sarmoss02/sites/TFS2008/BI_KaBIS'. Diese Berechtigungen müssen im SharePoint eingetragen werden.
Will man in einer Winforms-Anwendung einen String URL-encodieren, dann kann mann dafür einen einfachen Aufruf verwenden: HttpUtility.UrlEncode("http://www.artiso.com/page?ID=99"); Das einzige wass man dafür tun muss, ist die System.Web.dll zu referenzieren. Eine kleine Hürde gibt es bei Visual Studio 2010, da hier standardmäßig “.Net Framework 4 Client Profile” als Target-Framework ausgewählt ist und das Client Profile die System.Web nicht enthält. Deshalb muss man in den Eigenschaften des Projektes das Target-Framework umstellen, z.B. auf .NET Framework 4. 
Wollte heute ganz einfach eine Benachrichtigung für eine Liste im SharePoint einrichten. Das Ganze stellte sich als problematischer heraus als gedacht. Eigentlich ist das eine einfache Sache. Im Actions-Menü die Option “Aletr Me” aufrufen… … , Einstellungen vornehmen und schon kommt eine Fehlermeldung: The following users do not have e-mail addresses specified: <UserName>. Alerts have been created successfully but these users will not receive e-mail notifications until valid e-mail addresses have been provided Der Link darunter mit “Set my e-Mail address” war auch nicht sehr hilfreich. Nach einigen Recherchen bin ich dann auf ein paar weitere Details gestoßen. Zunächst habe ich herausgefunden, dass SharePoint die Benutzerprofile mit dem ActiveDirectory abgleicht, aber nur, wenn das konfiguriert ist. Das kann man unter Central Administration \ Shared Services Administration einstellen. Dort kann man im Dropdown-Menü des SharedService die Option “Open Shared Services Admin Site” aufrufen. Unter “User Profiles and My Sites” kann nun die Option “User profiles and properties” gewählt werden. Hier sollte zunächst geprüft werden, ob der Dienst der die User Profile mit dem ActiveDirectory abgleicht auch zur Ausführung eingeplant ist. Mit den unteren Links kann ein manueller Abgleich gestartet werden. Über “View user profiles” kann man sich die importierten Profile anzeigen lassen, mit “View import log” kann man sich ein Protokoll zum Abgleich anzeigen lassen. Sollen die Benutzer aus einer anderen Domäne importiert werden als die in der der SharePoint Server läuft, kann man über “View Import Connections” eine weitere Domäne hinzufügen. Bei mir bestand dann noch das Problem, dass das Profil für meinen User nicht sauber durch den Import aktualisiert wurde. Nachdem ich den User aus der entsprechenden Site entfernt und neu hinzugefügt hatte, hat es problemlos funktioniert und ich kann jetzt meine Alerts problemlos einrichten und bin immer auf dem Laufenden was den Inhalt meiner SharePoint-Listen anbelangt.
Mit TFS 2010 kommen nun endlich hierarchische Workitem Queries und erfreulicherweise lassen diese sich auch im SharePoint Portal schön darstellen. Was mich an der Geschichte nur etwas gestört hat, dass ist, dass die Hierarchie nach dem Laden immer vollständig aufgeklappt ist. Es gibt zwar einen Button “Collapse All” aber den dann immer extra zu drücken um erst mal einen Überblick zu bekommen, ist doch etwas lästig. Zunächst habe ich deshalb versucht die Query entsprechend anzupassen, jedoch gibt es an dieser Stelle leider noch keinen Parameter um das einzustellen. Für das SharePoint-Portal habe ich allerdings eine Lösung gefunden und die geht so: 1.) Ein neues Content Web Part auf der Seite einfügen: 2.) Auf dem Content Editor Web Part den Source Editor starten 3.) Hier folgendes Script eintragen: 1: <script language="javascript"> 2: function collapseQuery() 3: { 4: _ctl00_m_g_1409303e_8eb2_4dc3_80b0_822628dfcc28_ctl00.tryToggle(false, true); 5: } 6: 7: WPSC.RegisterForEvent("urn:schemas-microsoft-com:dhtml","onload",collapseQuery); 8: </script>
Die ID des Webparts (_ctl00_m_g_1409303e_8eb2_4dc3_80b0_822628dfcc28_ctl00) lässt sich relativ einfach im HTML-Source der Seite ermitteln (z.B. IE 8 F12 drücken um in die Developer Tools zu gelangen). Hier kann man dann über Find / Select Element by Click durch Anklicken des WebParts die Stelle im Code einfach finden und die ID zu ermitteln. Zu beachten ist dabei, dass das die ID des Controls etwas anders lautet als das WebPart selbts, so muss am Anfang ein _ stehen und das Control auf _ctl00 enden.

Mit dem TFS 2010 ist es nun möglich, denn Application-Tier über einen NLB-Cluster zu betreiben. Damit kann man Ausfallsicherheit und Load-Balancing für den App-Tier erreichen. Mit einem SQL-Cluster als Data-Tier skaliert der TFS nun sehr schön, sowohl in Punkte Performance als auch in Bezug auf die Ausfallsicherheit. Nun liegt es natürlich nahe, die Reporting Services ebenfalls über den NLB zu betreiben, was an sich auch kein Problem ist. Man muss nur ein paar Einstellungen vornehmen. So hats bei mir funktioniert: 1.) Das Scale-out Deployment für die Reporting-Services auf beiden Servern aktivieren (setzt SSRS Enterprise voraus) 2.) Die Web Service URL auf die IP-Adresse des NLB einstellen 3.) In der TFS Admin Console die Reporting Services über den NLB registrieren. Das hat bei mir nur über die IP-Adresse funktioniert, nicht über den Namen. Da muss ich bei Gelegenheit mal danach schauen. 4.) In der Datei C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportServer\rsreportserver.config unter <Service> folgendes Tag einfügen: <Hostname>sartfsnlb01</Hostname> 5.) In der Web.config unter C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportServer\ und unter C:\Program Files\Microsoft SQL Server\MSRS10.MSSQLSERVER\Reporting Services\ReportManager\ im Abschnitt <system.web> folgenden Tag einfügen: <machineKey validationKey="627BF72BB33AA8D28CA2C3E80920BA4DF0B726F97EEFBB0F4818350D63E6AFA380811F13ED1F086E386284654DB3DAF676707464EEB73EBF79858F477D8E4F5C" decryptionKey="F40B6E5A02B29A181D2D213B5ED8F50B73CFCFD0CC56E137" validation="SHA1" /> Achtung die Parameterwerte dürfen nuicht umgebrochen werden. Einen eigenen Key kann man sich einfach unter http://aspnetresources.com/tools/keycreator.aspx generieren lassen. 6.) Reporting Srevices neu starten. 7.) Nun werden bei einem Ausfall eines App-Tiers alle Reporting-Anfragen über den anderen App-Tier abgewickelt, der Anwender merkt davon nichts außer dass es beim ersten Zugriff nach dem Ausfall ein wenig länger dauert.
Dieses Jahr ist nach längerer Zeit die TechEd, die wichtigste Microsoft-Konferenz in Europa, wieder in Deutschland, genauer gesagt vom 09.Nov – 13. Nov in Berlin. Ich werde dort als ATE (Ask the Experts) zum Thema Visual Studio ALM vertreten sien und darüber hinaus mit Christian Binder und Neno Loje ein Q&A Session zu den Themen TFS, ALM und Visual Studio 2010 zu machen. Die Session wird in Deutsch sein, also wenn ihr Fragen rund um den Themenbereich habt, besucht unsere Q&A-Session. Soviel geballtes Wissen auf einmal gibts nicht so bald wieder  Visual Studio Team Foundation Server Q&A Mittwoch, 11. November 14:00 – 15:00 Uhr Community Stage im Zentrum der Ausstellung Halle 4.2 
Hype-V ist ein klasse Virtualisierungssystem das vor allem in der neuesten Version eine Reihe nützlicher Funktionen mitbringt. Besonders hilfreich sind Snapshots mit denen es gefahrlos möglich ist, auch auf dem Server mal was zu testen. Man kann sich aber mit Shanpshots leicht selber überlicsten oder gar in’s Knie schießen. Deshalb möchte ich hier ein paar Erfahrungen zum Besten geben: Funktionsweise von Snapshots Die Virtuellen Maschinen von Hyper-V schreiben ihre Daten in virtuelle Harddisks (VHD), also eine Datei auf der Platte des Hosts. Wird nun ein Snapshot gemacht, passiert vereinfach gesagt, Folgendes. Die VHD-Datei wird schreibgeschützt, so dass daran keine Änderungen mehr vorgenommen werden können. Statt dessen wird nun eine AVHD-Datei angelegt und alle Änderungen auf der Platte der VM werden nun dort hineingeschrieben. Wird erneut ein Snapshot erstellt, wird die AVHD gesperrt und eine weitere angelegt. Dies hat nun zweierlei Folgen: - Je mehr Snapshots erstellt werden, desto langsamer wird der Zugriff auf die virtuelle Disk, da Hyper-V ja aus der VHD und den verschiedenen AVHDs nun die Daten zusammensammeln muss.
- Nur die VHD und alle AVHDs zusammen ergeben den aktuellen Stand der virtuellen Disk, mit der VHD alleine hat man nur den Stand vom ersten Snapshot.
Gerade der letzte Punkt ist beim Verschienen der VM oder beim Backup zu berücksichtigen, da man hier schnell Daten verlieren kann, wenn man vergisst die AVHDs zu berücksichtigen. Aus beiden oben genannten Gründen macht es Sinn, Snapshots zu löschen, sobald diese nicht mehr gebraucht werden. Snapshots sind keine Technik zur Erstellung von Backups! Zum löschen eines Snapshots wird dieser einfach selektiert und dann mit “Delete” gelöscht. Aber ACHTUNG! Die Daten liegen nun immer noch in der AVHD. Erst wenn man die VM in den Save-State fährt, beginnt Hyper-V mit einem Merge, d.h. die Änderungen der AVHDs werden jetzt in die jeweils vorausgegangene AVHD bzw. VHD gemerged, sind alle Snapshots gelöscht, bleibt nur noch die VHD übrig. Erst nach Abschluss des Merge-Vorgangs erhält man durch eine Kopie der VHD eine komplette Sicherung der virtuellen Disk der VM.
Die .net Developer Group Ulm bietet am 27.10.2009 eine kostenlose Ganztagesveranstaltung rund um Visual Studio 2010 ALM (vormals VSTS 2010). Die Nachfrage für diese Veranstaltung ist so hoch, dass wir uns entschieden haben, die Veranstaltung am 26. November nochmals mit gleichen Sprechern und gleichem Inhalt zu wiederholen. Wer also noch Interesse hat, sollte sich bald möglichst unter http://www.dotnet-ulm.de/vsts2010/ registrieren, wir haben noch ein paar Plätze frei.
 Die Beta 2 von Visual Studio 2010 ist nun für MSDN Subscribers verfügbar, für alle anderen wird es noch bis Mittwoch dauern. Es gibt eine reihe von wichtigen Änderungen die Microsoft mit Visual Studio 2010 ankündigt: - Es gibt eine abgespeckte Version von TFS (TFS Basic) die auch auf Client-Betriebssystemen installiert werden kann.
- TFS ist jetzt in alle versionen von Visual Studio 2010 enthalten (meines Wissen nach nur bei denen mit MSDN)
- Es gibt ein vereinfachtes Modell der Produkt SKUs (Editionen)
- Neues Logo (siehe oben)
Was ich persönlich schade finde: Die Bezeichnung “Team System” verschwindet, es gibt nun nur noch - Microsoft® Visual Studio® 2010 Express
- Microsoft® Visual Studio® 2010 Professional
- Microsoft® Visual Studio® 2010 Professional with MSDN
- Microsoft® Visual Studio® 2010 Premium with MSDN
- Microsoft® Visual Studio® 2010 Ultimate with MSDN
- Microsoft® Visual Studio® Test Elements 2010 with MSDN
- Microsoft® Visual Studio® Team Foundation Server 2010
- Microsoft® Visual Studio® Team Lab Management 2010
- Microsoft® Visual Studio® Load Test Virtual User Pack 2010
Positiv ist aber, dass die Beta 2 eine Go-Live-Lizenz enthält. Der Launch-Termin wirde von Microsoft für den 22. März 2010 angekündigt. http://blogs.msdn.com/somasegar/archive/2009/10/19/announcing-visual-studio-2010-and-net-fx-4-beta-2.aspx
In Expression Blend gibt es ein cooles Feature, mit dem Beispieldaten für Databinding erzeugt werden können. Damit können beispielsweise Listboxen etc. mit Daten befüllt werden um z.B. DataTemplates im Designer testen zu können. Und auch bei der Ausführung der Anwendung stehen die Daten zur Verfügung. Damit können schnell und einfach Oberflächenprototypen erstellt werden. Eine detaillierte Beschreibung der Funktion findet sich hier.
Auf der diesjährigen ADC hatte ich zwei Vorträge: Zu beiden Vorträgen gibt es die Unterlagen über den jeweiligen obenstehenden Link.
Hat man eine Query die zwei Spalten mit dem gleichen Namen enthält, dann mekert der Reporting Services Designer “The query contains more than one unnamed or duplicated field name. Please specify unique column aliases.” In der MDX-Abfrage Aliase zu vergeben ist mir nicht gelungen. Glücklicherweise gibt es aber einen einfacheren Weg das Problem zu lösen. Man geht einfach in die Eigenschaften des Datasets und dort auf “Fields”. Hier kann man nun einfach einen eindeutigen Alias angeben. 
Oft möchte man Werte, z.B. Prozentwerte als kleine Balken in einem Report darstellen: Wie man das mit Hilfe der Reporting Services bewerkstelligt, ist im Folgenden kurz beschrieben. - Zunächst erstellt man sich eine Grafik mit dem gewünschten Verlauf
- Dann fügt man eine neue Spalte mit dieser Grafik in den Report ein. Der Grafik gibt man ein günstige Breite, z.B. 100px.
- Für die Grafik stellt man nun ein Padding für den rechten Rand ein und zwar über eine Expression:
- In der Expression gibt man nun eine Formel ein, die den rechten Rand so berechnet, dass er bei 0 die Breite des Bildes erreicht und beim Maximalwert 0.
- In obigem Beispiel hat das Bild eine Breite von 100pt und soll einen Maximalwert von 1.5 anzeigen, so dass bei 1.5 der Wert für das Padding 0 ist und bei 0 ist er 100 (1,5 * 75). Damit zeigt der Balken die Werte grafisch an. Auf Wunsch kann man natürlich den Wertebereich auch min Min() und Max() ermitteln.
http://blogs.msdn.com/bobmeyers/archive/2005/10/15/481342.aspx
Meinem SQL-Server kam bei einer meiner Datenbank-Tabellen was supekt vor jedenfalls zeigte er in Klammern hinter der Tabelle ein (Suspect) an und ich konnte auf die Tabelle nicht mehr zugreifen. Ärgerlich war, dass es sich dabei um die Config-Datenbenk meines SharePoint-Servers handelte und damit mein kompletter SharePoint-Srever lahm gelegt war. Glücklicherweise fand ich ein kleines Script, das das Problem in Sekunden behoben hat. EXEC sp_resetstatus 'DBname'
ALTER DATABASE DBname SET EMERGENCY
DBCC checkdb('DBname')
ALTER DATABASE DBname SET SINGLE_USER WITH ROLLBACK IMMEDIATE
DBCC CheckDB ('DBname', REPAIR_ALLOW_DATA_LOSS)
ALTER DATABASE DBname SET MULTI_USER
Dort habe ich einfach meinen Datenbanknamen entsprechend eingesetzt und schon lief der SharePoint wieder. Vielen Dank an der Stelle an Mohamad. http://mshehadeh.blogspot.com/2007/09/restoring-sql-server-2005-suspect.html
Mit Team Foundation Server 2010 wird der TFS nun auch für kleinere Teams noch interessanter als bisher. Es gibt eine Reihe von Vorteilen gegenüber der aktuellen Version: - Preis
Es gibt im Moment noch keine abschließenden Informationen über das Pricing, aber voraussichtlich wird der Preis zukünftig wohl kaum noch ein Argument sien, den TFS nicht zu nutzen. - Systemanforderungen
Die Anforderungen an das System sind deutlich geringer als bei TFS 2008. So kann der TFS nun auf einem Domänen-Controller und sogar auf Client-Betriebssystemen installiert werden. Zudem können nun einige Komponenten wie SharePoint und Reporting optional installiert werden. - Installation
Der Installationsvorgang wurde deutlich vereinfacht. Damit kommt Microsoft dem Slogen “ALM for the masses” einen großen Schritt näher. Weitere Details gibt es auf dem Blog von Brian Harry: http://blogs.msdn.com/bharry/archive/2009/10/01/tfs-2010-for-sourcesafe-users.aspx
Mit dem Work Item Type Designer (WIT Designer) können Work Item Type Definitionen einfach und bequem angepasst werden. Der WIT Designer ist Bestandteil der TFS Power Tools. Mit dem WIT Designer kann man auch die Workflows auf den Work Item Types grafisch bearbeiten. Dazu kann man aus der Toolbox einfach neue States und Transistions auf das Workflow-Diagramm ziehen … zumindest wenn die Toolbox Elemente enthält. Sollte die Toolbox einmal leer sein, dann gibt es eine nicht ganz elegante aber wirksame Methode, man löscht einfach alle toolbox*.tdb Dateien und zwar au dem Ordner C:\Users\<USERNAME>\AppData\Local\Microsoft\VisualStudio\8.0. Danach erscheinen die Elemente ganz normal.
Wir haben einen neuen Nachbarn bekommen In Augsburg gibt es nun auch eine .net Usergroup. Diese wird von Tobias Schmid geleitet. Damit ist nun also die Lücke zwischen München und Ulm geschlossen und ich freue mich auf eine gute Zusammenarbeit. Apropos Zusammenarbeit, ganz besonders freut es mich, dass ich am 14.10.2009 beim Gründungstreffen einen Vortrag zum Thema “Durchgängige Entwicklungsprozesse mit Visual Studio Team System” halten darf. Dann auf gute Nachbarschaft 
http://www.ug-augsburg.net/
 Mit Martin Woodward haben wir einen der weltweit bekanntesten Team System MVPs zu Gast der in seinem Vortrag über die neuen Möglichkeiten des Build Systems im TFS 2010 informieren wird. Dass sich beim Build in TFS2010 einiges getan hat, wird bereits aus der Auflistung der Hauptpunkte von Martins Vortrag ersichtlich. Es wird um Private Builds, Gated Checkins und um die neuen workflow-basierten Builddefinitionen gehen. Über TSUG-VE Die Team System User Group – Virtual Edition ist eine weltweite Usergroup zum Thema Team System. Die Treffen finden virtuell in Live Meeting statt. Weitere Informationen gibt’s unter http://www.tsug-ve.com.
Am 27.10.09 veranstaltet die .net Developer Group eine kostenlose Informationsveranstaltung rund um Visual Studio Team System 2010. Ein Tag voll gepackt mit wertvollen Informationen rund um die neue Version der Microsoft ALM-Plattform. Mit Visual Studio Team System 2010 führt Microsoft voraussichtlich Anfang nächsten Jahres eine neue Version seiner Entwicklungsplattform ein, die mit zahlreichen Neuerungen aufwartet. Diese neue Version wartet mit einer großen Zahl umfangreicher Neuerungen auf wie z.B.: - Architektur-Diagramme und UML-Support
- Erweiterte Funktionen für Test-Planung und Test-Durchführung
- Unterstützung von UI-Tests
- Verbesserte Verwaltung von Builds
- Verbesserte Verwaltung von Work Items
- Neue Reporting-Funktionen speziell für kleinere Teams
- Und vieles mehr
Um diese Umfangreichen Neuerungen alle vorstellen zu können, veranstaltet die .Net Developer-Group Ulm erstmalig einen ganztägigen Event um damit der Fülle von Funktionen auch gerecht zu werden. Dabei werden die beiden Referenten Christian Binder (http://blogs.msdn.com/cbinder) und Thomas Schissler (http://www.artiso.com/problog) nicht nur die neuen Funktionen vorstellen, sondern auch aufzeigen, welche Probleme aus dem Entwickler-Alltag damit gelöst werden können. Der Vortrag richtet sich dabei nicht nur an Entwickler und Projektleiter die bereits mit Team System arbeiten, sondern erläutert auch grundsätzliche Konzepte und bereits bestehenden Funktionen der Tools Visual Studio Team System und Team Foundation Server und bietet damit auch denjenigen einen guten Einstieg, die sich noch nicht intensiv mit Microsofts ALM-Plattform auseinandergesetzt haben. Für die Veranstaltung ist eine Registrierung erforderlich. Interessenten können sich unter http://www.dotnet-ulm.de/vsts2010 kostenlos registrieren.
Beim Installieren eines Team Foundation Server 2010 Beta 1 habe ich einen Fehler TF254038 bekommen. Beim Anlegen einer SharePoint Web Application auf dem TFS hat der Wizard behauptet ich hätte die SharePoint Extensions nicht installiert. Ich habe für den TFS und den SharePoint Server zwei getrennte Maschinen. Das Problem lag letztendlich darin, dass die Firewall auf der SharePoint Maschine den Zugriff auf die SharePoint Central Administration (Port 17012) geblockt hat. Nachdem ich den freigegeben habe, lief die Installation problemlos durch.
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. 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:
 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.
Im Team Foundation Server werden Änderungen an den Inhalten der Workitems in einer Historie festgehalten. Diese Historie kann man auf jedem einzelnen Workitem einsehen. 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: - Es ist wesentlich einfacher zu bedienen und übersichtlicher, so dass damit auch Ad-Hoc Reporting für Anwender möglich wird.
- 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.
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.
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.
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 
 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
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.
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.
&
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.
Beim Checkin ist auch die sehr nützliche Funktion zur Verknüpfung von Workitems beim Checkin verfügbar.
Damit kann Expression Blend nun endlich in den Entwicklungs-Prozess von Software-Anwendungen integriert werden und steht nicht nur als separates Design-Tool bereit.
 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!
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.
 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:
 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:
 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!
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.
 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
 Beim ersten Termin wurden die Grundlagen zu verteilten Anwendungen im allgemeinen und der WCF im speziellen vermittelt.
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.  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]"
Previous Next Problem Step 16: User left click on "Run (push button)" in "Open File - Security Warning"
Previous Next Problem Step 17: User left click on "Next > (push button)" in "artiso Workitem Manager Open"
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.
 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.
 | 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. |
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
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. 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”.
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.
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!
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: 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.
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).
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. 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”. Führt man hier nun den Checkin aus, kommt der aus dem Team-Explorer bekannte Dialog Hier können nun z.B. Checkin-Kommentare angegeben oder Workitems verknüpft werden. Sogar die Checkin-Plicies funktionieren hier wie gewohnt. 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.
 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.
 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.
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/
 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
 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
 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 "$(BuildNumber)"." /> 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 "$(SolutionRoot)"." /> 17: <Attrib Files="@(AssemblyInfoFiles)" Normal="true" /> 18: <FileUpdate Files="@(AssemblyInfoFiles)" 19: Regex="AssemblyVersion\(".*"\)\]" 20: ReplacementText="AssemblyVersion("$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)")]" /> 21: <FileUpdate Files="@(AssemblyInfoFiles)" 22: Regex="AssemblyFileVersion\(".*"\)\]" 23: ReplacementText="AssemblyFileVersion("$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)")]" /> 24: <Message Text="AssemblyInfo files updated to version "$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(AssemblyBuildNumber).$(AssemblyRevision)"" /> 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="<PublishUrl>.*</PublishUrl>" 15: ReplacementText="<PublishUrl>$(PublishDir)</PublishUrl>" /> 16: <FileUpdate Files="@(ProjectFiles)" 17: Regex="<InstallUrl>.*</InstallUrl>" 18: ReplacementText="<InstallUrl>$(InstallURL)</InstallUrl>" /> 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
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: Blick von der Space Needle auf Seattle  Die Team-System MVPs  Sam Guckenheimer  Brian Harry Karaoke mit Live-Band bei der Party Steve Balmer bei seiner Key-Note
Gestern und heute hatte ich auf der BASTA zwei Vorträge. Hier die Folien dazu:
 Ich bin reichlich spät dran, die VSOne ist schon seit einer Woche vorbei. Hier aber nun endlich meine Folien zu meinen Vorträgen
 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
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.
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.
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.
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?
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.
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:
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.

|
Copyright © 2010 Thomas. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.
Pick a theme:
|
|