Can You Unit Test in C and Why Should You Care?


Testing your code is an essential task for every software developer. Especially as a professional programmer you have to make sure that the software works as intended and is as bug free as possible. One type of testing is by writing Unit Tests. But is this also possible in the C Programming Language?

There are several possibilities to Unit Test your Code in C. The most common practice is the usage of Unit Testing Frameworks which also exist for the C Programming Language.

Finding Bugs
Image from testbytes at Pixabay

Are these Unit Tests useful and how can you even start? If you are new to testing as a whole or just new to testing in the C language, either way you should keep on reading to find out.

How Can You Unit Test in C?

In general there are two approaches for writing unit tests. The first one is by writing manual test functions and the second one is by using automated unit testing frameworks.

For manual unit testing you would wirte a program that calls a function of your program that you want to test and then print and output that you could compare to what you would expect. We will examine this in an example.

First we write our program under test or system under test (sut). In this case it is a simple addition function:

#pragma once

int add(int a, int b);
#include "system_under_test.h"

int add(int a, int b) {
    return (a + b);
}

Now we write our unit test program and include our system under test. Then we call the function we want to test and compare the output to our expected output:

#include "system_under_test.h"
#include <stdio.h>

void test_add() {
    const int expected = 7;
    int result = add(3, 4);
    int pass = expected == result;
    
    printf("Expected: %d | Result: %d\n", expected, result);
    if(pass) {
        printf("Test passed!");
    } else {
        printf("Test failed!");
    }
}

int main()
{
    test_add();
    /* Add more tests... */
    return 0;
}

This approach works and gives you a lot of control but is slow and cumbersome if you want to do it with larger codebases and more complex functions. A better solution is the usage of automated unit test frameworks which are described in the next section.

C Unit Testing Frameworks

As for many other languages there are Unit Testing Frameworks for C. The best known ones are CUnitOpens in a new tab., UnityOpens in a new tab. (don’t confuse with the game engine of the same name!), CppUTest Opens in a new tab.and GoogleTest Opens in a new tab.(a.k.a GTest). You should also be able to use any C++ Unit Test Framework in order to test your C Code. (All links open in new tabs)

A unit testing framework gives you the freedom to focus on what you test because it takes care of the confirmation, setup and teardown part.

In order to use such a framework you have to download the needed resources, install and configure it. If you have an IDE such as Visual Studio, some frameworks can be installed by extension managers or similar tools.

Although the functionalities of these frameworks are very similar they all are different in how to use. I have written a detailed explanation of the Unit Testing Frameworks mentioned above which you can read about in this article.

Following is just a quick example how you would test our system_under_test from the manual section in the CppUTest framework:

#include "CppUTest/TestHarness.h"
#include "CppUTest/CommandLineTestRunner.h"

#include "system_under_test.h"

TEST_GROUP(FirstTestGroup)
{
};

TEST(FirstTestGroup, AddTest)
{
    const int expected = 7;
    int result = add(3, 4);
    LONGS_EQUAL(expected, result);
}

int main(int ac, char** av)
{
   return CommandLineTestRunner::RunAllTests(ac, av);
}

Write your own C Unit Testing Framework

Another possibility is to write your own unit testing framework for C. The ones I showed you here are all good frameworks and at least one of them should fit your needs, but nevertheless it could be a good idea to write your own.

One reason is simply education. Writing a unit testing framework of your own is a great way to learn a new programming language because you will get into the habit of writing in that language while using some advanced features.

Also there could be a missing feature in the framework you use. Or the syntax of the existing frameworks is not to your liking. Whatever it is, writing an own unit testing framework can be a great exercise.

Why Should You Unit Test in C?

Until now we did not really mention why you should even care to write unit tests. There are several reasons that could change your mind if you are skeptical. It’s totally fine to be skeptical because writing tests seems to double your work and we all have deadlines too meet anyway.

We just could write tests where the Bugs are. The problem is that we don’t know where the Bugs are; they can be anywhere. So, that means we have to write tests for everything.

James W. Grenning, “Test-Driven Development for Embedded C”

Make sure the software does what its intended to

If we write the add function from our example above and by mistake type a minus instead of a plus sign, our software will certainly not do what it is intended to. A unit test helps to ensure the functionality.

Make sure the behaviour doesn’t change when refactoring

If you refactor code in order to make it more understandable and maintainable or if you add a new feature you want to be sure that the existing functionality (a.k.a. behaviour) does not change. Unit tests ensure that existing functionality will not break.

Find bugs faster and spend less time debugging

The time you put into writing unit tests seems to be lost time at first. But when you write these you catch little bugs early. If a small bug stays undetected until a later development phase it will be exponentially harder to find it through debugging. Also you won’t find yourself debugging that much if you have a solid unit test coverage of your code.

Raise confidence in yourself

Last but not least, unit tests raise the confidence in yourself and you being a software developer. If you can change code without worrying to break anything you will have a feeling of freedom and ease. You will also automatically write better code because writing testable code forces you to have a solid architecture. In addition you can refactor without fear and thus improve the code quality even further.

And now go and try unit testing in C for your own projects! I am sure that your software and code will improve over time.

Marco Lieblang

Professional Programmer since 2003, passionate Programmer since the mid 90's. Developing in many languages from C/C++ to Java, C#, Python and some more. And I also may know a bit about Assembly Languages and Retro Systems.

Recent Posts