December 2008 Entries

Virtuelles ALT.NET DE Meeting am 29.12.2008

Kurz vor Jahresende findet das erste ALT.NET DE Online Treffen statt

Beim ersten Treffen gibt es noch kein spezielles Thema.

Jeder interessierte kann Teilnehmen, sofern ein Headset vorhanden ist, eine WebCam dazu schadet nicht, jedoch muss der Live Meeting Client installiert sein (kann man auf der Testseite machen)

Wie das ganze abläuft steht noch nicht fest, es wohl erst einmal ein wenig Open Space sein um dies zu erarbeiten.

Offiziell geht es ab 20 Uhr los, die Lobby ist aber 19:30 Uhr geöffnet.

Weitere Informationen zum Online-Meeting

Technorati-Tags: ,,

Wie man von einem UserControl auf ein anderes zugreift?

Am besten gar nicht!

Eine der Standard-Fragen von Foren und Newsgroups scheint mir zu sein wie man von Control A auf Control B zugreift. Oft übergreifend zwischend UserControls welche auf einer WinForm/WebForm eingesetzt wird.

Bei ASP.NET wird dann oft versucht mit FindControl() dass jeweilige Control auf welches man nun unbedingt zugreifen muss zu suchen um dieses dann, sofern gefunden, entsprechend den Vorstellungen zu bearbeiten.

Dann Frage ich mich, ob der Sinn von Objekt-Orientierung in Ansätzen verstanden wurde? Soll dieses UserControl wirklich nur auf dieser speziellen Seite mit eingesetzt werden? Warum dann ein UserControl? Was wird gemacht wenn das UserControl mal auf einer anderen Seite eingesetzt wird? Wird dann je nach Seite entschieden welches andere Control gebraucht wird? und und und.

Warum denn nicht?

Durch die Verwendung eines UserControls erhält man eine potentiell wiederverwendbare Komponente die sich an verschiedenen Stellen einsetzen lässt. Damit dies jedoch funktioniert sollte ein Control so wenig wie möglich von seiner Umgebung wo es eingesetzt wird wissen, am besten gar nichts.

Doch es wird häufig in einem Control direkt auf die Datenbank zugegriffen, aus einem Control wird versucht zu erahnen in welchem Kontext es läuft um Entscheidungen zu treffen. Z.B. ein- und ausblenden von fremden - nicht im Control verwendeten - Controls oder fremden Text zu Modifizieren oder was auch immer nicht im Einflussbereichs der Control liegt.

Damit ist eine Wiederverwendung so gut wie unmöglich und kann direkt sein gelassen werden. Man hat eine sehr enge Kopplung an die Umgebung. Früher oder später knallt einem das Control um die Ohren (falsche Daten, keine Änderung des fremdem Controls etc.), man ärgert sich, schiebt Frust und früher ohne Objektorientierung war eh alles besser.

Ein paar Faustregeln

What Happens in Vegas, stays in Vegas.

  • Es geht das Control nichts an wo die Daten herkommen.
  • Es geht das Control nichts an wo es eingesetzt wird.
  • Es geht das Control nichts an was andere Controls machen
  • Es geht das Control nichts an welche Entscheidungen aufgrund bestimmter Zustände des Controls gemacht werden.
  • Die Steuerung und Reaktion auf ein Control übernimmt eine übergeordnete Instanz wie z.B die Seite auf der das Control verwendet.
  • Es geht die übergeordnete Instanz nichts an was im Control im Detail passiert.
  • Das Control (bzw. dessen Entwickler) entscheidet was für Verwendung wichtig ist und kommuniziert nur dies nach außen.

Die ASP.NET WebControls machen zum Beispiel machen es so, die WinFoms-Controls ebenso auch Control-Libraries arbeiten so. Warum? Damit sie überall eingesetzt werden können. Also spricht doch nichts dagegen die eigenen Sachen auch so zu gestalten.

 

Technorati-Tags: ,,,

Mehrere Monitore und wie bin ich nur ohne zusätzliche Unterstützung ausgekommen

Ich bin ja schon seit Jahren ein Verfechter davon mit mehreren Monitoren zu arbeiten. So gab es ein paar Dinge die mich störten, nur Kleinigkeiten, aber nervig. Was jedoch an Windows liegt und nicht an den mehreren Monitoren ;)

Habe dann vor einigen Wochen (erst!) UltraMon entdeckt. Doch ich habe es dann sofort in mein Herz geschlossen. Es ist nicht alles Perfekt, aber das was ich davon nutze gefällt mir.

TaskBar auf den anderen Monitoren

Windows zeigt die TaskBar nur auf dem primären Monitor an, was nervt wenn man auf einen anderen Monitor fokussiert ist und dann der Blick nach unten schweift um in der TaskBar was auszuwählen und es ist nicht da. Mit UltraMon hat jeder Monitor eine eigenen TaskBar, entweder nur mit den Fenster die auf dem Monitor sind, oder auf jeder  Taskbar denselben Inhalt.

Ich bevorzuge die erste Variante. Jedoch kommt es bei mir vor dass ich hier und da ein Programm wie Notepad++ oder so doppelt starte weil es nicht auf der im Fokus befindlichen TaskBar angezeigt wird. Dies kommt aber selten vor. Schade finde ich auch dass ich den Task-Manager nicht über die UltraMon-TaskBars anzeigen lassen kann.

Verschieben von Fenstern auf den anderen Monitor

Wenn man ein Fenster auf einem anderen Monitor zieht, dann passt Windows nicht die Größe an wenn die Monitore unterschiedliche Auflösungen haben. Ärgerlich. Mit UltraMon verschiebe ich auf Mausklick bzw. Tastendruck ein Fenster von A nach B und die Proportionen des Fensters werden beibehalten. Sehr schön.

Dies sind so ziemlich die einzigen Features von UltraMon die ich bewusst einsetze. UltraMon kann noch mehr, so “Kleinkram” wie Desktop-Hintergründe für mehrere Monitore eintragen, merken von Icon Positionen etc.

Anpassbar

UltraMon ist sehr granular anpassbar, so kann man entscheiden wo Buttons hinkommen, Menü erweitertet werden und ob überhaupt. Für problematische Anwendungen gibt es wohl auch spezielle Einstellungen, jedoch habe ich keine Probleme ausmachen können die auf UltraMon zu führen waren. Die TaskBar und die Fenster-Buttons fügen sich schön dem Vista-Aero-Look. Auch hält es sich direkt im Hintergrund wenn man plötzlich keinen zweiten Monitor mehr am System hat (was bei mir des öfteren vorkommt, da ich nur noch am Laptop arbeite).

Missen möchte UltraMon nicht mehr, ob es einem 40 Dollar wert ist muss man für sich selbst entscheiden. Es gibt eine mir bekannte alternative MultiMonitor Taskbar, die passt sich in der kostenlosen Version jedoch nicht dem Look & Feel des System an.

Technorati-Tags: ,,

Die Bestandteile von Visual Studio 2008 SP1 anpassen funktioniert nicht

Warum?

Hat man wie ich nur 64 Gigabyte als Hauptfestplatte (dafür SSD) im Laptop eingebaut. So ist man darauf bedacht diese nicht auch irgendwie nicht zum überlaufen zu bringen. Somit räume ich hier und da mal auf und lösche & deinstalliere was ich nicht mehr brauche.

Was ich schon ewig nicht mehr brauche, aber immer wieder auf meiner Festplatte landet ist die native C++ Entwicklung. So aus lauter Tradition.

Somit dachte ich mir einfach mal ich passe die Installation von Visual Studio 2008 an und entferne die nicht benötigen Bestandteile einfach.

Fehlverhalten

confusedAlso das Setup von Visual Studio gestartet, alles was ich nicht mehr brauchte abgewählt und dann kam es zur einer Fehlermeldung. Die ich leider aus dem Kopf nicht mehr zusammen bekomme. Irgendwas dass ein Pfad oder so nicht stimmte.

Na super, was für ein Pfad dachte ich mir, probierte einiges aus, fragte die Suchmaschine meine Vertrauens und in den tiefen des Internets habe ich was gefunden.

Deinstallieren des ServicePack 1

Die Verhinderung der Anpassung lag im ServicePack 1, sobald dies installiert ist kann man die Bestandteile von Visual Studio 2008 nicht mehr anpassen. Dumm gelaufen.

Lösungsweg

  1. Visual Studio 2008 Service Pack 1 deinstallieren
  2. Konfiguration von Visual Studio anpassen
  3. Service Pack 1 wieder installieren
  4. eventuell nun fehlerhafte AddIns/Packages installieren (bei mir machten nur die Silverlight Tools Probleme).

Das ganze dauerte zwar ein wenig, aber wenigstens dauert die Installation des 2008er ServicePacks ja nicht mehr so lange wie dass vom Visual Studio 2005.

Technorati-Tags: ,,,

Unterstriche im Namen von Unit-Tests; Berichte und einfache Eingabe

Wie man in den letzten Beiträgen gesehen hat verwende nutze ich für Namensgebung von Unit-Test Sätze und trenne die Worte mit einen Unterstrich und mache da kein PascalCasing.

Der Grund ist einfach die Lesbarkeit und erzeugen von Dokumentation.

When_the_user_request_the_Newsletter_on_the_AddNew_page_and_enters_a_password  ist einfacher zu lesen als WhenTheUserRequestTheNewsletterOnTheAddNewPageAndEntersAPassword.

image_thumbBDDDoc

Bei Normalen Klassen und Methodennamen klappt es meistens mit der Lesbarkeit mit PascalCasing jedoch bei natürlichen Sätzen die eine Spezifikation beschreiben passt es halt nicht so.

Desweiteren gibt es ein nettes Tool names BDDDoc. Welches aus BDD-Style Tests Berichte generiert die man zur Dokumentation verwenden kann.

http://blog.jpboodhoo.com/UpdateToBDDDoc.aspx

Unterstriche eingeben

Nicht ganz so optimal bei der Eingabe von Sätzen mit Unterstrichen ist natürlich die Eingabe der Unterstriche, diese hemmen ein wenig den Schreibfluss.

Schon wäre es wenn man während dem Schreiben des Satzes einfach alle Leerzeichen durch Unterstriche ersetzt würden.

In der deutschsprachigen ALT.NET Mailingliste wurde dafür eine nette Lösung gepostet. Man nehme einfach AutoHotKey, ein kleines Open-Source-Utility.

AutoHotKey ist mit Skripten anpassbar so das bei Tastendrücken Tastatur- und Mausmakros ablaufen. Mit einem speziellen Skript ist es möglich Leerzeichen durch Unterstriche während der Eingabe zu ersetzen.

Download AutoHotKey

Skript für das ersetzen der Leerzeichen

Dieses Skript in AutoHotKey einbinden und nachdem man Strg+Shift+U gedrückt hat werden alle Leerzeichen durch Unterstriche ersetzt. Nach der Eingabe- oder Esc-Taste schreibt man automatisch wieder Leerzeichen.

Technorati-Tags: ,,

Extension-Methods für ASP.NET MVC Unit-Tests

Ich habe ein paar Extension-Methods für schönere Unit-Tests vorgestellt. Nun stelle ich wieder zwei vor. Diese sind speziell für das ASP.NET MVC Framework mit der ASP.NET MVC Futures (Microsoft.Web.Mvc.Dll) Erweiterung.

public static class MvcBDDExtension
{
    public static void should_link_to<T>(this Expression<Action<T>> expected, Expression<Action<T>> action) where T : Controller
    public static void should_route_to<T>(this ActionResult actionResult, Expression<Action<T>> action) where T : Controller
}

Damit kann man überprüfen ob ein typisierter Link zu einer bestimmten Controller-Action gesetzt ist und ob ein RedirectRouteResult zu einer bestimmte Controller-Action zurückgegeben worden ist. Den Quelltext gibt es am Ende.

Erst einmal ein paar erklärende Worte vorneweg.

Typisierte Links sind mit den ASP.NET MVC Futures möglich. Diese haben den Vorteil dass ich die Controller als auch die Actions per Refactoring umbenennen kann ohne das mir die Anwendung kaputt geht. Man kann die Textuelle Verlinkung zwar mit Unit-Tests überprüfen, jedoch sollte ein Umbenennen einer Klasse oder Methode kein Anpassung von Unit-Tests zur Folge haben.

So sieht die Erstellung von typisierten Links innerhalb eines Views aus, am konkreten Beispiel einer MasterPage.

<div id="menucontainer">
    <ul id="menu">
        <li>
            <%=Html.ActionLink(Model.LinkToHome, @"Startseite")%></li>
        <li>
            <%=Html.ActionLink(Model.LinkToAboutUs, @"Impressum")%></li>
    </ul>
</div>

Das ViewModel sieht in diesem Fall so aus.

using System;
using System.Linq.Expressions;

namespace Newsletter.Web.Controllers.ModelViewData
{
    public class ViewDataBase
    {
        public Expression<Action<AccountController>> LinkToLogout;
        public Expression<Action<AdminController>> LinkToAdmin;
        public Expression<Action<AccountController>> LinkToRegister;
        public Expression<Action<HomeController>> LinkToHome;
        public Expression<Action<HomeController>> LinkToAboutUs;
        public string Title { get; set; }
        public string Username { get; set; }
    }
}

Der View ist entsprechend typisiert und bietet eine Model-Property zum einfacheren Zugriff auf das ViewModel.

using System;
using System.Web.Mvc;

using Newsletter.Web.Controllers.ModelViewData;

namespace Newsletter.Web.Views.Shared
{
    public partial class Site : ViewMasterPage<ViewDataBase>
    {
        protected ViewDataBase Model
        {
            get { return ViewData.Model; }
        }
    }
}

Die Controller-Actions werden dann folgendermaßen Eingetragen. Es sind verschiedene Controller mit entsprechenden Actions.

public static class ViewDataExtensions
{
    public static void SetMasterPageData(this ViewDataBase viewData)
    {
        viewData.LinkToAdmin = ac => ac.Index();
        viewData.LinkToRegister = ac => ac.Register(string.Empty, string.Empty, string.Empty, string.Empty);
        viewData.LinkToLogout = ac => ac.Logout();
        viewData.LinkToHome = hc => hc.Index();
        viewData.LinkToAboutUs = hc => hc.About();
    }
}

Damit sind typisierte Links auf Controller-Actions gesetzt und ich brauche mir keine Gedanken zu machen was passiert wenn ich diese umbenenne.

Es ist jedoch erforderlich in einem Unit-Test zu überprüfen ob auch wirklich bei jedem View die entsprechenden Links im ViewModel gesetzt sind.

Hier schlägt nun die Stunde für die should_link_to<T>() Extension-Method.

[Observation]
public void the_MasterPageLinks_should_be_set_if_a_ViewResult_is_given_back()
{
    if (result is ViewResult)
    {
        var model = GetViewModel<ViewDataBase>();

        model.LinkToAboutUs.should_link_to(homeController => homeController.About());
        model.LinkToHome.should_link_to(homeController => homeController.Index());

        model.LinkToAdmin.should_link_to(adminController => adminController.Index());
        model.LinkToLogout.should_link_to(accountController => accountController.Logout());
        model.LinkToRegister.should_link_to(accountController => accountController.Register(string.Empty, string.Empty, string.Empty, string.Empty));
    }
}

Durch einfaches Lesen des Quelltextes kann man nun schnell erkennen was dazu führen muss um den Test zum funktionieren zu bringen.

result ist ein field innerhalb der Test-Klasse welchen den ActionResult der zu testenden Controller-Action beinhaltet und GetViewModel<T>() holte das aktuelle ViewModel aus dem result.

Möchte man jedoch Testen ob eine Weiterleitung zu einer bestimmten Controller-Action vorgenommen wurde. So ist dies mit should_route_to<T>() möglich.

using System;
using System.Web.Mvc;

using DerAlbert.UnitTest.Base.BDD;

using Newsletter.Manager;
using Newsletter.Web.Controllers;
using Newsletter.Web.Controllers.ModelViewData;

namespace Newsletter.Controllers.Tests.SpecsSubscriberController.AddNewSubscriber
{
    [Concern(typeof (SubscriberController))]
    public class When_the_user_request_the_newsletter_on_the_addnew_page : concern_of_SubscriberController
    {
        // einiges an Setup und Observations für das Beispiel weggelassen, 
        // da es sonst zu unübersichtlich als Beispiel wird.

        private AddNewSubscriberViewData viewData;

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

            viewData = new AddNewSubscriberViewData
                           {
                               SubscriberName = @"Hubert",
                               EMail = @"hello@world.de",
                               EMailVerify = @"hello@world.de",
                               Result = @"an Answer"
                           };

            subscriberManager.when_told_to(sm => sm.ValidateCaptcha(viewData)).Return(true);
        }

        protected override void because()
        {
            result = sut.AddNewSubscriber(viewData);
        }
    
        [Observation]
        public void the_page_should_be_redirected_to_SubscriberController_SubscriberAdded()
        {
            result.should_route_to<SubscriberController>(sc => sc.SubscriberAdded());
        }
    }
}

Dies ist ein Real-World BDD-Style Test und hier etwas abgespeckt dargestellt. Hier sieht man im Quelltext was passiert muss damit eine Spezifikation erfüllt ist.

Jetzt ist es soweit der Quelltext der Methoden. Diese brauchen die ASP.NET MVC Future und die vorhandenen BDD Extensions.

Happy Testing mit den Extension-Methods.

using System;
using System.Linq.Expressions;
using System.Web.Routing;

using Microsoft.Web.Mvc.Internal;

using System.Web.Mvc;

namespace DerAlbert.UnitTest.Base.BDD
{
    public static class MvcBDDExtension
    {
        public static void should_link_to<T>(this Expression<Action<T>> expected, Expression<Action<T>> action) where T : Controller
        {
            RouteValueDictionary expectedDictionary = ExpressionHelper.GetRouteValuesFromExpression(expected);
            RouteValueDictionary actionDictionary = ExpressionHelper.GetRouteValuesFromExpression(action);
            actionDictionary.should_only_contain(expectedDictionary);
        }

        public static void should_route_to<T>(this ActionResult actionResult, Expression<Action<T>> action) where T : Controller
        {

            var redirectResult = (RedirectToRouteResult)actionResult;
            RouteValueDictionary actionDictionary = ExpressionHelper.GetRouteValuesFromExpression(action);
            actionDictionary.should_only_contain(redirectResult.Values);
        }
    }
}

Habt Ihr eigene Extension-Methods für Test? Her damit!
Wie haltet Ihr dass mit dem Testen?
Ist dies hier alles Mumpitz und Assert.IsXYZ() is viel besser?

Verehrte Leser, nutzt die Kommentarfunktion.

Technorati-Tags: ,,

Extension-Methods für schöneres Unit-Testing

Schönes Unit-Testing? Was soll denn dies sein.

Ok, schön ist Relativ. Ich finde dass die Lesbarkeit von Quelltexten sehr wichtig ist, auch die von Unit-Tests. Ich definiere dies dann als schön ;)

Die Assert-Syntax der Unit-Testing Frameworks war für mich nie so sonderlich einleuchtend. Da es ist einfach nicht so prickelnd liest.

[Test]
public void Fehlerhafte_EMail_mit_zwei_at_Zeichen()
{
    var validator =  new EMailValidator();

    Assert.IsFalse(validator.Validate("a@@bd.cd"));
    Assert.IsFalse(validator.Validate("a@.@bd.cd"));
}

Ich bin ein von Links-nach-Rechts Leser, mein ganzes Leben schon und hier muss ich mehr oder weniger umdenken. Klar, es geht, jedoch gibt es da Verbesserungspotential.

Mit Behavior-Driven-Development (BDD) erhalten die Unit-Tests eine neue Syntax. Es steht nicht der Test im Mittelpunkt, sondern die Spezifikation. Dazu gibt es auch eine verbesserte Schreibweise der Tests. Die jedoch hier nicht Thema ist, dazu später einmal mehr. In der Zwischenzeit verweise ich auf einen Blog-Eintrag von Stefan Lieser der dazu nächstes Jahr einige Vorträge halten wird. Jetzt nur die Empfehlung sich BDD näher anzusehen, da es die Denkweise für Unit-Tests verändert und leichter Zugänglich macht.

Jedoch kann man Teile des BDD-Style auch im klassischen Unit-Test verwenden. Wenn z.B. BDD nicht auf die zu testende Unit passt und man dort lieber Old School testet.

[Test]
public void Fehlerhafte_EMail_mit_zwei_at_Zeichen()
{
    var validator =  new EMailValidator();

    validator.Validate("a@@bd.cd").should_be_false();
    validator.Validate("aa@.@bd.cd").should_be_false();
}

In dieser Form ist der Test besser zu verstehen (für uns Links-nach-Rechts Leser). should_be_false() ist eine Extension-Method die auch nur einen Assert macht.

Diese Extension-Method habe ich von JP Boodhoo, auf einem Vortrag in Bonn hat er diese vorgestellt. Ich war sofort Feuer und Flamme und ich sagte zur mir; so einfach und nicht selbst darauf gekommen. Es wurde auch kein spezielles BDD-Test-Framework (wie MSpec oder NBhave) verwendet, sondern klassisches MbUnit.

Mittlerweile sind auch eigene dazu gekommen und vorhandene verbessert worden.

public static class BDDExtensions
{
    public static void force_traversal<T>(this IEnumerable<T> items)
    public static void should_be_null(this object item)
    public static void should_be_equal_to(this object item, object other)
    public static void should_contain<T>(this IEnumerable<T> items, T item)
    public static void should_be_greater_than<T>(this T item, T other) where T : IComparable<T>
    public static void should_not_be_equal_to<T>(this T item, T other)
    public static void should_be_equal_ignoring_case(this string item, string other)
    public static void should_contain<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
    public static void should_only_contain<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
    public static void should_only_contain_in_order<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
    public static void should_be_true(this bool item)
    public static void should_be_false(this bool item)
    public static void should_be_equal_to<T>(this T actual, T expected)
    public static ExceptionType should_throw_an<ExceptionType>(this Action workToPerform)
    public static void should_not_throw_any_exceptions(this Action workToPerform)
    public static void should_be_an_instance_of<Type>(this object item)
    public static void should_not_be_null(this object item)
    public static void should_not_be_null_or_empty(this string item)
    public static void should_be_null_or_empty(this string item)
    public static void should_be_empty<T>(this IEnumerable<T> items)
    public static void should_not_be_empty<T>(this IEnumerable<T> items)
}

Dies ist der aktuelle Stand von Basis-Extension-Methods die ich in Unit-Test und BDD-Tests verwende. Den kompletten Quelltext gibt es am Ende des Artikels.

Ich erweitere diese immer sobald es mir Sinnvoll erscheint. Auch mache mir spezielle Extension-Methods z.B. für ASP.NET MVC (dazu später mehr).

Hier noch ein kleines Beispiel um zu überprüfen ob in einer Liste bestimmte Elemente vorhanden sind.

[Test]
public void Wird_eine_Liste_mit_Namen_zurueckgeben()
{
    List<string> names = FooBar.GetNames();    
    names.should_only_contain(new List<string>{"Albert","Peter","Weinert"});
}

Der Einsatz von Extension-Methods anstelle von Assert.IsXYZ() führt zu einer besseren Lesbarkeit von Tests und somit zu schöneren Unit-Tests.

Hier nun der komplette Quelltext der Extension-Methods in Verbindung mit MbUnit, jedoch können diese einfach an andere Unit-Test-Frameworks angepasst werden.

/*
 * based on the BDD Extensions of Jean-Paul Boodhoo http://jpboodhoo.com
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;

using MbUnit.Framework;

namespace DerAlbert.UnitTest.Base.BDD
{
    public static class The
    {
        public static Action action(Action action)
        {
            return action;
        }
    }

    public static class BDDExtensions
    {
        public static void force_traversal<T>(this IEnumerable<T> items)
        {
            items.Count();
        }

        public static void should_be_null(this object item)
        {
            Assert.IsNull(item);
        }

        public static void should_be_equal_to(this object item, object other)
        {
            Assert.AreEqual(other, item);
        }

        public static void should_contain<T>(this IEnumerable<T> items, T item)
        {
            Assert.IsTrue(new List<T>(items).Contains(item));
        }

        public static void should_be_greater_than<T>(this T item, T other) where T : IComparable<T>
        {
            (item.CompareTo(other) > 0).should_be_true();
        }

        public static void should_not_be_equal_to<T>(this T item, T other)
        {
            Assert.AreNotEqual(other, item);
        }

        public static void should_be_equal_ignoring_case(this string item, string other)
        {
            StringAssert.AreEqualIgnoreCase(item, other);
        }

        public static void should_contain<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
        {
            var results = new List<T>(items);
            foreach (T itemToFind in itemsToFind)
            {
                results.Contains(itemToFind).should_be_true();
            }
        }

        public static void should_only_contain<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
        {
            itemsToFind.Count().should_be_equal_to(itemsToFind.Count());
            items.should_contain(itemsToFind);
        }

        public static void should_only_contain_in_order<T>(this IEnumerable<T> items, IEnumerable<T> itemsToFind)
        {
            itemsToFind.Count().should_be_equal_to(itemsToFind.Count());
            var results = new List<T>(items);
            var resultsToFind = new List<T>(itemsToFind);
            for (int i = 0; i < itemsToFind.Count(); i++)
            {
                resultsToFind[i].should_be_equal_to(results[i]);
            }
        }

        public static void should_be_true(this bool item)
        {
            item.should_be_equal_to(true);
        }

        public static void should_be_false(this bool item)
        {
            item.should_be_equal_to(false);
        }

        public static void should_be_equal_to<T>(this T actual, T expected)
        {
            Assert.AreEqual(expected, actual);
        }


        public static ExceptionType should_throw_an<ExceptionType>(this Action workToPerform)
            where ExceptionType : Exception
        {
            Exception resulting_exception = get_exception_from_performing(workToPerform);
            resulting_exception.should_not_be_null();
            resulting_exception.should_be_an_instance_of<ExceptionType>();
            return (ExceptionType) resulting_exception;
        }

        public static void should_not_throw_any_exceptions(this Action workToPerform)
        {
            workToPerform();
        }

        public static void should_be_an_instance_of<Type>(this object item)
        {
            Assert.IsInstanceOfType(typeof (Type), item);
        }

        public static void should_not_be_null(this object item)
        {
            Assert.IsNotNull(item);
        }

        public static void should_not_be_null_or_empty(this string item)
        {
            Assert.IsFalse(string.IsNullOrEmpty(item));
        }

        public static void should_be_null_or_empty(this string item)
        {
            Assert.IsTrue(string.IsNullOrEmpty(item));
        }

        public static void should_be_empty<T>(this IEnumerable<T> items)
        {
            Assert.IsTrue(items.Count() == 0);
        }

        public static void should_not_be_empty<T>(this IEnumerable<T> items)
        {
            Assert.IsFalse(items.Count() == 0);
        }

        private static Exception get_exception_from_performing(Action work)
        {
            try
            {
                work();
                return null;
            }
            catch (Exception e)
            {
                return e;
            }
        }
    }
}
Technorati-Tags: ,,

Es hat mich erwischt, ein neues Design

Es ist Nikolaus 2008 und ich habe mir heute ein neues Design für mein Blog gegönnt.

Gut das war auch nicht schwierig, vorher war ein Design ja auch nicht existent.

Da ich jedoch immer noch Entwickler und kein Designer bin habe ich mich bei www.free-css-templates.com bedient.

Beim Umstellung habe ich dann auch noch einen Syntax-Highlighter eingebaut, so das die Quelltext die nun wieder reichhaltiger gepostet werden auch besser aussehen.

Auch habe ich mich mal um den XHTML Output gekümmert und geschaut das er (soweit es mir möglich war anzupassen) valide ist.

Dies ist also der kleine Relaunch von Der-Albert.com in Zukunft gibt es hier wieder mehr zu lesen. Versprochen!