Coder Social home page Coder Social logo

ctest's Introduction

Issues MIT License


CTEST

An unit test lib for C.
Explore the docs »

Report Bug · Request Feature

Table of Contents
  1. Description
  2. How to contribute
  3. Requirements
  4. How to use the makefile
  5. Using ctest
  6. Documentation

(back to top)

Description

This repository contains a library that can be used to implement unit tests for C code.

(back to top)

How is a contribution made?

  1. Create a branch from an issue;
  2. Clone the repository:
git clone  https://github.com/ArturAssisComp/ctest.git
  1. Change to the desired branch:
cd ctest
git checkout <branch-name>
  1. For each meaningful change, make a commit;

-> Fist, add the files that were changed:

git add <filename1> <filename2> ... <filenameN>

-> Commit the changes:

git commit -m "Implemented function foo()"
  1. Push the changes:
git push origin <name-of-the-branch>
  1. If more changes are necessary, go to 4. Else, go to 7;
  2. Create a pull request and assign someone to review the changes that were made in the branch;

=> Other useful commands:

Check the history of commits

git log

Check the status of the repository

git status

Get changes from remote repository from branch master

git pull origin <master-branch-name>

(back to top)

Requirements

make 4.3

gcc 11.2.0

(back to top)

How to use the makefile?

Run the following command in the terminal in the root directory of the ctest project:

make

The headers, object files, and archive lib object will be saved into ./build/ folder. They may be used to implement unit tests using ctest lib in other projects.

To clean ./build/ folder, run:

make clean

In order to run all tests:

make test

or, to print the results to txt files in ./build/test_results/

make test_to_txt

(back to top)

How to use ctest in other projects?

Run the command make from the ctest base directory:

make

then, the headers and the archive ctest.a files will be created and saved into the folder ./build/ctest_lib/

The files are organized as follows:

headers --> ./build/ctest_lib/include/

ctest.a --> ./build/ctest_lib/lib/

In order to use the library, the user must copy the content from ctest_lib to the desired folder in the target project, import the header ctest.h, and compile the file with the unit tests using as input, among others, the ctest.a object file.

Example of usage

Let us suppose that the base directory for ctest is CTEST_BASE_DIR and the base directory for the target project, in which the unit tests will be implemented, is BASE_DIR. In an actual case, it is necessary to exchange BASE_DIR and CTEST_BASE_DIR to the respective actual directory name.

1 - Execute the make command from CTEST_BASE_DIR:

cd CTEST_BASE_DIR
make

2 - Copy the folder CTEST_BASE_DIR/build/ctest_lib and its contents to the target project:

cp -r CTEST_BASE_DIR/build/ctest_lib BASE_DIR/

3 - Create the unit test file with name unit_test.c:

//C file that implements the unit tests
#include "ctest_lib/include/ctest.h"


#define MSG_SIZE 100

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

int main(void)
{
	char suite_name[] = "Unit test";
	char suite_description[] = "Basic test case.";
	char *functions_tested[] = {
        "add",
		NULL
	};
	char error_msg[MSG_SIZE] = "";
	char msg[MSG_SIZE] = ""; 


	//------------------------------------------------------------------------------
	start_suite(suite_name, suite_description, functions_tested);
		//------------------------------------------------------------------------------
		start_module("EDGE CASES", "Module for testing edge cases.", functions_tested);
            /* 0 + 0 */
            assert_integer_equal(add(0, 0), 0, __LINE__, "add(0, 0) == 0");
            /*------*/
            /* -1 + 0 */
            assert_integer_equal(add(-1, 0), -1, __LINE__, "add(-1, 0) == -1");
            /*------*/
            /* -1 + 1 */
            assert_integer_equal(add(-1, 1), 0, __LINE__, "add(-1, 1) == 0");
            /*------*/
            /* 1 + 1 */
            assert_integer_equal(add(1, 1), 2, __LINE__, "add(1, 1) == 2");
            /*------*/
            /* -1 + 2 */
            assert_integer_equal(add(-1, 2), 1, __LINE__, "add(-1, 2) == 1");
            /*------*/    
		end_module();
		//------------------------------------------------------------------------------
    		//------------------------------------------------------------------------------
		start_module("Domain CASES", "Module for testing domain cases.", functions_tested);
            /* 123 + 44 */
            assert_integer_equal(add(123, 44), 167, __LINE__, "add(123, 44) == 167");
            /*------*/
            /* -14 + 10 */
            assert_integer_equal(add(-14, 10), -4, __LINE__, "add(-14, 10) == -4");
            /*------*/ 
		end_module();
		//------------------------------------------------------------------------------
        
		
	end_suite();
	//------------------------------------------------------------------------------
}

4 - Compile the unit test file and execute it:

cd BASE_DIR
gcc -o unit_test unit_test.c ctest_lib/lib/ctest.a

5 - Execute unit_test and check the results:

unit_test

(back to top)

Documentation

Overview

  • About assert functions: every assert function has the signature in the following format:

void assert_<type>_<description>(..., int line_number, char custom_message[]).

<type> describes the type of the target that will be used in the assertion process. <description> specify the type of assertion that will be made. As an example, <type> may be integer and <description> may be equal, resulting in assert_integer_equal.

line_number and custom_message are useful for printing meaningful failure messages. It is recommended to use the macro __LINE__ as the input line_number. custom_message may be NULL if no custom message will be used for failure message.

(back to top)

Types

(back to top)

Variables

(back to top)

Constants

(back to top)

Functions

Single data types

unsigned_integer

assert_unsigned_integer_equal
  • Signature:
void assert_unsigned_integer_equal (unsigned_integer target, unsigned_integer reference, int line_number, char custom_message[]);
  • Description: this function checks if the unsigned_integer target is equal to the unsigned_integer reference.
Example
#include "ctest_lib/include/ctest.h"
int main(void)
{
    char *functions_tested[] = { "None", NULL };
    start_suite("Unit test", "Basic test case.", functions_tested);
        start_module("Success module", "Basic test case.", functions_tested);
            assert_unsigned_integer_equal(2, 2, __LINE__, NULL); //pass
        end_module();	
        start_module("Fail module", "Basic test case.", functions_tested);
            assert_unsigned_integer_equal(0, 2, __LINE__, NULL); //fail
        end_module();	
    end_suite();
}

(back to top)

integer

(back to top)

floating_point

(back to top)

bool

(back to top)

char

(back to top)

file

(back to top)

void pointer

(back to top)

Array data types

unsigned_integerArray

(back to top)

integerArray

(back to top)

boolArray

(back to top)

charArray

(back to top)

string

(back to top)

Macros

(back to top)

ctest's People

Contributors

arturassiscomp avatar

Watchers

 avatar

ctest's Issues

Create a detailed readme for the project

  • Create instructions about how to contribute to the project;
  • Create instructions about how to use the project, including configuration details;
  • Create examples and use cases;

Bug in the start_module function from ctest_functions.h

The bug was noticed when testing assert macros.
The following piece of code was used in two different files (test_std_assert_macros_success.c and test_std_assert_macros_fail.c) and an error happened in one of them (test_std_assert_macros_fail.c).

start_module("UI ARRAY-notIsPartPerm", "Every assert in this module must pass.",\
(char *[]){"ASSERT_UNSIGNED_INTEGER_ARRAY_NOT_IS_PARTIAL_PERMUTATION", NULL});
(...)
end_module();

The error does not happen when the third parameter is changed from

(char *[]){"ASSERT_UNSIGNED_INTEGER_ARRAY_NOT_IS_PARTIAL_PERMUTATION", NULL} to
(char *[]){"A_UNSIGNED_INTEGER_ARRAY_NOT_IS_PARTIAL_PERMUTATION", NULL}

Empty custom message bug

If custom message is an empty string, the test failure message is not formatted properly.
Example:

assert_integer_equal(0, 1, __LINE__, "");

Is it necessary to have a global variable for the result of each unit test? (design issue)

Each assert function of this library uses a global variable called global_result to store the results of the test. It stores a bool that says if the test was successful and the details of the result. After that, it calls the print_result() function passing some arguments from the current test but, for some reason, it does not pass the result and the detailed message. Maybe it is a good idea to eliminate this global variable.

Implement a better floating point almost equal

The assert functions almostEqual used to compare floating points were implemented using a naive algorithm. It is interesting to implement a better and more sophisticated algorithm.
The implemented algorithm uses the approach of comparing the difference between two floating points with an absolute value. That is a very naive and inefficient approach. The idea is to implement a technique that uses the concept of UPL.
To do list:

  • Read the paper: "What Every Computer Scientist Should Know About Floating-Point Arithmetic";
  • Implement an algorithm for almostEqual comparison between floating points using the concept of "units in the last place" (ULP);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.