Ich kann Dir nur sagen, dass man nicht genug testen kann. Man sollte aber immer den Nutzen/Aufwand im Auge behalten.
Ich erstelle immer verschiedene Layer für meine Programme. Jeder Layer hat dann seine eigenen Testroutinen. Wo Du anfängst hängt davon ab, ob Du zuerst unten - also die Datenbankebene oder oben im Browser anfängst.
Ich selbst baue mir zuerst immer mein Datenmodel auf. Also die Objekte, die im Spiel zu verwalten sind. Dannach ist die Datenbank und der Aufbau der einzelnen Tabellen dran. Anders als im klassischen TDD fange ich erst dann an meine ersten Tests zu schreiben.
Meinst teste ich sowohl die DAL als auch die Datenbank selbst parallel. Wenn Dir VS Team Suite zur Verfügung steht hast Du dafür schon die best mögliche Ausgangslage. Mit VS TS kann man schliesslich auch die Datenbank selbst testen. Es gibt dafür z.B. den SQL Server 2008 Wizard. Mit diesem Projekt liest Du zerst das Datenbankschema einer vorher von Hand erstellten Datenbank aus und erzeugst ein Datenbank-Schema. Das ist doppelt hilfreich: beim Testen und beim späteren Deployment.
Mit VS kannst Du dann auch verschiedene Data Generation Pläne erstellen. Dabei werden beliebig viele Beispieldaten erstellt. Da das DB-Schema bekannt ist können hier auch Relationen zwischen verschiedenen Tabellen berücksichtigt werden.
Für einen Test gegen die Datenbank selbst kannst Du dann T-SQL verwenden, um bspw. Stored Procedures zu testen. Oder aber bei Unit Tests diese Werte aus der Datenbank auslesen und überprüfen, ob Werte gelesen und/oder verändert werden.
Für die DAL kann ich nur das Repository Pattern empfehlen. Hier teste ich dann zwei Dinge.
1. Schreibe ich mit einen TestRepository das ich später auch für die Tests der eigentlichen Funktionen (z.B. BaueGebäude) verwenden kann. Dies hat den Vorteil, dass ich unabhängig von der Datenbank bin, die Test wesentlich schneller ausgeführt werden können und die Datenbasis vorhersagbar ist. Allerdings empfiehlt es sich auch zu testen, ob die TestRepositories sich überhaupt so verhalten wie gedacht.
2. Anschliessend folgenden Integration Tests. Anders als die Units Tests, die sehr schnell ablaufen und die ich bspw. während der Entwicklung immer wieder durchführe, sind die Integration Test sehr langsam, da sie mit einer echten Datenbank arbeiten. Hier verwende ich die selben Testmethoden wie bei den Unit Tests und tausche nur die Repositories gegen echte Repositories aus, die entweder gegen die oben erzeugte Testdatenbank und deren Dummy-Daten laufen oder gegen eine Datenbank mit "echten" Daten.
Nachteil hierbei ist aber auch, dass die Datenbank dann immer wieder neu aufgebaut werden muss. Also eigentlich vor jeder Testmethode die Datenbank leeren und mit neuen Testdaten füllen. Hier bietet VS wirklich gute Dienste, nichtsdestotrotz dauert dies eben sein Zeit, weshalb die Tests dann auch länger laufen.
Durch die Aufteilung entweder in verschiedene Test-Projekte oder in verschiedene Testfälle (aka Test Lists) kann ich dann während der Entwicklung bspw. nur meine schnellen Unit Tests aufrufen und dann in unregelmässigeren Abständen oder beim Check-In meine langsamen Integration Tests.
Anschliessend baue ich Service Klassen, die dann wahlweise meine verschiedenen Repositories verwenden. Durch diese trennung kann ich dann die Logik aber sehr schön unabhängig von der Datenbasis testen.
Für einfache Tests, wie bspw. die Überprüfung der Funktion "IstEmailSyntaktischKorrekt" bietet VS zusätzlich nach die Möglichkeit einen Test mit verschiedenen Testdaten durchzuführen. Also anstelle mehrere Test zu schreiben, die verschiedene mögliche Emailadressen überprüft, kann man der Testmethode hier bspw eine CSV Datei mit verschiedenen Emailadressen übergeben (Dies geht jedoch nur mit VS Team Suite oder VS Test Edition)
Vor VS 2008 hatte ich immer nUnit verwendet, mit den neuen Funktionen und der wirklich guten Integration von VS 2008 habe ich allerdings viel mehr Möglichkeiten. So kann ich Datenbank, Web Oberfläche und Performance testen, was ich sonst nur mit verschiedenen anderen Test bibliotheken erreichen würde.
Es gibt aber keine vernünftige Aussage dafür wieviele Tests man schreiben sollte. Auch die Aussage, "Je mehr desto besser", stimmt nur zur Hälfte. Ich hatte auch Projekte in denen wir uns dann später nur noch um die Tests gekümmert haben und Angst davor hatten Änderungen an bestehenden Funktionen durchzuführen, da dies eine ganze Reihe von Tests brechen würde. (Ein sicherer Hinweis dafür, dass die Tests selbst nicht sehr sinnvoll sind)
Ich selbst fange immer nur mit einen einfachen Satz an Tests an. Bspw. ein Test pro öffentliche Funktion oder Methode in den Layern. Nur an kritischen Stellen, also sicherheitsrelevante oder komplexe Funktionen, schreibe ich mehr als einen Tests, eventuell sogar ein paar negativ Tests, um bspw. sicherzustellen, dass ein Login mit falschen Passwort nicht funktioniert.
Die meisten Tests kommen aber erst später im Verlauf des Projekts. Dann nämlich, sobald ich irgendwo ein Problem oder einen Bug. Dann schreibe ich einen Test, der genau diesen Bug nachstellt. Dieser Test sollte dann Rot sein (also der Test scheitern), da das Ergebnis ja nicht das ist, was ich eigentlich erwartet hatte. Anschliessend korregiere ich den Bug und überprüfe, ob mein Test nun endlich auf Grün steht.
Wichtig: Durch das Schreiben von Tests verhindert man nicht automatisch Fehler im Code. Der wirkliche Nutzen besteht meiner Meinung nach darin, dass man dann später überhaupt noch in der Lage ist, Änderungen (Fehlerbehebungen, Erweiterungen) vorzunehmen. Ohne Tests passierte mir das immer wieder. Ich schreibe ein Programm, es funktioniert und ich veröffentliche es. Monate (Jahre?) später kommt es dann zu einem Fehler oder es soll eine kleine Änderung vorgenommen werden. Entweder kann ich mich dann noch an alle Zeilen meiner Arbeit erinnern, oder ich habe ziemliches Gottvertrauen in meine Fähigkeiten alle Abhängigkeiten dann noch überschauen zu können. Auch beim Arbeiten im Team sind Tests fast schon überlebenswichtig. Wie oft habe ich mich davor schon darüber gewundert, das mein Code plötzlich nicht mehr funktionierte, nur weil jemand anderes eine Basisfunktion geändert hat oder einen Paramter umbenannt hat. Hier erst einmal die Fehlerquelle zu finden ist oft recht mühselig. Hier könnte ein Test schon beim Einchecken anzeigen, dass der neue Code Probleme verursacht. Existiert für diesen Fehlerfall noch kein Test, dann spätestens nachdem ich das Problem lokalisiert und behoben habe.
Ich hoffe, dass hilft Dir