2009-01-06 11 views
6

Ich versuche, ein neues MVC-Projekt mit Tests zu starten, und ich dachte, der beste Weg zu gehen würde 2 Datenbanken haben. 1 für das Testen gegen und 1 für wenn ich die App starte und benutze es (teste auch wirklich wie es noch keine Produktion ist).ASP.NET MVC TDD mit LINQ und SQL-Datenbank

Für die Test-Datenbank habe ich überlegt, create table scripts zu erstellen und Datenskripte innerhalb der Test-Setup-Methode zu füllen und dann all dies in der Abreißmethode zu löschen.

Ich werde jedoch Linq zu SQL verwenden und ich denke nicht, dass dies mir erlauben wird, dies zu tun?

Muss ich einfach die ADO-Route gehen, wenn ich es so machen möchte? Oder sollte ich einfach ein Mock-Objekt verwenden und Daten als Array oder etwas speichern?

Irgendwelche Tipps zu Best Practices?

Wie ging Jeff dies für StackOveflow?

Antwort

2

Ich habe den Link von Tvanfosson und RikMigrations überprüft und nachdem ich mit ihnen herumgespielt habe, bevorzuge ich die spottende DataContext-Methode am besten. Mir wurde klar, dass ich keine Tabellen erstellen und sie ständig löschen muss.

Nach ein wenig mehr Forschung fand ich Stephen Walther Artikel http://stephenwalther.com/blog/archive/2008/08/17/asp-net-mvc-tip-33-unit-test-linq-to-sql.aspx, die für mich scheint einfacher und zuverlässiger.

Also gehe ich mit dieser Implementierung.

Danke für die Hilfe.

4

Was ich tue, ist eine Schnittstelle für einen DataContext-Wrapper definieren und eine Implementierung des Wrappers für den DataContext verwenden. Dies ermöglicht mir, eine alternative, falsche DataContext-Implementierung in meinen Tests zu verwenden (oder, wenn es einfacher ist, zu verspotten). Dies abstrahiert die Datenbank vollständig aus meinen Unit-Tests. Ich habe einen Startcode unter http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx gefunden, obwohl ich ihn so erweitert habe, dass er die Validierungsimplementierungen für meine Entitätsklassen behandelt.

Ich sollte auch erwähnen, dass ich einen separaten Staging-Server für QA habe, so gibt es Live-Tests des gesamten Systems. Ich benutze nur keine tatsächliche Datenbank in meinem Komponententest.

+0

Ich benutze den gleichen DataContext Mocking-Code und es funktioniert gut –

1

Sie möchten vielleicht einen anderen Weg finden, die Datenbank für Ihre Komponententests tatsächlich zu schlagen, weil es viel mehr Zeit braucht. Haben Sie darüber nachgedacht, Migrations zum Erstellen/Löschen Ihrer Tabellen zu verwenden, statt SQL-Skripte zu verwenden? RikMigrations ist das, was ich verwendet habe, um meine Datenbank zu erstellen, so dass ich einfach meinen gesamten Code an einem Ort revidieren kann. Justin Etheredge hat einen tollen Artikel auf using RikMigrations.

1

ich mit großer Teil der obigen einverstanden sind, in Zusammenhang mit Unit-Tests. Ich denke jedoch, dass es wichtig ist, darauf hinzuweisen, dass die Verwendung von Mock-Repositories und Komponententests nicht die gleiche Teststufe bietet wie ein DB-Integrationstest.

Zum Beispiel haben unsere Datenbanken häufig kaskadierende Löschungen, die direkt in das Schema eingebaut sind. In diesem Fall werden beim Löschen einer primären Entität in einem Aggregat automatisch alle untergeordneten Entitäten gelöscht. Dies gilt jedoch nicht automatisch für ein verspottetes Repository, das nicht von einer physischen Datenbank mit diesen Geschäftsregeln gesichert wurde (es sei denn, Sie haben alle diese Regeln im Mock erstellt). Das ist wichtig, denn wenn jemand vorbeikommt und das Design meines Schemas ändert, brauche ich es, um meine Tests zu unterbrechen, damit ich den Code/das Schema entsprechend anpassen kann. Ich weiß zu schätzen, dass dies Integrationstests und keine Unit-Tests sind, aber ich denke, es war erwähnenswert.

Meine bevorzugte Option besteht darin, eine Master-Design-Datenbank zu erstellen, die Beispieldaten enthält (die gleiche Art von Daten, die Sie in Ihren Mocks erstellen würden). Zu Beginn jedes Testlaufs habe ich ein automatisiertes Skript, das eine Sicherung der MasterDB erstellt und diese in "TestDB" wiederherstellt (was alle meine Tests verwenden). Auf diese Weise verwalte ich ein Repository sauberer Testdaten im Master, das sich bei jedem Testlauf neu erstellt. Meine Tests können mit den Daten experimentieren und alle benötigten Szenarien testen.

Wenn ich die Anwendung debuggen, habe ich ein anderes Skript, das sichert und die Master-DB zu einer DEV-Datenbank wiederherstellt. Ich kann auch hier mit Daten herumspielen, ohne mich um den Verlust meiner Beispieldaten sorgen zu müssen. Normalerweise führe ich dieses bestimmte Skript nicht in jeder Sitzung aus, da die Verzögerung darauf wartet, dass die Datenbank neu erstellt wird. Ich kann es einmal am Tag laufen und dann die App den ganzen Tag über ausprobieren. Wenn ich zum Beispiel alle Datensätze aus einer Tabelle als Teil meines Debugging lösche, würde ich das Skript ausführen, um die DevDB neu zu erstellen, wenn ich fertig bin.

Diese Schritte klingen, als würden sie dem Prozess eine riesige Menge an Zeit hinzufügen, aber tatsächlich - sie tun es nicht. Unsere Anwendung hat derzeit etwa 3500 Tests, von denen etwa 3000 irgendwann auf die DB zugreifen. Die Sicherung und Wiederherstellung der Datenbank dauert normalerweise etwa 10-12 Sekunden zu Beginn jedes Testlaufs. Und da die ganze Testsuite erst nach dem Einchecken von TFS ausgeführt wird, macht es uns nichts aus, wenn wir noch eine Weile warten müssen. An einem durchschnittlichen Tag dauert unsere gesamte Testsuite ungefähr 15-20 Minuten.

Ich schätze und akzeptiere, dass Integrationstests viel langsamer als Komponententests sind (wegen der inhärenten Notwendigkeit, eine echte DB zu verwenden), aber es stellt eher die "echte Welt" -App dar. Zum Beispiel, Mock-Repositorys geben keine DB-Fehlercodes zurück, keine Zeitüberschreitung, sie sperren nicht, sie haben nicht genug Speicherplatz, usw.

Komponententests sind in Ordnung für einfache Berechnungen, grundlegende Geschäftsregeln usw. und sicherlich sind sie absolut die beste Wahl für die meisten Operationen, die keinen Zugriff auf DB (oder andere Ressourcen) beinhalten. Aber ich glaube nicht, dass sie so wertvoll sind wie Integrationstests - die Leute reden viel über Komponententests, aber über Integrationstests wird wenig gesagt.

Ich erwarte, dass diejenigen, die sich leidenschaftlich für Komponententests begeistern, mir dafür Flammen schicken werden. Das ist in Ordnung - ich versuche nur, etwas Gleichgewicht zu schaffen und die Leute daran zu erinnern, dass Projekte, die voll von bestandenen Komponententests sind, immer noch in dem Moment scheitern können, in dem Sie sie im Feld implementieren.

+0

interessant, aber definitiv aus auf einer Tangente .. plus die Buchstaben TFS schickte einen Schauder auf meinem Rücken! – Lloyd