Tau - A Micro (1k lines of code) Unit Test Framework for C/C++

Tau τ

Standard Standard License Twitter Download Docs

A Micro Unit Testing Framework for >C11/C++11 projects, with the promise of always being tiny - about 1k lines of code. This framework is a much simpler, much lighter and much faster alternative to heavier frameworks like Google Test, & Catch2, making it suitable for on-to-go testing (embedded developers will especially love us!).

I initially wrote Tau to be a unit testing framework for C; however, initial results showed great promise of compiling with (and testing) C++ code. While Tau doesn't currently support mocking, or a way to test for exceptions in C++, its limitations are in fact its biggest strength - you get negligible overhead & fast compilation speeds for the sacrifice of a few constructs.

Features

  • Ultra-light (~1k lines of code)
  • 8x times faster than GoogleTest and Catch2
  • Can test both C and C++ code (see ThirdParty tests)
  • Blazing Fast Assertions
  • Gtest-like Assertion Macros
  • Supports Test Fixtures
  • Allows filtering of test cases

Installation

None! Tau is header-only, so simply include it in your project.

#include <tau/tau.h>

To build Tau with CMake, read through the CMake Quickstart Guide.

Prerequistes

To begin, you must include the following in any (but only one) C/C++ file. This initializes Tau to set up all your tests:

TAU_MAIN() // IMPORTANT: No semicolon at the end 

This defines a main function, so if you write a main() function and declare TAU_MAIN(), your compiler will throw a redeclaration of main error.

If you must write a main() function, use the following instead:

TAU_NO_MAIN()

This won't define a main function, but sets up any variables/methods that Tau needs to run properly.

Getting Started

Defining a Test Suite

To define a test suite, simply do the following:

TEST(TestSuiteName, TestName) {
    CHECK(1); // does not fail
    ... rest of the test body ...
}

The TEST macro takes two parameters - the first is the name of the Test Suite, and the second is the name of the test. This allows tests to be grouped for convenience.

Testing Macros

Tau provides two variants of Assertion Macros - CHECKs and ASSERTs. These resemble function calls. When these assertions fail, Tau prints the source code location (file + line number) along with a failure message.

ASSERTs generate fatal failures - the test suite will cease its execution and move on to the next test suite to run.

CHECKs generate non-fatal failures - the remainder of the test suite will still execute, allowing for further checks to run.

Read the Primer for more details, including the other testing macros Tau provides you with.

Example Usage

Below is a slightly contrived example showing a number of possible supported operations:

#include <tau/tau.h>
TAU_MAIN() // sets up Tau (+ main function)

TEST(foo, bar1) {
    int a = 42; 
    int b = 13; 
    CHECK_GE(a, b); // pass :)
    CHECK_LE(b, 8); // fail - Test suite not aborted 
}

TEST(foo, bar2) {
    char* a = "foo";
    char* b = "foobar";
    REQUIRE_STREQ(a, a); // pass :)
    REQUIRE_STREQ(a, b); // fail - Test suite aborted
}

Supported Platforms

Tau supports codebases and compilers that are compliant with the C11/C++11 standard or newer. Tau's source code is officially supported on the following platforms. If you notice any problems on your platform, please file an issue on the Tau Github Issue Tracker. PRs with fixes are welcome!

Operating Systems Compilers
Linux gcc 5.0+
macOS clang 5.0+
Windows MSVC 2017+

Contributing

We appreciate all contributions, feedback and issues. If you plan to contribute new features, utility functions, or extensions to the core, please go through our Contribution Guidelines.

To contribute, start working through the Tau codebase, read the Documentation, navigate to the Issues tab and start looking through interesting issues.

Asking for help

If you have any questions, please:

  1. Read the docs.
  2. Look it up in our Github Discussions (or add a new question).
  3. Search through the issues.

Who uses Tau?

In addition to several of my personal projects, Tau is also used in the following notable projects:

Supporting This Project

If you are able to and would like to sponsor this project, you may do so using either of the links below. Thank you very much in advance :)

Buy Jason a Coffee Buy Jason a Coffee Buy Jason a Coffee

License

This project was written by Jason Dsouza and licensed under the MIT License.

Owner
Jason Dsouza
Researcher @harvard, Teacher @freeCodeCamp, and Compiler Warlock @adorad.
Jason Dsouza
Comments
  • Refactor of macro names related to strings and substrings check, to avoid confusion

    Refactor of macro names related to strings and substrings check, to avoid confusion

    Hello @jasmcaus , I decided to contribute to this unit test framework because I am really going to use it in practice for all my projects. I found it here and I chose it among the others due to its simplicity and effectiveness. So, I like it very much, but in my opinion there is one aspect that absolutely it is worth to improve. If we consider CHECK_EQ and CHECK_NE as the opposite statement, as well as CHECK_BUF_EQ and CHECK_BUF_NE, I would expect that for strings comparison CHECK_STREQ would be coupled with CHECK_STRNE. Unfortunately, CHECK_STRNE is already used to compare two substrings that are supposed to be equal. In other words, the pattern "_EQ/_NE" is broken. As such, in order to avoid confusions and keep the whole structure intuitive, I would propose to rename the macros related to strings and substrings as indicated below:

    Whole-string Checks:

    CHECK_STREQ --> CHECK_STR_EQ CHECK_STRNEQ --> CHECK_STR_NE REQUIRE_STREQ --> REQUIRE_STR_EQ REQUIRE_STRNEQ --> REQUIRE_STR_NE

    Substring Checks:

    CHECK_STRNE --> CHECK_STRN_EQ CHECK_STRNNE --> CHECK_STRN_NE REQUIRE_STRNE --> REQUIRE_STRN_EQ REQUIRE_STRNNE --> REQUIRE_STRN_NE

    As an alternative solution for the substring checks (but this has still to be evaluated) we could allow an optional third parameter in the string check macro. Something like this: CHECK_STR_EQ(actual, expected, n) is like calling CHECK_STRN_EQ(actual, expected, n)

    Just to make this transition smooth I would also keep the old names as "deprecated" defines at the bottom of tau.h, so that they can be removed safely at some point in the future. What do you think? If you agree, I would be more than happy to take care of this in my repository and then submit a pull request.

    Stefano

  • CHECK with message doesn't work

    CHECK with message doesn't work

    First of all I'd like to thank @jasmcaus for this useful library.

    So, I found out a little problem with custom failure message. According to documentation it's enough to add a further parameter. But If I add a parameter, the check never fails.

    Below an example.

    TEST(TAU, ItShouldFailWithMessage)
    {
        CHECK(0);                           // this check fails correctly.
        CHECK(0, "It should FAIL");         // this check doesn't fail.
    }
    

    Am i missing something?

  • New buf macros

    New buf macros

    I have added the following macros to check the content of two buffers.

    • CHECK_BUF_EQ / REQUIRE_BUF_EQ checks that two buffers of a given size match. If test does not succeed, the content of both buffers is shown, with differences highlightet; CHECK_BUF_EQ

    • CHECK_BUF_NE / REQUIRE_BUF_NE checks that two buffers don't have the same content;

    I have also added few internal tests for such new macros.

  • Compilation failed with cmake

    Compilation failed with cmake

    Hi, this is the follow up of https://github.com/HazelLang/Hazel/issues/6 here is the error message that showed up. (CMakeOutput.log)

    -- Building for: Visual Studio 16 2019
    -- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19041.
    -- The C compiler identification is MSVC 19.26.28806.0
    -- The CXX compiler identification is MSVC 19.26.28806.0
    -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe
    -- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Detecting C compile features
    -- Detecting C compile features - done
    -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe
    -- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Detecting CXX compile features
    -- Detecting CXX compile features - done
    CMake Error at CMakeLists.txt:206 (set_target_properties):
      INTERFACE_LIBRARY targets may only have whitelisted properties.  The
      property "VERSION" is not allowed.
    
    
    -- Configuring incomplete, errors occurred!
    See also "C:/lang/Muon/build/CMakeFiles/CMakeOutput.log".
    

    And I've did some googling and found the problem that caused. which is I'm using MSVC 19.26, MSVS 2019 and cmake 3.15. (Note that I've no prior knowledge in cmake). Your cmake script require 3.5+ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) and my version is lower, however the FATAL_ERROR wasn't also working because

    The FATAL_ERROR option is accepted but ignored by CMake 2.6 and higher. It should be specified so CMake versions 2.4 and lower fail with an error instead of just a warning.

    Sorry if this issue is is pointless but I just want to point out the problem that caused, maybe you could print an error and terminate the script if the version is not compatible yourself, apparently cmake won't.

  • cmake's install() macro fails with _deps/tau-src/include/tau not found

    cmake's install() macro fails with _deps/tau-src/include/tau not found

    Hi and thank you for this project.

    I'm trying to use cmake's install() macro in my project which is using Tau. I followed the instructions from cmake-quickstart.md. But 'make install' fails with:

    CMake Error at _deps/tau-build/cmake_install.cmake:46 (file):
      file INSTALL cannot find  "my/build/_deps/tau-src/include/tau":  No such file or directory.
    Call Stack (most recent call first):
      cmake_install.cmake:47 (include)
    

    Appreciate any support.

  • Abi tests/Helper macros for char signedness

    Abi tests/Helper macros for char signedness

    As of now, char, which is de facto used in string.h has no abi tests for the user.

    Macros for usage

    // MACROS
    #define IS_SIGNED(Type) (((Type)-1) < 0)
    
    #include <assert.h>
    static_assert(sizeof(U8) == 1, "U8 must have 1 byte size"); // compile-time error
    
    // http://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
    #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
    usage: BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE );
    

    The macros themself are also useful for a quick abi tests and providing one header+main.c example (ie under 0BSD) would be nice.

  • Only use red text for FAILED summary if tests failed

    Only use red text for FAILED summary if tests failed

    What this changes?

    This change causes the FAILED summary text to be displayed with red coloration only if there were failed tests. Otherwise use the default text coloration (light gray). Other unit testing frameworks (GTest, DocTest) follow this convention.

    Motivation

    I find it slightly distracting and confusing to see the red "FAILED" text in the test summary when all tests have passed, with zero failures. I only expect to see red text in the console output from a unit test framework in the event that there were test failures.

    Comparisons

    1. Tau image

    2. Google Test image

    3. DocTest image

  • --list option must not run but only list the tests

    --list option must not run but only list the tests

    diff --git a/tau/tau.h b/tau/tau.h
    index d446912..ab67bd3 100644
    --- a/tau/tau.h
    +++ b/tau/tau.h
    @@ -1044,6 +1043,7 @@ static TAU_Bool tauCmdLineRead(int argc, char** argv) {
             else if(strncmp(argv[i], listStr, strlen(listStr)) == 0) {
                 for (i = 0; i < tauTestContext.numTestSuites; i++)
                     tauPrintf("%s\n", tauTestContext.tests[i].name);
    +           return TAU_false;
             }
     
             // Disable colouring
    
  • --no-summary option doesn't works

    --no-summary option doesn't works

    diff --git a/tau/tau.h b/tau/tau.h
    index d446912..085cf6c 100644
    --- a/tau/tau.h
    +++ b/tau/tau.h
    @@ -1052,7 +1051,7 @@ static TAU_Bool tauCmdLineRead(int argc, char** argv) {
             }
     
             // Disable Summary
    -        else if(strncmp(argv[i], summaryStr, strlen(summaryStr))) {
    +        else if(strncmp(argv[i], summaryStr, strlen(summaryStr)) == 0) {
                 tauDisableSummary = 1;
             }
    
  • Please fix tauPrintf macro

    Please fix tauPrintf macro

    Without following fix --list option causes segfault.

    diff --git a/tau/tau.h b/tau/tau.h
    index d446912..361ae6a 100644
    --- a/tau/tau.h
    +++ b/tau/tau.h
    @@ -416,10 +416,9 @@ tauColouredPrintf(int colour, const char* fmt, ...) {
     }
     
     #ifndef TAU_NO_TESTING
    -    #define tauPrintf(...)                                  \
    -        if(tauTestContext.foutput)                          \
    -            fprintf(tauTestContext.foutput, __VA_ARGS__);   \
    -        printf(__VA_ARGS__)
    +    #define tauPrintf(...) (                                  \
    +        tauTestContext.foutput ? fprintf(tauTestContext.foutput, __VA_ARGS__) : 0,  \
    +        printf(__VA_ARGS__) )
     #else
         #define tauPrintf(...)   \
             printf(__VA_ARGS__)
    
  • Primer doc does not match code

    Primer doc does not match code

    In the primer doc there is a mention of REQUIRE_STRNNEQ and CHECK_STRNNEQ but I think, in the code they're actually REQUIRE_STRNE / REQUIRE_STRNNE and CHECK_STRNE / CHECK_STRNNE

  • gcc 12.1.0 fails to compile the example

    gcc 12.1.0 fails to compile the example

    My working env is msys2 on Windows, and gcc is of version 12.1.0.

    When I compile the example code, an error occurs, which tells:

    tau/types:h:22:58: error: size of array 'static_assertion_at_line__LINE__' is negative
    22 | #define TAU_STAT_ASSERT1__(cond, line)        typedef char static_assertion_at_line_##line[[(!!(cond)*2-1]
       |                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    However, gcc of version 11.2.0 on windows can compile the example sucessfully.

    I have no idea whether this error is related to the gcc of specific version or not.

  • docs: TEST blocks require that there is no return value

    docs: TEST blocks require that there is no return value

    From a little toy project https://github.com/matu3ba/pbcd/blob/4ffd0dfe6006c5342302d4099c02d537facf4ffe/runTest.sh

    ^
    test.c:28:3: error: void function '_TAU_TEST_FUNC_foo_bar1' should not return a value [-Wreturn-type]
      return status;
    

    Alternatively (but probably more cumbersome): support custom return values.

  • design questions on minimizing dependencies

    design questions on minimizing dependencies

    I am wondering, if #include <string.h> #include <stdarg.h> are strictly necessary, as we only need a few of the functions and argument handling doesnt sound super complicated either.

    Can you add a comment on the other headers, what they are used for?

        #include <errno.h> // Kernel error codes
        #include <libgen.h> // regex for filter [but only contains dirname and __xpg_basename, so kinda useless???
        #include <unistd.h> // file seek
        #include <sys/types.h> // system types, but where are those used?!
        #include <sys/wait.h> // also includes features.h, pid exit status etc as process info
        #include <signal.h> // signal handler
        #include <time.h> // time
    
  • Filtering by exact name doesn't work

    Filtering by exact name doesn't work

    It's not possible to use entire test name (TESTSUITE.TESTNAME) to run a single test by mean of "--filter" option. Anyway if I remove just last char from the test name, it works.

  • question: how can I test for arithmetic overflow

    question: how can I test for arithmetic overflow

    Is there even a simple way to macro overload arithmetic expressions to auto-insert overflow checks ie via SEI Standard https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152052 ?

    Alternatively documentation how to emit the instructions for testing with clang/gcc would be great.

Athena, a C testing framework

Part of the Olympus project. Athena, the Greek goddess of wisdom. Athena provides a testing framework. Usage Create a file in bin/. #include the sourc

Feb 26, 2022
Source code of the paper "Lord of the Ring(s): Side Channel Attacks on the CPU On-Chip Ring Interconnect Are Practical"

Overview This repository contains the source code to reproduce the experiments of the paper: Lord of the Ring(s): Side Channel Attacks on the CPU On-C

Aug 17, 2022
Simple C++ code to benchmark fast division algorithms

fast_division Simple C++ code to benchmark fast division algorithms relying on constant divisors. The code is a companion to the paper Integer Divisio

Jul 31, 2022
Algo-Tree is a collection of Algorithms and data structures which are fundamentals to efficient code and good software design
Algo-Tree is a collection of Algorithms and data structures which are fundamentals to efficient code and good software design

Algo-Tree is a collection of Algorithms and data structures which are fundamentals to efficient code and good software design. Creating and designing excellent algorithms is required for being an exemplary programmer. It contains solutions in various languages such as C++, Python and Java.

Jul 24, 2022
Public repository for rolling release of main Vector robot code repository.

vector Public repository for rolling release of main Vector robot code repository. This rolling release will be worked to completion until all non-thi

Sep 8, 2022
This repo is full with code from random c++ projects. Anyone can contribute

Randomcplusplus Learn c++ This repo is for random c++ code that can be used for any project Learn how to code in c++ by using and reading peoples exam

Jan 30, 2022
Redacted source code for exercises proposed in the Data Structures and Algorithms laboratory.

fsega_ie2_dsa Redacted source code for exercises proposed in the Data Structures and Algorithms laboratory. Usage The src/ directory contains a direct

Dec 5, 2021
An optimized version of the KGloVe code (global embeddings for Knowledge Graphs)

Optimized Implementation of the KGloVe algorithm This repository contains an optimized implementation of KGloVe, which was proposed in Cochez M., Rist

Feb 25, 2022
100 Days Of Code

100DaysOfCode I will be following Coding Ninja for learning most of the stuff. I am working on DS and Algos PS : It's not consecutive 100Days Day 1: C

May 25, 2022
FEMTIC is a 3-D magnetotelluric inversion code. FEMTIC is made by object-oriented programming with C++.

FEMTIC FEMTIC is a 3-D magnetotelluric inversion code based on the following studies. FEMTIC was made using object-oriented programming with C++. FEMT

Sep 7, 2022
This repository contains the Assignment code of Data Structures and Algorithms Assignments of SPPU, Second Year IT Syllabus (2019 pattern)

DSAL This repository contains the Assignment code of Data Structures and Algorithms Assignments of SPPU, Second Year IT Syllabus (2019 pattern) Assign

Apr 6, 2022
libsrt is a C library for writing fast and safe C code, faster.

libsrt is a C library for writing fast and safe C code, faster. It provides string, vector, bit set, set, map, hash set, and hash map handling. Suitable for soft and hard real-time. Allows both heap and stack allocation. *BETA* (API still can change: suggestions are welcome)

Sep 12, 2022
Nodable is node-able. The goal of Nodable is to provide an original hybrid source code editor, using both textual and nodal paradigm.
Nodable is node-able. The goal of Nodable is to provide an original hybrid source code editor, using both textual and nodal paradigm.

Nodable is node-able ! Introduction: The goal of Nodable is to provide an original hybrid source code editor, using both textual and nodal paradigm. I

Aug 29, 2022
Tau is a fast syntax highlighter capable of emitting HTML.

tau - a reasonably fast (wip) syntax highlighter. Tau is a fast syntax highlighter capable of emitting HTML. It highlights the following languages: py

Apr 21, 2022
UT: C++20 μ(micro)/Unit Testing Framework
UT: C++20 μ(micro)/Unit Testing Framework

"If you liked it then you "should have put a"_test on it", Beyonce rule [Boost::ext].UT / μt | Motivation | Quick Start | Overview | Tutorial | Exampl

Sep 22, 2022
UT: C++20 μ(micro)/Unit Testing Framework
UT: C++20 μ(micro)/Unit Testing Framework

"If you liked it then you "should have put a"_test on it", Beyonce rule UT / μt | Motivation | Quick Start | Overview | Tutorial | Examples | User Gui

Sep 21, 2022
Tool that generates unit test by C/C++ source code, trying to reach all branches and maximize code coverage

What is UTBotCpp? UTBotCpp generates test cases by code, trying to cover maximum statements and execution paths. We treat source code as source of tru

Sep 21, 2022
C++ Unit Testing Easier: A Header-only C++ unit testing framework

CUTE C++ Unit Testing Easier: A Header-only C++ unit testing framework usually available as part of the Cevelop C++ IDE (http://cevelop.com) Dependenc

Aug 31, 2022
A testing micro framework for creating function test doubles

Fake Function Framework (fff) A Fake Function Framework for C Hello Fake World! Capturing Arguments Return Values Resetting a Fake Call History Defaul

Sep 19, 2022