Light-Weight Introduction To Test-Driven DevelopmentAuthor: Manfred Lange I am an average engineer. I'm not a genius. So when starting with a new topic I need an simple introduction and a good enough justification for trying the new topic out, be it a new technology, a new tool, whatever. Fortunately I had one of the best teachers on the subject for getting introduced to test-driven development (TDD), Kent Beck. Many years ago he introduced me to what TDD really is about. What TDD is notLet's first discuss what TDD is not. TDD does not mean test-first. Just because one writes the test first is he/she doing test-driven development. TDD is more than that. Just writing the test, and then making the test pass, is not enough. Frankly, you would loose most of the benefits of the approach. Also, TDD cycles are not measured in hours or days, but in seconds and minutes. If you write a test and then spend an hour on making it pass, most likely you are trying to take too large a bite. Driving Your ImplementationAs the name already suggest: You use tests to drive your development efforts. And this is not a one-way street. But let's take one step at a time. Let's assume that you want to implement a stack class. Nothing exciting and most likely you would use one from a library anyways. Please stick with me as I am using this simple example for illustration purposes only. Stack Class as ExampleSo what do we want our stack class do? Here is a short list of features we would like it to have:
For those who are already familiar with generics: We will implement the stack for integers only for simplicity reasons. So let's look at the above list. Let's start with the IsEmpty property. If we create a new stack object it should return the value true. So here is how it is expressed in C#: 1: [TestFixture] 2: public class StackTests { 3: [Test] 4: public void NewStackIsEmpty() { 5: Stack stack = new Stack(); 6: Assert.True(stack.IsEmpty); 7: } 8: } If you are not familiar with C# don't worry. I'll explain the key items as we go. In the above code snippet we have defined a class with the name StackTests. I have chosen this name to indicate that I place all tests for the Stack class here. That's the coding convention I use. You are certainly free to choose your own. A class definition is delimited with curly braces. C# uses an approach that is similar to C++ and Java, both of which delimit code blocks with curly braces as well. (Note: To keep it simple I'm not precise with the terminology here. The grammar for all these languages may use the terms in slightly different ways.) Lines 1 and 3 contain attributes. You can apply attributes to many different code elements in C# (and other .NET languages). Java uses the term annotations. In this code example the attribute TestFixture was used to mark the class StackTests as a class that contains tests. The attribute Test is used to mark the method NewStackIsEmpty() as a test. Lines 3 to 7 define a method. The keyword public indicates that the method is visible to all code that has visibility to the class StackTests as well. The keyword void indicates that the method does not return a value. Each statement is delimited by a semicolon. Please note that I have chose to use each line for a single statement only. Again, this is my choice and I suggest you experiment to find out what works best for you. In line 5 a variable of type Stack is declared. It has the name stack (lower case, so it is different from the class name). Also in line 4 a new instance of a stack is created by using the keyword new and calling a constructor which in this case doesn't take any parameters. In other words: Once the line has been executed the variable named stack (lower case!) contains a reference to a stack object. In line 6 you see the invocation of a class method (Assert.True()). A class method is a method that does not require an instance of that class to be created. A different term for class method is static method. The class's name is Assert and contains a large number of assertion methods that help implementing tests. In this particular case I want to check whether the IsEmpty property for a newly created stack object returns true. In C# a property can be accessed by simply writing the variable name - here "stack" -, then the dot, and then the property name - in the example "IsEmpty". When I run the compiler against this piece of code, it will complain that it doesn't know anything about a class Stack. Basically I'm using the compiler as the advisor at this stage. That is certainly a very simplistic perspective, but it's good enough to start making the point. It is easy to create a simple Stack class: 1: public class Stack { 2: } You may ask: Why don't I implement the IsEmpty property as well? To make the point, I do just as much as I absolutely have to do to keep going. The compiler was only complaining about the class. Let's try to compile again. This time the compiler finds the Stack class. On the other hand it now complains about the missing IsEmpty property. Let's add a simple version: 1: public class Stack { 2: public bool IsEmpty { 3: get { 4: return true; 5: } 6: } 7: } C# uses a dedicated syntax to implement properties. (Java has the get_*/set_* convention instead for bean properties.) In this case there is no setter, although one might argue that maybe the setter could be the replacement for the Clear() method in our feature list. Personally, I prefer a clearer approach and so we keep the feature list as is. The property looks as if it is hard coded and indeed it is. But still, I try to get away with the simplest thing that could possibly work. Let's try to compile. This time the build succeeds. And even better. When I run the test, it passes. But have we actually finished testing IsEmpty? Not really, as we need to test that it returns false if we have added an element to the stack. But the class doesn't have yet a method for adding a element to the stack. I decide to just add a new item to my work list. Here is the updated work list including the additional test but also crossed out the feature we have implemented:
|
Sponsors:
|
||||||
Copyright © 2002-2008 by Agile Utilities NZ Ltd. All rights reserved. Site design by Andreas Weiss. This site is protected by bot traps. |