| Wir beginnen mit unserem Test. Hierzu editieren wir die bereits angelegte Testklasse. Eine Testklasse testet immer genau eine reale Klasse. Die Testklasse sollte - verkürzt - wie folgt aussehen: using TDD_Demo;
namespace TestProject
{
[TestClass]
public class StackTest
{
private IStack<int> stack;
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
[TestInitialize()]
public void MyTestInitialize() {
stack = new MyStack<int>();
}
}
} Listing 1: TestProject-Standardcode Methoden, welche mit [TestInitialize()] gekennzeichnet werden, werden vor jedem Test ausgeführt. Da die Reihenfolge von Tests nicht vorgegeben ist, dürfen sich die Tests nicht gegenseitig manipulieren. Jeder Test soll die identische Umgebung vorfinden. Aus diesem Grund wird das Stack-Objekt jedes Mal neu initialisiert. Wir verwenden hier die Klassen MyStack und IStack. Zunächst legen wir die beiden also in unserem eigentlichen Projekt (TDD_Test) an und lassen MyStack von IStack erben: namespace TDD_Demo
{
public interface IStack<T>
{
}
}
namespace TDD_Demo
{
public class MyStack<T> : IStack<T>
{
}
} Listing 2: Grundgerüst des Stacks Zeit für unseren ersten Test, den wir gleich unter MyTestInitialize erstellen: [TestMethod]
public void testSize()
{
stack.Push(1);
int expected = 1;
int actual = stack.Size;
Assert.AreEqual(expected, actual);
} Listing 3: Funktion testSize() Zunächst gilt es, erst einmal die Compilerfehler zu beseitigen. Dafür erstellen wir im Interface eine Methode void Push(T item); und die Property int Size { get; }. Die Implementierung in MyStack sollte dabei zunächst so einfach wie möglich sein: public void Push(T item)
{
}
public int Size
{
get { return 0; }
} Listing 4: Basisfunktionalität des Stacks Phase 1: make it red Wenn wir den Test nun ausführen, schlägt er fehl. Dieser Schritt ist zwingend. Warum? Zum Einen ist es eine gute Prüfung, ob der Test überhaupt ausgeführt wird. Zum anderen soll jeder Test etwas neues in die Implementierung bringen. Ist der Test also bereits jetzt grün, müssen wir überlegen, warum dies der Fall ist. Schreiben wir gerade wirklich etwas, was es noch nicht gibt? Es funktioniert doch bereits... Meistens ist ein Test schon rot, sobald man die nötigen Methoden erstellt hat. Sie machen ja noch nichts. Phase 2: make it green Jetzt geht es darum, den Test grün zu bekommen. Dieser Schritt ist gerade am Anfang schwierig, weil die für das endgültige Ziel naheliegendste Lösung nicht immer die gewünschte ist. Es wird stets die einfachste Lösung gesucht. Diese lautet in unserem Fall: public int Size
{
get { return 1; }
} Listing 5: Funktion Size() zum Ersten Warum geben wir uns damit zufrieden? Die Antwort ist leicht: wir wollen eine hohe Testabdeckung. Würden wir hier mehr implementieren, als nötig, wäre dies nicht getestet. Damit wäre es später jedoch schwierig, Fehler zu finden. Phase 3: make it nice Im Normalfall wäre jetzt ein Refactoring fällig. Es ist allerdings noch nicht genug passiert, als dass wir hier etwas refactorn könnten. Wir kommen in ein paar Zyklen wieder auf diesen Schritt zurück. |