Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Using GoogleTest for C Code Unit Testing

Tech May 21 1

Obtain GoogleTest Source

Retrieve the source code from the official repository: https://github.com/google/googletest

Build Libraries on Linux

Transfer the downloaded source to your Linux environment using SFTP.

Refer to the README file included in the googletest directory for compilation instructions.

Follow the documentation to compile the source code on Linux:

After successful compilation, locate the generated library files. The primary libraries are libgtest.a and libgtest_main.a. Additional mock libraries are available for C++ stubbing scenarios.

With these libraries preparde, you can proceed to implement testing.

Create Test Implementation

Set up your test project structure by creating lib and unittest directories, then transfer them to your Linux system via SFTP.

Copy the compiled gtest libraries and header files into your project structure:

For each source directory under src, create corresponding test directories within unittest.

math_operations_test.cpp

#include <iostream>
#include <gtest/gtest.h>
#include "math_operations.h"

using namespace std;

extern "C" {
    // float compute_maximum(float x, float y);
    // float compute_minimum(float x, float y);
}

class NumericOperations : public testing::Test {
protected:
    void SetUp() override {
        cout << "Starting test case" << endl;
    }
    
    void TearDown() override {
        cout << "Finishing test case" << endl;
    }
};

TEST_F(NumericOperations, MaximumValueFirst) {
    float output = compute_maximum(1.5f, 2.5f);
    EXPECT_FLOAT_EQ(output, 2.5f);
}

TEST_F(NumericOperations, MaximumValueSecond) {
    float output = compute_maximum(3.5f, 2.5f);
    EXPECT_FLOAT_EQ(output, 3.5f);
}

TEST_F(NumericOperations, MaximumValueEqual) {
    float output = compute_maximum(2.5f, 2.5f);
    EXPECT_FLOAT_EQ(output, 2.5f);
}

TEST_F(NumericOperations, MinimumValueFirst) {
    float output = compute_minimum(1.5f, 2.5f);
    EXPECT_FLOAT_EQ(output, 1.5f);
}

TEST_F(NumericOperations, MinimumValueSecond) {
    float output = compute_minimum(2.5f, 1.5f);
    EXPECT_FLOAT_EQ(output, 1.5f);
}

TEST_F(NumericOperations, MinimumValueEqual) {
    float output = compute_minimum(1.5f, 1.5f);
    EXPECT_FLOAT_EQ(output, 1.5f);
}

utility_function_test.cpp

#include <iostream>
#include <gtest/gtest.h>
#include "utility.h"

using namespace std;

extern "C" {
    // int utility_function(void);
}

class UtilityTesting : public testing::Test {
protected:
    void SetUp() override {
        cout << "Initializing utility test" << endl;
    }
    
    void TearDown() override {
        cout << "Completing utility test" << endl;
    }
};

TEST_F(UtilityTesting, FunctionReturnValue) {
    int outcome = utility_function();
    EXPECT_EQ(outcome, 1);
}

Create Build Script

#!/bin/bash
set -e

display_error() {
    echo -e "\033[1;31m$1\033[0m"
}

display_warning() {
    echo -e "\033[1;33m$1\033[0m"
}

display_success() {
    echo -e "\033[1;32m$1\033[0m"
}

display_info() {
    echo -e "\033[1;34m$1\033[0m"
}

PROJECT_EXECUTABLE="test_suite"
sh cleanup_script.sh
cd ../unittest

if [ ! -d "test_results" ]; then
    mkdir test_results
    display_success "Created test_results directory"
else
    rm -rf test_results
    mkdir test_results
    display_success "Cleaned existing test_results directory"
fi

if [ ! -d "build_cache" ]; then
    mkdir build_cache
    display_success "Created build_cache directory"
else
    rm -rf build_cache
    mkdir build_cache
    display_success "Cleaned existing build_cache directory"
fi

if [ "$?" != "0" ]; then
    exit 1
fi

cd build_cache

compilation_start=$(date "+%Y-%m-%d %H:%M:%S")
display_success "=================Compilation Started==================="
cmake .. -G "Unix Makefiles"
display_success "===================Building Process====================="
make
compilation_end=$(date "+%Y-%m-%d %H:%M:%S")
display_success "Start time: ${compilation_start}"
display_success "End time: ${compilation_end}"

cp ./${PROJECT_EXECUTABLE} ../test_results
cd ../test_results
./${PROJECT_EXECUTABLE}

Configure CMake for Testing

Execute Compilation and Tests

user@development-machine:~/projects/testing_project/build$ sh execute_tests.sh
Previous build cache cleared
test_results directory created
build_cache directory created
=================Compilation Started===================
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - completed
-- Check for working C compiler: /usr/bin/cc - functional
-- Detecting C compile features
-- Detecting C compile features - completed
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - completed
-- Check for working CXX compiler: /usr/bin/c++ - functional
-- Detecting CXX compile features
-- Detecting CXX compile features - completed
Target executable: test_suite
Source directory: /home/user/projects/testing_project/unittest
CMake source path: /home/user/projects/testing_project/unittest
-- Configuration successful
-- Generation successful
-- Build files placed in: /home/user/projects/testing_project/unittest/build_cache
===================Building Process=====================
[ 20%] Compiling CXX object CMakeFiles/test_suite.dir/math_operations_test/math_operations_test.cpp.o
[ 40%] Compiling CXX object CMakeFiles/test_suite.dir/utility_function_test/utility_function_test.cpp.o
[ 60%] Compiling C object CMakeFiles/test_suite.dir/home/user/projects/testing_project/src/math_operations/math_operations.c.o
[ 80%] Compiling C object CMakeFiles/test_suite.dir/home/user/projects/testing_project/src/utility/utility.c.o
[100%] Linking CXX executable test_suite
[100%] Build target test_suite completed
Start time: 2024-02-25 21:32:07
End time: 2024-02-25 21:32:10
Executing tests from /home/user/projects/googletest_source/googletest/src/gtest_main.cc
[==========] Executing 7 tests across 2 test groups.
[----------] Global test environment initialized.
[----------] 6 tests from NumericOperations
[ RUN      ] NumericOperations.MaximumValueFirst
Starting test case
Finishing test case
[       OK ] NumericOperations.MaximumValueFirst (0 ms)
[ RUN      ] NumericOperations.MaximumValueSecond
Starting test case
Finishing test case
[       OK ] NumericOperations.MaximumValueSecond (0 ms)
[ RUN      ] NumericOperations.MaximumValueEqual
Starting test case
Finishing test case
[       OK ] NumericOperations.MaximumValueEqual (0 ms)
[ RUN      ] NumericOperations.MinimumValueFirst
Starting test case
Finishing test case
[       OK ] NumericOperations.MinimumValueFirst (0 ms)
[ RUN      ] NumericOperations.MinimumValueSecond
Starting test case
Finishing test case
[       OK ] NumericOperations.MinimumValueSecond (0 ms)
[ RUN      ] NumericOperations.MinimumValueEqual
Starting test case
Finishing test case
[       OK ] NumericOperations.MinimumValueEqual (0 ms)
[----------] 6 tests from NumericOperations (0 ms total)

[----------] 1 test from UtilityTesting
[ RUN      ] UtilityTesting.FunctionReturnValue
Initializing utility test
Hello world! Initial program output.
Completing utility test
[       OK ] UtilityTesting.FunctionReturnValue (0 ms)
[----------] 1 test from UtilityTesting (0 ms total)

[----------] Global test environment finalized
[==========] 7 tests from 2 test groups executed. (1 ms total)
[  PASSED  ] 7 tests.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.