Unit Testing in C Part 4 – Testing with Unity

This is the series on Unit testing in C for embedded development. The aim of this series is to provide easy and practical examples that anyone can understand. This is the Unit Testing in C – Testing with Unity tutorial. Let’s get started.

Unit Testing in C – Testing with Unity

Prerequisites

I would recommend you to explore the relevant topics by using the below link.

  1. Unit Testing Introduction
  2. Code Coverage
  3. Installing Ceedling

Introduction

In this tutorial, we are going to discuss –

Before doing anything, we have to know about the unity.

Unity

Unity is simply a rich collection of assertions you can use to establish whether your source code behaves the way you think it does. Unity provides a framework to easily organize and execute those assertions in test code separate from your source code. There are many TEST_ASSERT functions are available in the Unity framework, which is used to validate the values. We will see one by one.

TEST_ASSERT_XXX Functions

Validating Boolean

These are the functions used to validate the boolean condition.

Function Note
TEST_ASSERT_TRUE (condition) If the condition is true, then this evaluates to pass otherwise fail.
TEST_ASSERT (condition) This function is another way of TEST_ASSERT_TRUE
TEST_ASSERT_FALSE (condition) If the condition is false, then this evaluates to pass otherwise fail.
TEST_ASSERT_UNLESS (condition) This function is an another way of TEST_ASSERT_FALSE
TEST_ASSERT_NULL (pointer) If the pointer is NULL, then this evaluates to pass otherwise fail.
TEST_ASSERT_NOT_NULL (pointer) If the pointer is not a NULL, then this evaluates to pass otherwise fail.

Example

int a = 10;

//This evaluates to pass
TEST_ASSERT( (a > 0) )
TEST_ASSERT_TRUE( (a > 0) )
TEST_ASSERT_UNLESS( (a == 0) )
TEST_ASSERT_FALSE( (a == 0) )

//This evaluates to fail
TEST_ASSERT( (a == 0) )
TEST_ASSERT_TRUE( (a == 0) )
TEST_ASSERT_UNLESS( (a >> 0) )
TEST_ASSERT_FALSE( (a >> 0) )

Validating Integers

Separate set of functions are available for signed, unsigned integers that too for all sizes. Please have a look at below functions.

Functions Note
TEST_ASSERT_EQUAL_INT (exp, act) Compare two signed integers for equality and display errors
TEST_ASSERT_EQUAL_INT8 (exp, act) Compare two 8bit signed integers for equality and display errors
TEST_ASSERT_EQUAL_INT16 (exp, act) Compare two 16bit signed integers for equality and display errors
TEST_ASSERT_EQUAL_INT32 (exp, act) Compare two 32bit signed integers for equality and display errors
TEST_ASSERT_EQUAL_INT64 (exp, act) Compare two 64bit signed integers for equality and display errors
TEST_ASSERT_EQUAL (exp, act) This is another way of calling TEST_ASSERT_EQUAL_INT
TEST_ASSERT_NOT_EQUAL (exp, act) Compare two signed integers for a not equality and display errors
TEST_ASSERT_EQUAL_UINT (exp, act) Compare two unsigned integers for equality and display errors
TEST_ASSERT_EQUAL_UINT8 (exp, act) Compare two 8bit unsigned integers for equality and display errors
TEST_ASSERT_EQUAL_UINT16 (exp, act) Compare two 16bit unsigned integers for equality and display errors
TEST_ASSERT_EQUAL_UINT32 (exp, act) Compare two 32bit unsigned integers for equality and display errors
TEST_ASSERT_EQUAL_UINT64 (exp, act) Compare two 64bit unsigned integers for equality and display errors
TEST_ASSERT_INT_WITHIN(delta, expected, actual)
This evaluates to pass if the actual signed value is within plus or minus delta of the expected value. This also comes in size specific variants like 8bits, 16bits, 32bits and 64bits.
TEST_ASSERT_UINT_WITHIN(delta, expected, actual)
This evaluates to pass if the actual unsigned  value is within plus or minus delta of the expected value. This also comes in size specific variants like 8bits, 16bits, 32bits and 64bits.
TEST_ASSERT_GREATER_THAN(threshold, actual) This evaluates to pass if  the actual value is greater than the threshold. This also comes in size specific variants.
TEST_ASSERT_LESS_THAN(threshold, actual) This evaluates to pass if  the actual value is lesser than the threshold. This also comes in size specific variants.

Example

int a=10;

//This will evaluates to pass
TEST_ASSERT_EQUAL_INT(10, a);

//This will evaluates to fail
TEST_ASSERT_EQUAL_INT(5, a);

Validating hex values

These are the functions used to validate the unsigned hex values.

Functions Note
TEST_ASSERT_EQUAL_HEX (exp, act) Compare two unsigned hex values for equality and display errors
TEST_ASSERT_EQUAL_HEX8 (exp, act) Compare two 8 bit unsigned hex values for equality and display errors
TEST_ASSERT_EQUAL_HEX16 (exp, act) Compare two 16 bit unsigned hex values for equality and display errors
TEST_ASSERT_EQUAL_HEX32 (exp, act) Compare two 32 bit unsigned hex values for equality and display errors
TEST_ASSERT_EQUAL_HEX64 (exp, act) Compare two 64 bit unsigned hex values for equality and display errors

Validating bits

These are the functions used to validate the bits in the value.

Functions Note
TEST_ASSERT_BITS (mask, exp, act) Apply the integer mask to specify which bits should be compared between two other integers. In mask, if any bit is 0 means it will ignore and if any bit is 1 means it will compare that bit between exp and act.
TEST_ASSERT_BITS_HIGH (mask, act) This call used to check whether bits are set to high or not using the mask. In mask, if any bit is 0 means it will ignore and if any bit is 1 means it will check the bit is high or not with act value.
TEST_ASSERT_BITS_LOW (mask, act) This is opposite of TEST_ASSERT_BITS_HIGH.This will check whether the masked bit is low or not.
TEST_ASSERT_BIT_HIGH (bit, act) This is used to test a single bit and verify that it is high. The bit is specified 0-31 for a 32-bit integer.
TEST_ASSERT_BIT_LOW (bit, act) This is used to test a single bit and verify that it is low. The bit is specified 0-31 for a 32-bit integer.

Example

int act = 0x12FF;

/* Here Mask is 0xF. That means it will compare first 4bits.
** So after masked, exp value also 0xF and act also 0xF.
** Both value's first four bits are matching.
** This evaluate to pass the test case.
*/
TEST_ASSERT_BITS(0xF, 0xFFFFFFFF, act);


/* Here Mask is 0xF00. That means it will compare bits from 8 to 11.
** So after masked, exp value also 0xF00 and act also 0x200.
** Both value's masked bits are not matching.
** This evaluate to fail the test case.
*/
TEST_ASSERT_BITS(0xF00, 0xFFFFFFFF, act);


/* Here Mask is 0xF. That means it will check the first 4bits are high or not.
** So after masked, act value is 0xF.
** That means those 4bits are high.
** This evaluate to pass the test case.
*/
TEST_ASSERT_BITS_HIGH(0xF, act);

/* Here Mask is 0xF00. That means it will check bits8 to 11 are high or not.
** So after masked, act value is 0x200.
** That means those 4bits are not high.
** This evaluate to fail the test case.
*/
TEST_ASSERT_BITS_LOW(0xF00, act);


/* Here first argument is 0. That means it will check bit 0 is high or not.
** So here bit 0 is high.
** This evaluate to pass the test case.
*/
TEST_ASSERT_BIT_HIGH(0, act);

/* Here first argument is 8. That means it will check bit 8 is high or not.
** So here bit 8 is not high.
** This evaluate to pass the test case.
*/
TEST_ASSERT_BIT_LOW(8, act);

Validating Strings and pointers values

These are the functions used to validate the strings and pointers values.

Functions Note
TEST_ASSERT_EQUAL_PTR (exp, act) Checks the both exp pointer and act pointer are same or not.
TEST_ASSERT_EQUAL_STRING (exp, act) This checks the two NULL terminated strings. It will fail if any character is different.
TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)
This checks the two strings till it reach the given len. It will fail if any character is different.

Example

char a[] = "EMBETRONICX";
char *b = a;
char c[] = "embetronicx";

//This will pass
TEST_ASSERT_EQUAL_PTR(a, b);

//This will pass
TEST_ASSERT_EQUAL_STRING(a, b);

//This will pass
TEST_ASSERT_EQUAL_STRING_LEN(a, b, 3);

//This will fail
TEST_ASSERT_EQUAL_STRING(a, c);

Validating Structures and memory

We cannot validate the structure through its members. But we can validate the structure using memory compare. This function is used to compare the memory and structure as well.

Note : You have to know the structure padding. I will always fail if structure is padded by 0.

Functions Note
TEST_ASSERT_EQUAL_MEMORY (exp, act, len) Compare the memory of len bytes from exp and act . Fails if it is not matching.

Example

typedef struct{
    int a;
    int b;
} temp;

temp a_struct = {10, 20};
temp b_struct = {10, 20};
temp c_struct = {5, 20};

char a[] = "Embetroncix";
char *b = a;
char c[] = "embetronicx";


//This will pass
TEST_ASSERT_EQUAL_MEMORY(a, b, 5);

//This will pass
TEST_ASSERT_EQUAL_MEMORY(&a_struct, &b_struct, sizeof(temp));

//This will fail
TEST_ASSERT_EQUAL_MEMORY(&a_struct, &c_struct, sizeof(temp));

//This will fail
TEST_ASSERT_EQUAL_MEMORY(a, c, 5);

Validating Arrays

We have functions to validate the arrays also like above. These are the functions to be used to check the arrays.

Functions Note
TEST_ASSERT_EQUAL_INT_ARRAY (exp, act, elem) This will compare the two signed integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_INT8_ARRAY (exp, act, elem) This will compare the two 8bit signed integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_INT16_ARRAY (exp, act, elem) This will compare the two 16bit signed integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_INT32_ARRAY (exp, act, elem) This will compare the two 32bit signed integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_INT64_ARRAY (exp, act, elem) This will compare the two 64bit signed integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_UINT_ARRAY (exp, act, elem) This will compare the two unsigned integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_UINT8_ARRAY (exp, act, elem) This will compare the two 8bit unsigned integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_UINT16_ARRAY (exp, act, elem) This will compare the two 16bit unsigned integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_UINT32_ARRAY (exp, act, elem) This will compare the two 32bit unsigned integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_UINT64_ARRAY (exp, act, elem) This will compare the two 61bit unsigned integer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_HEX_ARRAY (exp, act, elem) This will compare the two hex value arrays exp and act of elem elements
TEST_ASSERT_EQUAL_HEX8_ARRAY (exp, act, elem) This will compare the two 8bit hex value arrays exp and act of elem elements
TEST_ASSERT_EQUAL_HEX16_ARRAY (exp, act, elem) This will compare the two 16bit hex value arrays exp and act of elem elements
TEST_ASSERT_EQUAL_HEX32_ARRAY (exp, act, elem) This will compare the two 32bit hex value arrays exp and act of elem elements
TEST_ASSERT_EQUAL_HEX64_ARRAY (exp, act, elem) This will compare the two 64bit hex value arrays exp and act of elem elements
TEST_ASSERT_EQUAL_PTR_ARRAY (exp, act, elem) This will compare the two pointer arrays exp and act of elem elements
TEST_ASSERT_EQUAL_STRING_ARRAY (exp, act, elem) This will compare the two string arrays exp and act of elem elements

Example

unsigned int a0[] = {1, 8, 567, 120};
unsigned int a1[] = {1, 8, 567, 120};
unsigned int a2[] = {1, 8, 567, 10};

//These below cases will pass
TEST_ASSERT_EQUAL_INT_ARRAY(a0, a1, 4);
TEST_ASSERT_EQUAL_INT_ARRAY(a0, a2, 3);
TEST_ASSERT_EQUAL_UINT_ARRAY(a0, a1, 4);
TEST_ASSERT_EQUAL_HEX32_ARRAY(a0, a1, 4);

//These below cases will fail
TEST_ASSERT_EQUAL_INT_ARRAY(a0, a2, 4);
TEST_ASSERT_EQUAL_INT_ARRAY(a0, a2, 4);
TEST_ASSERT_EQUAL_UINT_ARRAY(a0, a2, 4);
TEST_ASSERT_EQUAL_HEX32_ARRAY(a0, a2, 4);

_MESSAGE variant

If you add _MESSAGE to the names of any assertion listed above for the message variant (and include your own string as the final parameter in the assertion). The message variant of TEST_ASSERT_EQUAL_INT is given below. That message will be printed when it is failing.

TEST_ASSERT_EQUAL_INT_MESSAGE(exp, act, message)

Example:

int a=10;
 
//This will evaluates to fail and print the message
TEST_ASSERT_EQUAL_INT_MESSAGE(13, a, "Test Failed: \"a\" should be 13");

You should see the print like this.

"Expected 13 Was 10. Test Failed: "a" should be 13"

Like this you can add the _MESSAGE to any functions.

Ignoring the test case

If you want to ignore the test case then you have to use this function.

TEST_IGNORE()

This will not run the respected test case and ignore it.

Failing the test case

If you want to fail the test case you can use the below function.

TEST_FAIL()

Note:

Functions are available for float and double also. Out of this, I think, I’ve covered most of the functions which we use widely. If I’ve missed anything please find that in ThrowTheSwitch.

Now we will move to the example project.

Creating a new project

Now I am going to create a new project which has no source code initially. In this project ceedling will be linked automatically since we are creating the project using ceedling.

Create the project using ceedling new proj_name using the command terminal (command prompt) in your desired directory (folder).

Example:

C:\Users\ceedling-proj>ceedling new simple_prog

After this, you can able to see the prints like below.

Welcome to Ceedling!
      create  simple_prog/project.yml

Project 'simple_prog' created!
 - Execute 'ceedling help' to view available test & build tasks

Cool. Now you have created the new project using ceedling.

Now you could able to see the new folder (directory) is created by ceedling called proj_name. In our case the folder (directory) name is simple_prog. Inside that folder you can see src and test directories along with that one project.yml file. We will discuss about project.yml later. In those two directories, no files will be there. We have to create those files.

Requirement for the development

First we will get a requirement. Need to develop the function like mentioned below.

  • I’ve to have three 8-bit global variables called Jill, Jung and Jukk.
  • Need to create the function called do_bit_man(uint8_t position).
  • We have to set the bit of the Jill variable based on the position.
  • We have to clear the bit of the Jung variable based on the position.
  • We have to toggle the bit of the Jukk variable based on the position.

Got your requirement? Ok, let’s write the code now. Oops, wait a minute. This is TDD. Before writing the code, we need to have a test plan and test code. Let’s plan how we are going to test.

Testing Plan

Let’s create a test plan based on the requirement above.

  1. Check the argument whether it is valid or not.
  2. If it is valid then do set, clear, and toggle to respected variables.
  3. Then check the variables

Now let’s write the code.

Writing a Sample source code in C

Here we are not going to write the complex program. We will go step by step. So let’s write the code for bit manipulation. To create source code, we need .c and .h files. Using ceedling also we can create the source template. We can create a module using ceedling module:create[module_name].

First go into the project directory where project.yml file stays. Then enter the command to create the module.

>cd simple_proj
>ceedling module:create[bit_manipulation]

After this, you can see the prints like below.

File src/bit_manipulation.c created
File src/bit_manipulation.h created
File test/test_bit_manipulation.c created
Generate Complete

Three files have been created automatically while creating module. Now we can use those files to add our source code.

NOTE: In this tutorial, we are not going to compile the program or test the output of the program. Out intention is to write the unit test for out source code.

I am going to write the source code for above requirement. Please find the code below.

bit_manipulation.c

#include "bit_manipulation.h"

uint8_t Jill = 0x00;
uint8_t Jung = 0xFF;
uint8_t Jukk = 0x00;


int8_t do_bit_man(int8_t position)
{
    if( ( position < 0 ) || ( position > 7 ) ) 
    {
        //positon should be 0 to 7. Because we are going to modify 8 bit value.
        return -1;
    }   
    
    //set particular bit
    Jill |= ( 1 << position );
    
    //clear particular bit
    Jung &= ~( 1 << position );
    
    //toggle particular bit
    Jukk ^= ( 1 << position );
    
    return 0;
}

bit_manipulation.h

#ifndef BIT_MANIPULATION_H
#define BIT_MANIPULATION_H

#include <stdio.h>
#include <stdint.h>

int8_t do_bit_man(int8_t position);

#endif // BIT_MANIPULATION_H

All good? I have written one function called do_bit_manThis is one unit of the source code. So we are going to test that function.

Testing those functions with Unity

Till here, we have source code. Now we will write the unit test code. Open the test_bit_manipulation.cunder the test directory. In that test_bit_manipulation.c there might be some default code will be there like below.

#include "unity.h"

#include "bit_manipulation.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_bit_manipulation_NeedToImplement(void)
{
    TEST_IGNORE_MESSAGE("Need to Implement bit_manipulation");
}

We are going to write out own test case. So we can remove the function called test_bit_manipulation_NeedToImplement.

What is setUp function?

This is kinda start function which is used to initialize some variables. This setUp function is executed before each test function is run. If you
have three test functions in your test file, setUp gets called three times.

What is tearDown function?

This is kinda end function which is used to free some variables. This tearDown function is executed after each test function is run. If you have three test functions in your test file, tearDown gets called three times.

Note: You have to include the unity.h file in every test file. And include your require header files also.

Test Case 0

Let’s write our first test case to test the function do_bit_man(uint8_t position). So I am going to create the test function called test_do_bit_man_0(void).This function name can be anything but make sure you are adding test_ in front of that function name. This test case is negative test. When I pass more than 7, it should return -1 and it should not modify the any values of those global variables. Please find the below function.

//Test Case 0
void test_do_bit_man_0(void)
{
    int8_t result;
    
    result = do_bit_man( 15 );
    
    TEST_ASSERT_EQUAL_INT8( -1, result );
    
    TEST_ASSERT_EQUAL_INT8( 0x00, Jill );
    TEST_ASSERT_EQUAL_INT8( 0xFF, Jung );
    TEST_ASSERT_EQUAL_INT8( 0x00, Jukk );
}

To verify this, you can run ceedling test:allMake sure that you are running the command terminal on the directory where the project.yml file is present. When you run this, you will get prints like below.

simple_prog>ceedling test:all


Test 'test_bit_manipulation.c'
------------------------------
Generating runner for test_bit_manipulation.c...
Compiling test_bit_manipulation_runner.c...
Compiling test_bit_manipulation.c...
Linking test_bit_manipulation.out...
Running test_bit_manipulation.out...

--------------------
OVERALL TEST SUMMARY
--------------------
TESTED:  1
PASSED:  1
FAILED:  0
IGNORED: 0

Our test case has passed. It is not modifying any of the variable and returns -1.

Test Case 1

Another negative test case we have to do. When I pass negative value (less than 0), that time also it should behave as test case 0. Write our second test case.

//Test Case 1
void test_do_bit_man_1(void)
{
    int8_t result;
    
    result = do_bit_man( -1 );
    
    TEST_ASSERT_EQUAL_INT8( -1, result );
    
    TEST_ASSERT_EQUAL_INT8( 0x00, Jill );
    TEST_ASSERT_EQUAL_INT8( 0xFF, Jung );
    TEST_ASSERT_EQUAL_INT8( 0x00, Jukk );
}

You will get prints like below.

simple_prog>ceedling test:all


Test 'test_bit_manipulation.c'
------------------------------
Generating runner for test_bit_manipulation.c...
Compiling test_bit_manipulation_runner.c...
Compiling test_bit_manipulation.c...
Compiling bit_manipulation.c...
Linking test_bit_manipulation.out...
Running test_bit_manipulation.out...

--------------------
OVERALL TEST SUMMARY
--------------------
TESTED:  2
PASSED:  2
FAILED:  0
IGNORED: 0

Our two negative test cases also passed. Let’s write our positive test case.

Test Case 2

If we pass the valid argument ( 0 to 7), then it should set, clear and toggle the respective variables in the position of argument and it should return 0.

//Test Case 2
void test_do_bit_man_2(void)
{
    int8_t result;
    int8_t position = 5;
    result = do_bit_man( position );
    
    TEST_ASSERT_EQUAL_INT8( 0, result );
    
    TEST_ASSERT_BIT_HIGH( position, Jill );
    TEST_ASSERT_BIT_LOW( position, Jung );
    TEST_ASSERT_BIT_HIGH( position, Jukk );
}

You should get print like below.

simple_prog>ceedling test:all


Test 'test_bit_manipulation.c'
------------------------------
Generating runner for test_bit_manipulation.c...
Compiling test_bit_manipulation_runner.c...
Compiling test_bit_manipulation.c...
Linking test_bit_manipulation.out...
Running test_bit_manipulation.out...

--------------------
OVERALL TEST SUMMARY
--------------------
TESTED:  3
PASSED:  3
FAILED:  0
IGNORED: 0

Complete Test code

These are the possible test cases that we can write. Please see the complete test code below.

#include "unity.h"

#include "bit_manipulation.h"

extern uint8_t Jill;
extern uint8_t Jung;
extern uint8_t Jukk;

void setUp(void)
{
    Jill = 0x00;
    Jung = 0xFF;
    Jukk = 0x00;
}

void tearDown(void)
{
}

//Test Case 0
void test_do_bit_man_0(void)
{
    int8_t result;
    
    result = do_bit_man( 15 );
    
    TEST_ASSERT_EQUAL_INT8( -1, result );
    
    TEST_ASSERT_EQUAL_INT8( 0x00, Jill );
    TEST_ASSERT_EQUAL_INT8( 0xFF, Jung );
    TEST_ASSERT_EQUAL_INT8( 0x00, Jukk );
}

//Test Case 1
void test_do_bit_man_1(void)
{
    int8_t result;
    
    result = do_bit_man( -1 );
    
    TEST_ASSERT_EQUAL_INT8( -1, result );
    
    TEST_ASSERT_EQUAL_INT8( 0x00, Jill );
    TEST_ASSERT_EQUAL_INT8( 0xFF, Jung );
    TEST_ASSERT_EQUAL_INT8( 0x00, Jukk );
}


//Test Case 2
void test_do_bit_man_2(void)
{
    int8_t result;
    int8_t position = 5;
    result = do_bit_man( position );
    
    TEST_ASSERT_EQUAL_INT8( 0, result );
    
    TEST_ASSERT_BIT_HIGH( position, Jill );
    TEST_ASSERT_BIT_LOW( position, Jung );
    TEST_ASSERT_BIT_HIGH( position, Jukk );
}

Code coverage

If you want to see the code coverage, please follow the below steps.

Install the gcovr using pip.

pip install gcovr

You can see the prints like below if you have installed correctly.

simple_prog>pip install gcovr
Collecting gcovr
  Downloading gcovr-4.2-py2.py3-none-any.whl (45 kB)
     |████████████████████████████████| 45 kB 166 kB/s
Collecting jinja2
  Downloading Jinja2-2.11.1-py2.py3-none-any.whl (126 kB)
     |████████████████████████████████| 126 kB 1.7 MB/s
Collecting lxml
  Downloading lxml-4.5.0-cp37-cp37m-win_amd64.whl (3.7 MB)
     |████████████████████████████████| 3.7 MB 5.5 kB/s
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl (16 kB)
Installing collected packages: MarkupSafe, jinja2, lxml, gcovr
Successfully installed MarkupSafe-1.1.1 gcovr-4.2 jinja2-2.11.1 lxml-4.5.0

Then have to add gcov plugin using project.ymlOpen the project.yml and add - gove after plugin like below.

:plugins:
  :load_paths:
    - "#{Ceedling.load_path}"
  :enabled:
    - stdout_pretty_tests_report
    - module_generator
    - gcov

That’s it. Now you can see the report by using ceedling gcov:all. You will get details like below.

simple_prog>ceedling gcov:all


Test 'test_bit_manipulation.c'
------------------------------
Running test_bit_manipulation.out...

--------------------------
GCOV: OVERALL TEST SUMMARY
--------------------------
TESTED:  3
PASSED:  3
FAILED:  0
IGNORED: 0


---------------------------
GCOV: CODE COVERAGE SUMMARY
---------------------------
bit_manipulation.c Lines executed:100.00% of 7
bit_manipulation.c Branches executed:100.00% of 4
bit_manipulation.c Taken at least once:100.00% of 4
bit_manipulation.c No calls

If you want to generate detailed html review, then please use the below command after ceedling gcov:all.

ceedling utils:gcov

You will get prints like this.

simple_prog>ceedling utils:gcov
Creating a detailed html report of gcov results in build/artifacts/gcov/GcovCoverageResults.html...
Done.

Once it is generated, then you can see the html file in simple_prog\build\artifacts\gcovOpen those two files which is generated and analyse. Right now it is 100%. That means we have covered all the lines and branches. You will get report like this.

coverage resultI want you guys to experiment on those by removing any of the test case and regenerate the report. Now you may see some percentage drop. Like this you can learn about code coverage.

Whenever you regenerate the report please clean it and regenerate or follow the steps below to get the updated report.

  1. ceedling clean  – This will clean the generated files.
  2. ceedling test:all – build and test the test case
  3. ceedling gcov:all– generate coverage result
  4. ceedling utils:gcov – Generate the html detailed report

By this experiment you can see how many branches we have and how many lines we have covered etc. You may get report like below if you remove test case 2.

Unit Testing in C - Testing with Unity

If we remove, one test case (test case 2), then we are missing one branch and 4 lines. If you don’t understand the code coverage, please go back here and read about the code coverage.

Note: Let’s say you have one test case where you have three TEST_ASSERT_X function. If any one fails, it will stop there and won’t run next line in that test case. It will run the next test case. So all TEST_ASSERT_X should pass in order to make the test case to pass.

4.5 2 votes
Article Rating
Subscribe
Notify of
guest

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

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
2
0
Would love your thoughts, please comment.x
Ads Blocker Image Powered by Code Help Pro
Ads Blocker Detected!!!

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

Refresh