Is Unit Testing in C with Google Test possible?


When you program and unit test in C++ you may have used the Google Test framework. There are several unit testing frameworks for pure C, but is it also possible to use Google Test?

Unit Testing in C with the Google Test Framework is possible. There are some constraints that the programmer has to obey because of the procedural nature of the C programming language. Any features that precede object oriented language features are not permitted.

Let’s find out how to test C-Code with Google Test and what we should look for when doing so.

Can You Unit Test in C with the GTest Framework?

It is indeed possible to test C-Code with the Google Test framework, although this is a C++ framework. It is common practice to test C-Code with C++ frameworks, you could for example also use the CppUTest framework.

But there are some things to keep in mind when you test C-Code with Google Test. Because you normally would test C++ code you have to look out for some peculiarities in order to avoid mistakes.

When you test C-Code you cannot create an instance of the code under test. In contrast to to testing C++ code you will not get a “fresh” instance for every test. This means that you have to care about the initialization or you will get dependencies between tests – and this is really bad. This could lead to a condition where your tests pass sometimes, but fail at other times.

The dependencies between modules are fixed and there are no real classes, so you cannot use dependency injection with mocks/stubs to break a dependency for your test. You could do this for individual functions with function pointers nevertheless. But be aware and know what you’re doing.

You also don’t have the possibility to use real polymorphism and therefore you cannot break the dependencies in this way either.

There are, however, ways to fake classes Opens in a new tab.and polymorphism Opens in a new tab.in C, so take a look at the articles behind the links.

How to get Google Test (GTest) Framework

When you read this article I assume that you already use the Google Test framework for your C++ code. But if you never used it before I will tell you quickly how to obtain and install it.

You can get the latest version of the GTest framework at this GitHub pageOpens in a new tab.. You will have to download (or clone) the source code and build the framework yourself. In order to do this you will need the make (or cmake) tool. You can read how to do this hereOpens in a new tab..

If you are on Windows and use the Microsoft Visual Studio, you can simply open the NuGet Package Manager of your test project, search for “GTest” or “GoogleTest” and install the corresponding package. The advantage is that you don’t have to build it and the linking is also done for you.

Example: The Bowling Kata in C

For our Example we will use the famous Bowling Kata. It is a good practice for a Programmer, usually used to refine techniques and practice TDD. Like doing Katas in martial arts in order to become perfect in movement and execution, these Katas are meant to do the same for your programming skills.

The Bowling Kata that you will find through the link above is done in Java. We will modify it so that we can program in C and use Google Test as a testing framework.

Normally you would go through a Kata step by step, doing one test after the other, making mistakes on purpose, then correct and finally refactor. The example here is in the middle of the Kata where some steps are already done while others are incomeplete.

This is the .cpp-File that contains the tests and makes use of the Google Test framework. We group the tests by using a class which is derived from the GTest Test class. By doing this we can make use of the SetUp function which is executed automatically before every test.

You see that we include our .c-File by using the extern keyword.

#include <gtest/gtest.h>

extern "C" {
#include "BowlingGame.h"
}


class BowlingGameTest : public testing::Test {
protected:
	void SetUp() override {
		game_initialize();	/* Without this the Tests could break*/
	}
};

/** HELPER FUNCTIONS **/
void rollMany(const int n, const int pins) {
	for (int i = 0; i < n; i++) {
		game_roll(pins);
	}
}

void rollSpare() {
	game_roll(5);
	game_roll(5);
}

/** TESTS **/
TEST_F(BowlingGameTest, GutterGame) {
	rollMany(20, 0);
	ASSERT_EQ(0, game_score());
}

TEST_F(BowlingGameTest, AllOnes) {
	rollMany(20, 1);
	ASSERT_EQ(20, game_score());
}

TEST_F(BowlingGameTest, OneSpare) {
	rollSpare();
	game_roll(3);
	rollMany(17, 0);
	ASSERT_EQ(16, game_score());
}

// TODO: Strikes, Final Score, ...

The header file of our C-Code is just a plain interface with all the declarations and the include guard:

#pragma once

void game_initialize();

void game_roll(const int pins);
int  game_score();

Our .c-File is the code under test. Although it is pure C, the GTest framework checks against it properly. We have to write the initialize-Function and call it in the SetUp fuction of our test-class in order to get a “fresh” status for every test.

For example, if we would not initialize _rolls[21] to 0 before every test, it could happen that sometimes the test GutterGame would pass (if run as first test), but sometimes it would fail (when run after AllOnes), because then rolls[21] would contain values from the test before.

You’ll find “ToDos” in the Code and may have noticed that the Kata is not complete yet. Go ahead and finish the Kata – this way you will practically learn your first steps using GTest and C

#include "BowlingGame.h"

/* Private Variables */
static int _rolls[21];
static int _currentRoll = 0;

/* Private Functions (Declarations) */
static int isSpare(const int frameIndex);

/* Initialization */
void game_initialize()
{
	memset(_rolls, 0, sizeof(_rolls));
	_currentRoll = 0;
}

/* Public Functions */
void game_roll(const int pins)
{
	_rolls[_currentRoll++] = pins;
}

int game_score()
{
	int score = 0;
	int frameIndex = 0;
	for (int frame = 0; frame < 10; frame++) {
		if (isSpare(frameIndex)) {
			score += 10 + _rolls[frameIndex + 2];
			frameIndex += 2;
		}
		else { /* TODO: Duplication */
			score += _rolls[frameIndex] + _rolls[frameIndex + 1];
			frameIndex += 2;
		}
	}
	return score;
}

/* Private Functions (Definitions) */
static int isSpare(const int frameIndex) {
	return (_rolls[frameIndex] + _rolls[frameIndex + 1] == 10);
}

When you run the tests in a windows console, you will get this output:

GoogleTest BowlingKata Example
Example: Running GoogleTest Framework Tests for C-Files in the Windows Console

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