SharePoint Test-Isolation: Daten

16. August 2012Malte Clasen

Automatisierte Tests in SharePoint lassen sich am einfachsten über direkte Zugriffe auf das Objektmodell aufbauen, wie ich es im vorherigen Artikel bereits demonstriert habe. Die Idee dahinter ist, dass Datenstrukturen nicht deklarativ, sondern programmatisch inkrementell in ChangeSets aufbaut werden. So erhält man nicht nur mehr Update-Möglichkeiten, sondern auch direkt die Grundlage für automatisierte Tests, die ohne WSP-Deployments auskommen.

Tests sind nur dann wertvoll, wenn sie reproduzierbar sind, d. h. wenn zwei Testläufe immer dasselbe Ergebnis liefern, sofern man nicht zwischendurch den Programmcode geändert hat. Bei SharePoint trifft man an dieser Stelle schnell auf ein Hindernis: Jeder Test gegen das Objektmodell kann Änderungen vornehmen, die für nachfolgende Testläufe sichtbar sind. Das betrifft zum einen die geschriebenen Testdaten, aber auch die erzeugten Datenstrukturen selbst.

Eine gängige Möglichkeit, diese Kontextabhängigkeit zu vermeiden, ist Mocking. Dabei werden die problematischen Klassen durch Platzhalter, die äquivalentes Verhalten vortäuschen,, ersetzt. Für Unit-Tests ist das eine durchaus adäquate Vorgehensweise. Bei der SharePoint-Entwicklung ist aber oft die Integration mit dem SharePoint-Objektmodell kritischer als die darauf aufbauende Business-Logik, falls solch eine überhaupt existiert. Werden die eigenen Komponenten unabhängig von SharePoint getestet, treten zur Laufzeit oft unerwartete Probleme auf, wenn man beim Mocking nicht alle Feinheiten des Objektmodells berücksichtigt hat. So kann man beispielsweise bei einem SPWeb-Objekt beobachten, dass die Liste der zur Verfügung stehenden Feldtypen nicht dynamisch aktualisiert wird. Instanziiert man ein SPWeb und legt danach einen neuen benutzerdefinierten Feldtypen an, kann man diesen nicht in der bestehenden Instanz zum Anlegen einer neuen Spalte verwenden. Neben den Cache-Effekten können auch unerwartete Abhängigkeiten beobachtet werden: SPWeb.EnsureUser() greift für Forms-basierte Authentifizierung auf System.Web.Security.Roles.Providers zu, was wiederum versucht, die web.config zu lesen (http://blog.mastykarz.nl/inconvenient-programmatically-sharepoint-users-spweb-ensureuser/). Das funktioniert zwar im Kontext einer Web-Anwendung, nicht aber für SharePoint-Konsolenanwendungen. Daher ist es hilfreich, auch Integration-Tests gegen das Objektmodell durchzuführen.

Das Problem ist, die Tests so weit voneinander zu isolieren, dass sie sich nicht gegenseitig beeinflussen. Wenn wir erneut einen Blick in Richtung SQL werfen, fällt auf, dass dort im Allgemeinen mit Transaktionen gearbeitet wird, die nach einem Testlauf via Rollback alle Änderungen zurückziehen. In SharePoint gibt es leider keinen vergleichbaren Mechanismus. Eine weitere Inspirationsquelle bieten Unit-Tests: Hier werden alle Strukturen im Arbeitsspeicher erzeugt und zwar für jeden Testlauf erneut. Nach Abschluss kümmert sich der Garbage Collector der Laufzeitumgebung darum, die nicht mehr benötigten Daten zu entfernen. Eine vergleichbare Herangehensweise ist auch in SharePoint möglich: Wenn für jeden Testlauf eine eigene SiteCollection erzeugt wird, können die Tests auf dieser unabhängig voneinander Listen, Spalten, etc. anlegen. Eine noch weitergehende Isolation wäre bei eigenen WebApplications oder gar eigenen Farmen pro Test möglich. Dies ist aber aus Zeitgründen nur in Ausnahmefällen möglich: Das Erzeugen einer SiteCollection ist um Größenordnungen schneller als das Erzeugen einer WebApplication, ganz zu schweigen von einer neuen Farm.

Eine weitere Größenordnung gewinnt man, wenn die SiteCollections schon im Vorfeld anlegt werden. Über einen Windows-Service können Sie immer ein paar Dutzend SiteCollections vorrätig halten. Der Testlauf schaut dann, ob eine unbenutzte Test-SiteCollection bereit steht oder ob eine neue erzeugt werden soll (Listing 1).

Listing 1


Die Bestimmung, ob eine SiteCollection unbenutzt ist, ist nicht ganz trivial, da SharePoint bei Zugriffen auf gerade in Erstellung oder Löschung befindliche SiteCollections gern Exceptions wirft (Listing 2).

Listing 2

}

Verwendete, aber durch Testabbrüche nicht gelöschte, SiteCollections kann der Windows-Service nach einer vernünftigen Zeitspanne löschen, er fungiert also als Garbage Collector (Listing 3).

Listing 3

}

In der Praxis kann der Overhead für einen derart isolierten Test auf gut 300 ms gesenkt werden. Das ist immer noch viel im Vergleich zu Unit-Tests, aber dennoch so wenig, dass sie auch für das Test-Driven-Development in Frage kommen.

Haben Sie Fragen zu automatisierten Tests in SharePoint oder zu bestimmten Komponenten? Gerne möchte ich mich mit Ihnen zu Erfahrungen in diesem Bereich austauschen. Ich freue mich auf Ihre Kommentare.

Unter folgendem Link finden Sie Verweise auf darauf aufbauende Konzepte: http://malteclasen.de/blog/.

Interessieren Sie sich für weitere SharePoint-Themen und Leistungen? Im Microsoft-Bereich auf unserer Unternehmenswebsite erhalten Sie weiterführende Informationen.

Malte Clasen Malte Clasen ist promovierter Software-Ingenieur und seit über 10 Jahren als Entwickler tätig. Bei adesso arbeitet er als Senior Software Engineer. Sein Schwerpunkt liegt auf agiler Software-Entwicklung mit .NET.
Artikel bewerten:
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...

Kommentar hinzufügen:

Ihr Kommentar: