xUnit BDD Extensions

Wednesday, October 22, 2008 6:24:03 PM (W. Europe Daylight Time, UTC+02:00)

Auf dem .NET Open Space hat Björn Rochel seine xUnit BDD Extensions vorgestellt und wir haben uns in einer Session auch länger darüber unterhalten.

Heute habe ich seine Extensions das erste Mal ausprobiert und einen neuen Unit Test nach BDD Art geschrieben.

Dieser spezielle Test war besonders kompliziert, da ich hier Code in einem Windows Service testen wollte und dafür die OnStart Methode aufrufen musste, die protected ist. Außerdem startet der Code der getestet wird mehrere neue Threads, und der Test sollte prüfen, ob diese Threads auch wirklich gestartet wurden.

Der Test sieht dann folgendermaßen aus:

public class 
When_the_Service_Starts_And_There_Are_three_Tasks : 
TaskRunnerServiceSpecification
   {
       #region Arrange

       protected override void EstablishContext()
       {
           base.EstablishContext();

           newThreads = new List<Thread>();

           // add some tasks
           tasks.Add(new TestTask(this));
           tasks.Add(new TestTask(this));
           tasks.Add(new TestTask(this));
       }

       internal IList<Thread> newThreads;



       #endregion

       #region Act

       protected override void Because()
       {
           // because OnStart was called...
           taskRunnerService.InvokeNonPublicMethod(
              "OnStart", new object[] {
                 new string[0]});

           // ... wait a second to give the other 
           // threads a chance to execute
           Thread.Sleep(1000);
       }

       #endregion

       #region Assert

       [Observation]
       public void should_create_three_new_threads()
       {
           newThreads.Distinct().Count().
           ShouldBeEqualTo(3);
       }

       [Observation]
       public void should_execute_all_tasks()
       {
           tasks[0].wasExecuted.ShouldBeTrue();
           tasks[1].wasExecuted.ShouldBeTrue();
           tasks[2].wasExecuted.ShouldBeTrue();
       }


       #endregion

       #region Cleanup


       protected override void AfterEachObservation()
       {
           base.AfterEachObservation();

           foreach (var thread in newThreads)
           {
               if (thread.IsAlive)
                   thread.Abort();
           }
       }

       #endregion
   }

Im Prinzip verbirgt sich dahinter ein “ganz normaler” Unit Test mit xUnit und Rhino Mocks (wobei ich in diesem speziellen Test zufällig gerade keine Mocks nutze), allerdings besser strukturiert und mit lesbareren Methodennamen (z.B. ShouldBeTrue statt Assert.True).

Durch die Bennenung der Tests und Methoden nach BDD-Art ist die Ausgabe im ReSharper Testrunner richtig gut lesbar:

image

In dem Beispielcode oben fehlt noch eine Hilfsklasse für diesen Test, TestTask. Diese setzt nur ihre “wasExecuted”-Eigenschaft auf true, falls die Execute-Methode aufgerufen wurde, und fügt ihren Thread zur newThreads-Liste hinzu.

Wir werden das in der Praxis weiter ausprobieren (ein anderer Kollege hat sich vorhin auch schon an BDD versucht), und diesen Ansatz wenn er sich bewährt für alle unsere Unit Tests übernehmen.

Kick it on dotnet-kicks.de

Das Model-View-Presenter Pattern in ASP.NET – Teil 1

Tuesday, October 21, 2008 7:10:09 PM (W. Europe Daylight Time, UTC+02:00)

Im Moment liest man überall vom ASP.NET Model View Controller (MVC) Framework. Das MVC Framework unterscheidet zwischen einem Model, einer View und einem Controller, und führt so zu einer klaren Aufgabentrennung und leichter testbarem Code.

Um testbare ASP.NET Web Seiten zu schreiben, bei der die Darstellung (View) sauber von der Logik und vom Modell getrennt ist, muss  man jedoch nicht erst auf das MVC Framework warten. Auch mit ASP.NET Web Forms ist es möglich, gut strukturierte und testbare Anwendungen zu entwickeln.

Ein Ansatz dafür ist das Model-View-Presenter (MVP) Pattern. Auf den ersten Blick ist das MVP Pattern dem MVC Pattern sehr ähnlich. Beide Ansätze verfolgen im Prinzip die gleichen Ziele, erreichen diese nur auf einem anderen Weg. Eine genaue Beschreibung der Unterschiede gibt es z.B. unter

http://ameleta.spaces.live.com/blog/cns!5F6316345A821420!163.entry

http://stackoverflow.com/questions/2056/what-are-mvp-and-mvc-and-what-is-the-difference#101561

Das Pattern das ich verwende ist eine Variante des MVP Patterns, und nennt sich “Supervising Controller”. Dieses Pattern wird von Fowler sehr ausführlich beschrieben.

Meine Implementierung des MVP Patterns basiert auf einer Implementierung von David Hayden: http://www.pnpguidance.net/Post/UnityIoCDependencyInjectionASPNETModelViewPresenter.aspx

David verwendet das MVP Pattern zusammen mit Microsoft Unity als Dependency Injection Container. Über das Thema Dependeny Injection werde ich später vielleicht in einem eigenen Beitrag schreiben, bis dahin soll es ausreichen zu wissen, dass sich Unity darum kümmert, dass Model, View und Presenter richtig miteinander “verdrahtet” werden.

David hat Basisklassen für View und Presenter geschrieben. Die View ist bei ihm eine von System.Web.Page abgeleitete Klasse. Die View hat zwei Typparameter, TView und TPresenter. Als TView übergeben wir ein Interface, das die Methoden enthält, über die der Presenter Daten in der View darstellen kann. TPresenter ist der zur View passende Presenter. Die View erhält eine Referenz zu ihrem Presenter, und benachrichtigt diesen dann über verschiedene Ereignisse (Seite geladen, Button geklickt usw.).

Ich habe mit Davids Code angefangen und bin dann mehrfach an Stellen gekommen, wo ich seinen Code erweitern musste. So soll z.B. eine einzelne Seite oft nicht nur eine View, sondern gleich mehrere unterschiedliche Views in Form von Steuerelementen darstellen können. Dafür habe ich eine BaseControl-Klasse geschrieben, die von UserControl ableitet und so MVP basierte UserControls ermöglicht. Auch für MasterPages möchte ich das MVP Pattern einsetzen können, und habe dafür eine BaseMasterPage geschrieben.

An einigen Stellen musste ich auf ASP.NET-spezifische Klassen wie SessionState und Cache zugreifen. Um diese besser testen zu können und in meinen Tests unabhängig von ASP.NET zu bleiben habe ich mir für diese Fälle die Interfaces ICacheProvider bzw. IStateProvider geschrieben, die von BasePage/BaseControl/BaseMasterPage implementiert werden, und somit einen Zugriff auf SessionState und Cache ermöglichen, ohne dass ich dafür in meinen Tests ASP.NET Klassen verwenden müsste.

Als letzte Klasse gibt es dann schließlich noch die BaseApplication, die sich genau wie die HttpApplication-Klasse in Davids Beispiel um die Initialisierung des Unity-Containers kümmert.

Zusammengenommen ergibt sich damit folgendes bild:

image

Da ich diese Klassen so in mehreren Projekten verwenden kann (und auch bereits verwendet habe) habe ich das alles noch in ein eigenes Projekt ausgelagert.

Soweit die Theorie. In Teil zwei zeige ich dann an Beispielen aus meinem Quellcode, wie ich das MVP Pattern angewendet habe.

Kick it on dotnet-kicks.de

Was ist eigentlich dieses ALT.NET?

Sunday, August 10, 2008 2:11:37 AM (W. Europe Daylight Time, UTC+02:00)

Wer regelmäßig .NET Blogs liest – insbesondere englischsprachige .NET Blogs – wird in letzter Zeit früher oder später auf den Begriff ALT.NET gestossen sein. Mir ist der Begriff jedenfalls in den letzten Monaten immer häufiger begegnet, und irgendwann habe ich dann angefangen, mich näher mit dem Thema zu beschäftigen.

Was ist denn nun ALT.NET? Faul wie ich bin kopiere ich einfach Mal die Erklärung dazu von der deutschen ALT.NET Community altdotnet.de:

Was ist ALT.NET?
Die wichtigste Quelle dazu ist http://www.altnetpedia.com/ (engl.)
Die ALT.NET Bewegung definiert sich wie folgt (engl. Version):
  • ALT.NET Entwickler verwenden was funktioniert und suchen ständig nach neuen, besseren Lösungen.
  • ALT.NET Entwickler bewegen sich auch außerhalb des Mainstream und verwenden Lösungen, Konzepte, Ideen aus allen Bereichen (Open Source, Agile, Java, Ruby, etc.).
  • ALT.NET Entwickler geben sich mit dem status quo nicht zufrieden und suchen ständig nach Möglichkeiten sich in ihrem Code besser, einfacher und eleganter auszudrücken.
  • ALT.NET Entwickler halten Tools für wichtig, wirklich wichtig sind aber fundierte Kenntnisse und Prinzipien. Die besten Tools sind solche, die einen bei der Anwendung der Prinzipien unterstützen.


ALT.NET ist nicht kontra Microsoft und auch nicht alternativ. Es geht uns darum aus den möglichen Alternativen die jeweils beste auszuwählen. Das schließt Lösungen von Microsoft ausdrücklich mit ein, genauso wie Open Source und Third Party Hersteller.

Klingt zunächst einmal sinnvoll und interessant. Allerdings gibt es auch einige kritische Meinungen dazu (einige sind auf der englischsprachigen ALT.NET Seite verlinkt). So wirken z.B. einige der aktiveren ALT.NET Community-Mitglieder auf andere Blogger elitär und arrogant, und teilweise wird ALT.NET als Anti-Microsoft Bewegung gesehen, die alles ablehnt, was von Microsoft kommt, egal ob die alternativen Lösungen nun tatsächlich besser sind oder nicht. Insbesondere in englischsprachigen Blogs sind mir einige Blogbeiträge begegnet, die in diese Richtung gehen (tatsächlich war einer dieser Beiträge sogar mein erster Kontakt mit ALT.NET). In der deutschen Community habe ich zumindest bisher noch nichts negatives darüber gelesen.

Prinzipiell finde ich es gut, sich mit alternativen Tools zu beschäftigen. Nach neuen und besseren Lösungen suche ich sowieso ständig. Für mich persönlich heisst das aber nicht, dass ich unbedingt gleich für alles Alternativen zum “Mainstream von Microsoft” suchen muss. Auch wenn es für manche Bereiche gute Alternativen gibt (z.B. NHibernate als Alternative zu LINQ to SQL) entscheide ich mich trotzdem oft für die Microsoft Lösung.

Ich bin freiberuflicher Trainer und Entwickler. Als Trainer muss ich mich mit den Technologien auskennen, die am meisten nachgefragt werden. Bisher hatte ich noch keine einzige Anfrage zu NHibernate, Castle Windsor, Monorails oder irgendwelchen anderen Alternativen Technologien, aber zu den “Mainstream” Technologien von Microsoft bekomme ich mehr Anfragen als ich annehmen kann. Würde ich anfangen, alle Mainstream Technologien durch ihre “ALT.NET Alternativen” zu ersetzen, dann könnte ich solche Anfragen bald nicht mehr annehmen, weil mir dann die praktische Erfahrung mit den Mainstream Produkten fehlen würde. Als Entwickler habe ich das Problem, das ich quasi für jedes Projekt in eine neue Firma komme und mit neuen Leuten zusammenarbeite, und dann mit den Technologien arbeiten muss, die beim jeweiligen Kunden eingesetzt werden – und das sind nun mal in der Regel die “Mainstream Technologien” von Microsoft. Ausnahmen gibt es da höchstens beim Team Foundation Server – der ist gerade für kleinere Firmen einfach oft zu teuer, so dass dann Alternativen wie Subversion, Cruisecontrol.NET usw. eingesetzt werden.

Bin ich also nun ein “ALT.NETter” oder eher ein “Mainstream” Entwickler? Ich setzte zwar hauptsächlich Tools von Microsoft ein, aber wenn man sich die ALT.NET Definition oben mal genauer anschaut steht dort nirgendwo, dass das ein Widerspruch sein muss. Unter den für mich gegebenen Rahmenbedingungen setze ich die Tools ein, die für mich am besten geeignet sind. Das sind nun mal in meinem Fall sehr oft – aber nicht immer – die Microsoft Tools. Teilweise sind es aber auch “ALT.NET Tools”, z.B. xUnity und RhinoMocks. Insofern würde ich mich weder als “typischen ALT.NET Entwickler” noch als “typischen Microsoft Mainstream Entwickler” sehen.

Im Oktober findet übrigens die erste deutsprachige ALT.NET Konferenz statt: http://netopenspace.de. Wenn nichts dazwischen kommt werde ich auf jeden Fall daran teilnehmen, das wird sicher eine spannende Abwechslung zu den klassischen Konferenzen.

Technorati Tags: ,

Kick it on dotnet-kicks.de
Page 1 of 1 in the ALTNET category