Silverlight 1.1 bietet ein .NET Runtime so dass man in seiner gewohnten Programmiersprache entwickeln kann, für mich ist das C#. Ein weiteres liebgewordenes “Werkzeug” sind für mich Unit Tests. Ich will daher der Frage nachgehen, wie man Unit Tests realisieren kann für Code der unter Silverlight läuft. Das Beispiel habe ich mit VS2008 RTM und Silverlight 1.1 Tools Alpha erstellt.
Erste Voraussetzung dazu ist ein Unit Test Framework welches gegen die Silverlight Assemblies compiliert ist. Damit der Versuch nicht zu aufwendig wird habe ich dazu NUnitLite im Quelltext verwendet. Ferner bietet sich NUnitLite auch deshalb an da es explizit für Plattformen mit reduziertem Funktionsumfang konzipiert wurde.
Nach Download und Entpacken der NUnitLite Quellen habe ich mit VS2008 eine neue Solution mit einem Silverlight Projekt erstellt.
Die Datei ‘Class1.cs’ habe ich anschließend entfernt und die NUnitLite Dateien in das Projekt übernommen. Dies geht recht einfach wenn man das Projekt NUnitLite.csproj in die Solution mit aufnimmt (VS2008 konvertiert das Projekt von VS2005 nach VS2008) und dann die benötigten Dateien und Verzeichnisse im Solution Explorer in das Silverlight Projekt kopiert.
Nachdem man die NUnitLite Dateien in das Silverlight Projekt kopiert hat kann man das NUnitLite Projekt wieder aus der Solution entfernen. Ferner muss man die Datei AssemblyInfo.cs im Properties Ordner des Silverlight Projektes entfernen da sie sonst doppelt vorliegt.
Einem erfolgreichen Build steht nun (fast) nichts mehr im Weg. Folgende Änderungen sind am Quellcode vorzunehmen:
- In der Datei Assert.cs muss das verwendete EditorBrowsable Attribut auskommentiert werden.
- In der Datei CommandLineOptions.cs muss GetEntryAssembly durch GetCallingAssembly ersetzt werden.
- In der Datei DebugWriter muss Debug.Write durch Debug.WriteLine ersetzt werden.
Ergebnis: NUnitLiteSilver.dll.
Diese können wir im folgenden in einem Unit Test Projekt verwenden. Dazu erstellen wir ein neues Silverlight Class Library Projekt. Anschließend fügen wir diesem Projekt eine Referenz auf das NUnitLiteSilver Pojekt hinzu (oder eine Referenz auf NUnitLiteSilver.dll). Dann ergänzen wir noch ein paar Tests:
using NUnit.Framework;
namespace SomeTests
{
[TestFixture]
public class ExampleTestFixture
{
[Test]
public void ThisTestIsOk() {
Assert.That(5, Is.EqualTo(5));
}
[Test]
public void ThisTestFails() {
Assert.Fail("error!");
}
}
}
Was jetzt noch fehlt ist ein TestRunner. Silverlight bietet out of the box keine Konsolenanwendung, daher basteln wir uns einen ganz simplen Testrunner wie folgt: wir ergänzen ein weiteres Silverlight Projekt, diesmal vom Typ ‘Silverlight Project’, mit dem Namen NUnitLiteSilverRunner. Auch in dieses Projekt ergänzen wir eine Referenz auf NUnitLiteSilver.dll oder das zugehörige Projekt.
In der Datei Page.xaml ergänzen wir einen TextBlock in den wir die Ergebnisse des TestRunners schreiben:
<Canvas x:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="NUnitLiteSilverRunner.Page;assembly=ClientBin/NUnitLiteSilverRunner.dll"
Width="640"
Height="480"
Background="White"
>
<TextBlock x:Name="results" Height="480" Width="640" />
</Canvas>
NUnitLite bringt einen TextUI TestRunner mit, der einen TextWriter als Parameter erwartet. Um in den TextBlock zu schreiben erstellen wir daher einen TextBlockTextWriter:
using System;
using System.IO;
using System.Windows.Controls;
namespace SilverlightTestRunner
{
public class TextBlockWriter : TextWriter
{
private readonly TextBlock textBlox;
public TextBlockWriter(TextBlock textBlox) {
this.textBlox = textBlox;
}
public override void Write(char value) {
textBlox.Text += value;
}
public override void Write(string value) {
textBlox.Text += value;
}
public override void WriteLine(string value) {
textBlox.Text += value + Environment.NewLine;
}
public override System.Text.Encoding Encoding {
get { return System.Text.Encoding.Default; }
}
}
}
Anschließend ergänzen wir die Codebehind Datei Page.xaml.cs wie folgt:
using System;
using System.Windows.Controls;
using NUnitLite.Runner;
using SilverlightTestRunner;
namespace NUnitLiteSilverRunner
{
public partial class Page : Canvas
{
public void Page_Loaded(object o, EventArgs e) {
InitializeComponent();
try {
TextUI testRunner = new TextUI(new TextBlockWriter(results));
testRunner.Execute(new string[] { "SomeTests, Version=1.0.0.0" });
}
catch (Exception e1) {
results.Text += e1.Message;
}
}
}
}
Nun können wir das Projekt NUnitLiteSilverRunner als Startprojekt festlegen und mit F5 die Ausführung beginnen. Ergebnis: System.Reflection.Assembly.GetName() schmeißt eine Exception.

Ich habe kurzerhand überall den Aufruf Assembly.GetName() durch Assembly.Fullname ersetzt. In der Methode TextUI.WriteCopyright() habe ich die Zeilen die die Version der Assembly ermitteln und ausgeben auskommentiert. Was man tun muss damit Assembly.GetName() unter Silverlight ausgeführt wird bleibt noch zu klären.
Ergebnis? Trommelwirbel…… Die Tests werden ausgeführt