TDD In C Part II

In the previous part we saw how we can create CppUnitLite library for using in other projects and also how we can make our projects to depend on that library and use. Now it’s time for writing a very simple Stack project with TDD approach in C which is a non-OO language(Odd) as a first practice.

Before I start to write about the codes, I just wanna say if the indentation in codes have problems or layout of them is not right it’s because of wordpress problems in handling these kind of stuff in both HTML and Visual style, sorry about that anyway.

I just want to remind the StackMain.cpp file for the project which we wrote in the previous part. This is how your StackMain.cpp file should look like before you write any test:

#include "C:\software\CppUnitLite\om\CppUnitLite\TestHarness.h"
#include
int main()
{
    TestResult tr;
    TestRegistry::runAllTests(tr);
    system("pause");
    return 0;
}

When you compile and run your project you’ll get the the result which says: “There were no test failures” which is obvious cause there are no tests yet.

Ok, now it’s time for writing our first test case for the Stack. We include Stack.h file here(which doesn’t exist yet). At first we want to handle size of the stack, so here’s our first test:

TEST(Stack, sizeShouldBeEmptyAtCreation)
{
    LONGS_EQUAL(0, getSize());
}

In front of TEST keyword we have two arguments. Both of them are names. First is a GroupName which determine the name of a group that our tests belong to(it’s just a name, no confusion) and the second one is the name of test which should be as expressive as possible.

Of course it doesn’t compile because there is no getSize() method in there yet, so we make it compile by adding Stack.h file to the project and write the followings in it:

#ifdef __cplusplus
extern "C"
{
    #endif
    int getSize();
    #ifdef __cplusplus
}
#endif

This block is the magic! Any code which is written in this block should be in C and we can call it from C++ with this trick(extern “C”). After that, we should add Stack.c file to the project and write the followings in it for making the project compile:

#include “Stack.h”
int getSize()
{
    return -1;
}

Now it compiles but sure it will fail because we expect 0 but it’s -1. It’s so easy to make this pass:

int getSize()
{
    return 0;
}

It’s time for the next test case:

TEST(Stack, sizeShouldBeOneAfterOnePush)
{
    push(4);
    LONGS_EQUAL(1, getSize());
}

Ok for making this pass first of all we determine push method in Stack.h and Stack.c files for making it compile and then write enough code to make the test pass so it’ll be like:

static int itsSize = 0;
void push(int element);
int getSize();

And in the Stack.c will have:

void push(int element)
{
    ++itsSize;
}

The interesting point is here. When you run your tests in some platforms(like mine) you’ll get failure message at this point(in others maybe later) and size is not what you expected. Here’s why, your tests run in no predictable order, so you can’t rely on them in this way. Maybe the second test runs first which increase the itsSize variable and then the first one runs which will make failure cause itsSize is not “Zero” at that time!

When you do TDD in a non-OO language like C sometimes you need to handle some concepts of OO programming. For example initialization which handled by Constructors in those languages. At here we need some kind of initialization that set the itsSize variable to Zero anytime we want to use Stack functionality in a context(like our tests here). So we write this function and we call it at the top of each unit test we write:

void initialize();

And in the Stack.c:

void initialize()
{
    itsSize = 0;
}

Now everything is fine and all the tests pass. So we go to the next test case:

TEST(Stack, sizeShouldBeZeroAfterOnePushAndPop)
{
    initialize();
    push(3);
    pop();
    LONGS_EQUAL(0, getSize());
}

We do the following in Stack.h:

void pop();

And then in Stack.c:

void pop()
{
    --itsSize;
}

You think this is stupid, cause we all know that pop method in stack should return an element, so what’s with the void in it’s prototype? I know, but we don’t have a test for this yet so we shouldn’t write production code for that. Remember the Third Rule Of TDD by Robert C.Martin(Uncle Bob): “we should write enough code to make a failing test pass, more than that is just wasting time.” Ok now that everything is fine and all tests pass we should move on and go to the next test case. I think we handle all the scenarios for size of the Stack so here’s our next test case:

TEST(Stack, shouldPopOneAfterPushingOne)
{
    initialize();
    push(1);
    LONGS_EQUAL(1, pop());
}

For making it pass we can do the following:

int pop()
{
    --itsSize;
    return 1;
}

Don’t forget to change the prototype of pop method in the Stack.h file too. Now it passed but it’s hard coded(return1;) we should make it more general according to this rule of TDD by Uncle Bob: “as tests become more specific, code becomes more general.” So here’s the next test:

TEST(Stack, shouldPopTwoAfterPushingTwo)
{
    initialize();
    push(2);
    LONGS_EQUAL(2, pop());
}

We make it pass so easily like this:

static int itsElement;

And then in Stack.c:

void push(int element)
{
    ++itsSize;
    itsElement = element;
}

int pop()
{
    --itsSize;
    return itsElement;
}

Everything is fine now. It’s time for the last test case which make our Stack completely general with all of Stack’s functionality:

TEST(Stack, shouldPopInReverseOrderAfterMultiplePushes)
{
    initialize();
    push(1);
    push(2);
    LONGS_EQUAL(2, pop());
    LONGS_EQUAL(1, pop());
}

For making it pass we’ll do this:

#define MAXSIZE 100
static int itsElements[MAXSIZE];

And then in the Stack.c we’ll make following changes for making the new test pass while keep previous ones passing:

void push(int element)
{
    itsElements[itsSize++] = element;
}

int pop()
{
    return itsElements[--itsSize];
}

At this moment all tests pass without any problem and our Stack has the full functionality of the stack data structure.

One invaluable thing for me about this experience, was when you counter a problem which is odd or strange or it’s odd or strange from your point of view, don’t say NO so quick and don’t give up, try to figure out is there any way for handling that situation or not and then go for it.

That’s almost what I did for this problem and it ended up with learning lots of interesting things. So this was how we can do TDD In C with a very simple Stack example. I hope you enjoyed this series.

“Whatever you are, be a good one.”~Abraham Lincoln

TDD In C Part I

A few days ago one of my friends told me: “do you think we can do TDD in C?” at first I thought this is some kind of stupid cause TDD makes sense for Object Oriented programming and design so for a non-OO language like C it doesn’t make any sense.

One day after that my friend told me again: “I Googled about it a little and found something. Apparently we can do TDD in C”. You know that I’m a TDD geek so it was really interesting topic for me. When I got home I started to search about that issue and found some useful things on the Internet.

We can do TDD in C with “CppUnitLite”. Actually CppUnitLite is written for C++ as you can figure it out from its name. But you all know that we can call C code from C++ with a little trick which we’ll see later in this post series.

Although the first step for doing TDD in C is integrating CppUnitLite with your IDE. I’m using Dev-C++ as an IDE for writing C and C++ codes, so I tried to do this with Dev-C++. After a lot of searching I didn’t find a very useful and simple guide for doing this, so I tried and struggled so much with little things that I found in Internet(sporadic things here and there) and finally did it.

Then I decided to write about it here in the first part of this series, so if there will be someone like me interested in the topic can find useful things for doing this integration in one place in a simple manner.

You can download CppUnitLite here. After you did this for integrating it with your Dev-C++ IDE you can do the following steps:

1. After you extracted the Zip file you downloaded, there are some folders and some files(.h and .cpp files which are for the CppUnitLite test modules that is written in C++).

2. Launch your Dev-C++ IDE and then create a new project from File->New->Project path.

3. Choose static library as the type of your project and name it CppUnitLite:

Static Library Project4. Then add to your project files of CppUnitLite like the below pictures:

Adding CppUnitLite Files To Project

CppUnitLite Files Added To Project5. And finally Compile this project.

Ok first step was completed. You build a library for CppUnitLite on your system. If you go to the path which you saved this project, there’s a file there with name CppUnitLite.a, this is your CppUnitLite library that you can use in other projects for writing tests.

Now we want to write our first C project with TDD approach. Before I start that I should mention that when you download CppUnitLite from ObjectMentor website and extract that Zip file, there’s a sample Stack project which is written in C++ and in OO way that you can use for learning TDD in C++. So I’m gonna write Stack in C and non-OO way(I know it’s weird but it’s just a SAMPLE for showing you guys how we can do TDD in a non-OO language like C).

Ok, launch your Dev-C++ IDE again and create a new project and this time choose Empty Project as your project type and call it Stack. Now we should make this project depends on the library we just created. For doing this right click on your project name(top-left of the IDE, called Stack in the project tab) and choose Project Options, then add your library(CppUnitLite.a) to this project like the following picture:

Adding CppUnitLite Library To The Project

Ok now that this project depends on the CppUnitLite library we can use this library’s modules in our project. So we add to our project the first file and save it as StackMain.cpp. Then type the followings in that file:

#include "..\CppUnitLite\TestHarness.h"
//here is the path of TestHarness.h in your system
#include <stdlib.h>

int main()
{
    TestResult testResult;
    TestRegistry::runAllTests(testResult);
    system("pause");
    return 0;
}

 

 

Ok, now after you compile and run this project you should get the following result:

Result Of Running Tests

Of course there were no test failures cause we didn’t write any test yet but we integrated CppUnitLite to our project and it works like a charm now. It’s completely ready for us to write our tests and code for the Stack project.

This will be the next post in this series…