I am doing my first steps with TDD. The problem is (as probably with everyone starting with TDD), I never know very well what kind of unit tests to do when I start working in my projects.
Let's assume I want to write a Stack class with the following methods(I choose it as it's an easy example):
Stack<T>
- Push(element : T)
- Pop() : T
- Peek() : T
- Count : int
- IsEmpty : boolean
How would you approch this? I never understood if the idea is to test a few corner cases for each method of the Stack class or start by doing a few "use cases" with the class, like adding 10 elements and removing them. What is the idea? To make code that uses the Stack as close as possible to what I'll use in my real code? Or just make simple "add one element" unit tests where I test if IsEmpty and Count were changed by adding that element?
How am I supposed to start with this?
Here's my rough tests' implementation:
[TestMethod]
public void PushTests() {
StackZ<string> stackz = new StackZ<string>();
for (int i = 0; i < 5; ++i) {
int oldSize = stackz.Size;
stackz.Push(i.ToString());
int newSize = stackz.Size;
Assert.AreEqual(oldSize + 1, newSize);
Assert.IsFalse(stackz.IsEmpty);
}
}
[TestMethod, ExpectedException(typeof(InvalidOperationException))]
public void PeekTestsWhenEmpty() {
StackZ<double> stackz = new StackZ<double>();
stackz.Peek();
}
[TestMethod]
public void PeekTestsWhenNotEmpty() {
StackZ<int> stackz = new StackZ<int>();
stackz.Push(5);
int firstPeekValue = stackz.Peek();
for (int i = 0; i < 5; ++i) {
Assert.AreEqual(stackz.Peek(), firstPeekValue);
}
}
[TestMethod, ExpectedException(typeof(InvalidOperationException))]
public void PopTestsWhenEmpty() {
StackZ<float> stackz = new StackZ<float>();
stackz.Pop();
}
[TestMethod]
public void PopTestsWhenNotEmpty() {
StackZ<int> stackz = new StackZ<int>();
for (int i = 0; i < 5; ++i) {
stackz.Push(i);
}
for (int i = 4; i >= 0; ++i) {
int oldSize = stackz.Size;
int popValue = stackz.Pop();
Assert.AreEqual(popValue, i);
int newSize = stackz.Size;
Assert.AreEqual(oldSize, newSize + 1);
}
Assert.IsTrue(stackz.IsEmpty);
}
Any corrections/ideas about it? Thanks
“Test-driven development” refers to a style of programming in which three activities are tightly interwoven: coding, testing (in the form of writing unit tests) and design (in the form of refactoring).
Red, Green and Refactor is the three phase of Test Driven Development and this the sequence that get followed while writing code. When followed, this order of steps helps ensure that you have tests for the code you are writing and you are writing only the code that you have to test for.
Fewer bugs and errors are the primary benefit of the TDD approach. When the code has fewer bugs, you'll spend less time fixing them than other programming methodologies. TDD produces a higher overall test coverage and, therefore to a better quality of the final product.
Start by testing the basic principles of your API.
Test on zero elements.
Test on one element:
Test on >1 elements:
Each of these would be at least one test case.
For example (roughly outlined in Google's unit test framework for c++):
TEST(StackTest, TestEmpty) {
Stack s;
EXPECT_TRUE(s.empty());
s.push(1);
EXPECT_FALSE(s.empty());
s.pop();
EXPECT_TRUE(s.empty());
}
TEST(StackTest, TestCount) {
Stack s;
EXPECT_EQ(0, s.count());
s.push(1);
EXPECT_EQ(1, s.count());
s.push(2);
EXPECT_EQ(2, s.count());
s.pop();
EXPECT_EQ(1, s.count());
s.pop();
EXPECT_EQ(0, s.count());
}
TEST(StackTest, TestOneElement) {
Stack s;
s.push(1);
EXPECT_EQ(1, s.pop());
}
TEST(StackTest, TestTwoElementsAreLifo) {
Stack s;
s.push(1);
s.push(2);
EXPECT_EQ(2, s.pop());
EXPECT_EQ(1, s.pop());
}
TEST(StackTest, TestEmptyPop) {
Stack s;
EXPECT_EQ(NULL, s.pop());
}
TEST(StackTest, TestEmptyOnEmptyPop) {
Stack s;
EXPECT_TRUE(s.empty());
s.pop();
EXPECT_TRUE(s.empty());
}
TEST(StackTest, TestCountOnEmptyPop) {
Stack s;
EXPECT_EQ(0, s.count());
s.pop();
EXPECT_EQ(0, s.count());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With