Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm going to be giving a talk to my department next week about unit testing and test-driven development. As part of this, I'm going to show some real-world examples from some code I've written recently, but I'd also like to show some very simple examples that I'll write in the talk.

I've been searching on the web for good examples, but I've been struggling to find any that are particularly applicable to our area of development. Almost all of the software we write is deeply-embedded control systems running on small microcontrollers. There's a lot of C code that is easily applicable to unit testing (I'll be talking about unit testing on the PC rather than on the target itself) as long as you stay clear of the 'bottom' layer: the stuff that talks directly to the microcontroller peripherals. However, most examples I've found tend to be based on string-processing (e.g. the excellent Dive Into Python Roman numerals example) and since we hardly ever use strings this isn't really suitable (about the only library functions our code typically uses are memcpy, memcmp and memset, so something based on strcat or regular expressions isn't quite right).

So, on to the question: please can anyone offer some good examples of functions that I can use to demonstrate unit testing in a live session? A good answer in my (subject to change) opinion would probably be:

  • A function that is simple enough that anyone (even those who only write code occasionally) can understand;
  • A function that doesn't appear pointless (i.e. working out the parity or CRC is probably better than a function that multiplies two numbers together and adds a random constant);
  • A function that is short enough to write in front of a room of people (I may take advantage of Vim's many clipboards to reduce errors...);
  • A function that takes numbers, arrays, pointers or structures as parameters and returns something similar, rather than handling strings;
  • A function that has a simple error (e.g. > rather than >=) that's easy to put in that would still work in most cases but would break with some particular edge case: easy to identify and fix with a unit test.

Any thoughts?

Although it's probably not relevant, the tests themselves will probably be written in C++ using the Google Test Framework: all our headers already have the #ifdef __cplusplus extern "C" { wrapper around them; this has worked well with the tests I've done so far.

share|improve this question

closed as off-topic by Thomas Owens Sep 6 '13 at 11:42

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions asking us to recommend a tool, library or favorite off-site resource are off-topic for Programmers as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it." – Thomas Owens
If this question can be reworded to fit the rules in the help center, please edit the question.

add comment

3 Answers

up vote 8 down vote accepted
+50

Here's a simple function that's supposed to generate a checksum over len bytes.

int checksum(void *p, int len)
{
    int accum = 0;
    unsigned char* pp = (unsigned char*)p;
    int i;
    for (i = 0; i <= len; i++)
    {
        accum += *pp++;
    }
    return accum;
}

It has a fencepost bug: in the for statement, the test should be i < len.

What's fun is, if you apply it to a text string like this...

char *myString = "foo";
int testval = checksum(myString, strlen(myString));

you'll get the "right answer"! That's because the extra byte that was checksummed was the zero string terminator. So you can wind up putting this checksum function into code, and maybe even shipping with it, and never notice a problem - that is, until you start applying it to something other than text strings.

Here's a simple unit test that will flag this bug (most of the time... :-)

void main()
{
    // Seed the random number generator
    srand(time(NULL));

    // Fill an array with junk bytes
    char buf[1024];
    int i;
    for (i = 0; i < 1024; i++)
    {
        buf[i] = (char)rand();
    }

    // Put the numbers 0-9 in the first ten bytes
    for (i = 0; i <= 9; i++)
    {
        buf[i] = i;
    }

    // Now, the unit test. The sum of 0 to 9 should
    // be 45. But if buf[10] isn't 0 - which it won't be,
    // 255/256 of the time - this will fail.
    int testval = checksum(buf, 10);
    if (testval == 45)
    {
        printf("Passed!\n");
    }
    else
    {
        printf("Failed! Expected 45, got %d\n", testval);
    }
}
share|improve this answer
    
Very good! This is just the kind of answer that I was hoping for: thank you. –  DrAl Jun 1 '11 at 7:00
    
When you create the buffer you already have rubbish in that chunk of memory, is it really necessary to initialize it with random numbers? –  Snake Sanders Aug 16 '13 at 14:12
add comment

What about implementing a sort function like bubble sort? Once you have the sort function working, you can continue with binary search which is just as good for introducing unit testing and TDD.

Sorting and searching depends on comparisons which is easy to get wrong. It also involves swapping pointers around which must be done with care. Both is prone to errors, so feel free to mess up :)

A few more ideas:

  • Unit tests helps a lot when doing refactoring. So once your bubble sort works, you could change it into a more powerful sort like qsort, and the tests should still pass, proving your new sort function works as well.
  • Sorting is easy to test, the result is either sorted, or it is not, which makes it a good candidate.
  • The same for searching; it either exists or it doesn't.
  • Writing tests for sorting opens up discussions like what type of input to use for test (zero elements, random input, duplicate entries, huge arrays etc).
share|improve this answer
    
Do you have any specific suggestions for a simple error that would show how testing makes life easier? –  DrAl May 26 '11 at 12:01
    
@DrAl: Updated my answer with that. –  Martin Wickman May 26 '11 at 12:56
    
Thanks, that looks good. –  DrAl Jun 1 '11 at 12:47
add comment

I happen to have test cases for a priority queue that I used in a course in university and I would be happy to share it with you.
I it is a VS2010 project. The queue is in C and the test cases in C++ for testing it.
Returns structs and integers. Have state and I think you can find some corner cases in the code. I have used it in a ATMEL AT169P embedded controller. Any idea where to host it?

share|improve this answer
    
Sounds interesting, thank you. The only hosting ideas I've got are something like github, bitbucket, launchpad or something similar to that, depending on what you use for version control. I guess an alternative might be a zip file on some file sharing site, but not all are accessible from here (due to IT policy). –  DrAl May 26 '11 at 12:00
    
@DrAl this link is valid 24hrs pastebin.com/8jR9Dk42 –  user1041 May 26 '11 at 12:35
    
Thanks, I've copied the code; I'll have a look through it. –  DrAl May 26 '11 at 13:00
    
@DrAl I remember that I have an anonymous namespace in the "C-file", maybe you want to change that to static variables just in case a dilligent viewer will be on your chat. –  user1041 May 27 '11 at 13:44
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.