TDD with GoogleTest and Netbeans

By | February 12, 2016

With googletest set up for use with the the Netbeans IDE it is relatively easy to start working on your code using Test Driven Development Methods. This article shows you how to develop a simple set of library functions using TDD.

A previous post describes how to get the Google Testing Framework set up for use with Netbeans. I like using Netbeans because it offers many of the advantages of Eclipse but in a rather simpler environment. One of the features built into Netbeans is the ability to bhild for, and execute unit tests. My main project can be bilt and run as normal but the Unit testing feature lets me create a kind of sub project that holds the tests. These can be run with a singe button press or keyboard shortcut and give me a list of passing and failing tests.

In this article, I want to create a very simple library of functions that manipulate structures representing rectangles. It has no purpose other than to serve as a way to show some test driven development.

TDD – Test Driven Development

There are a lot of resources and many persuasive videos that will tell you what a great idea TDD is and why you shoul do it. I am going to take that for granted even though there are arguments for and against and concentrate on some basics of the way it can work in practice. I should point out that there are also a lot of resources on how TDD should be done properly and in the context of teams and large projects.

Robert C Martin talks about three rules of TDD in an article from 2005 (http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd):

You are not allowed to write any production code unless it is to make a failing unit test pass.
You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.
You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

These rules are applied in a development cycle with short time frames.

do
Write a (failing) test
Do the least work to make it pass
Refactor if appropriate
while not finished

With these simple guidelines in mind what do I want to achieve?

Problem statement

A largely artificial problem but, suppose I need to store a structure representing a rectangle. The structure definition looks like this:

Part of my library must be able to tell me if two rectangles intersect and to calculate the union of two rectangles.

You can already see some problems I expect but I will deal with those as they arise. It is quite common for problems to not be fully thought through when development begins.

What Kinds of Tests are available?

Before getting to the problem itself, I want to look at how tests are created, what they look like, what kinds of tests can be used and how they are organised.

Googletest provides a large variety of tests but I will use only a couple of common ones. The simplest is a test for equality. An example might look like this:

Yes, it is that simple. If that were the only test in my suite, googletest might generate the following output:

If the test failed – for example

I would expect to see this instead:

The output from googletest tells me the name of the failed test, the source file and line number of the failed test and what the values involved were. With a well written test case, I can easily track down the caused of the error.

For a good description of basic googletest functionality, have a look at this (http://www.ibm.com/developerworks/aix/library/au-googletestingframework.html)

Developing the rectangle library

Where to start? Always a good question. There is a type definition for the rectangle so it is easy enough to declare variables of the right type. Defining the member variables can be done by simple assignment so that probably does not need testing just now. Instead, I will jump right in and write a simple test to get started The goal will be to write the function intersect(TRect A, TRect B) that returns tue is the two rectangles interesect – that is if they overlap at all.

The solution can be approached step by step. First, I will deal only with the left and right edges and see what can be learned from that So, I need a failing test.

Here is the starter test.

I have two rectangles that intersect

The first job is to make the test compile and fail. I need to create a rectangle.h file, a rectangle.c file and include the rectangle.h header in the test code.

That indeed fails and Get the following output from running the test:

Googletest tells me what failed, where the test is in my test suite and how it failed.

Passing the Test

The next task is to write the least possible amount of code to make the test pass. Since I am testin that the left edge of A is to the left of the right edge of B, a simple conditional in the intersects() function will do the trick.

and, when I run the tests again, I get a pass:

Improving the Solution

This is all some way off code for detecting intersections but it is on the way. What if the rectangles are reversed? Now I must be able to detect that the left edge of B might be less than the right edge of A. It is not long before a little mature thought tells me that the code for this could get complicated, needing comparisons of maximum this and minimum that. What becomes apparent is that, for rectangles to intersect, the right edge of one of them must not be to the left of the left edge of the other. So I will test for that.

I move RectB over. It does not intersect but I expect my previous test will still succeed:

That is good and now I have to go and make the smallest change to the function that allows both tests to pass.

Refactoring the Solution

I changed the intersects() function to be:

Now I need to see what happens if the rectangles are reversed. That is B is to the left of A. Th easiest way to test that is to reverse A and B in the test:

That fails so it is back to the code. What is the least I can do to make it pass? This I think:

Success! The code can now detect any case where the left and right edges do not overlap and so the rectangles cannot intersect. Notice that the function exits as soon as it is possible to know that there is no intersection and so it is relatively efficient. There is no need to sort edges or find maxima and minima.

Completing the Solution

I can follow the same process with the Y axis, create a test for each case, and add the code to make it pass. For brevity here, I have done that. and I end up with the following code for intersects():

and two more tests:

When is it Finished?

A reasonable question at this point is “Am I done?”. Are the tests exhaustive? That is are the complete and sufficient? That can be a bit difficult to answer. Perhaps a few more tests to check a number of intersection cases.

I am interested in one rectangle enclosing hte other and coincident rectangles. These tests break the rules in the sense that they do not fail. That may be an indication that the problem is solved and no further works needs to be done. I can think of some more tests and an implicit error in my test names but I leave that as an exercise for the reader.

What Next?

The method for detecting rectangle intersection used here is far from original but it is efficient technique that is faster than some other solutions. The method of development may have led more directly to this solution than others since it required the least amount of code at each step. Normally, there would be some review and refactoring going on but in this case, I am happy with what I have.

If any refactoring were to be done, there is a set of eight tests that would all have to pass before such a refactoring could be considered successful.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.