Skip to content

vpiotr/utest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Overview

Build Status License C++11

Micro (header-only) library for unit testing.

Library author: Piotr Likus

Created: 31/08/2020

Initial code based on blog post by Bastian Rieck, see: https://bastian.rieck.me/blog/posts/2017/simple_unit_tests/

Requirements

This library requires C++11 or later and has been tested on Linux Mint 20 and other modern Linux distributions.

Key C++11 features used:

  • Lambda expressions
  • auto keyword for type deduction
  • Uniform initialization syntax ({})
  • std::enable_if for SFINAE
  • std::chrono for timing
  • nullptr and std::nullptr_t
  • static_assert for compile-time checks
  • decltype for type deduction

The library is fully compatible with C++11, C++14, C++17, and C++20 standards.

Project home

https://github.com/vpiotr/utest

Build and Installation

Building the demo and tests

mkdir _build && cd _build cmake .. cmake --build . # Run the demo ./bin/utest_demo # Run the tests ctest # or make test

Installing the library

mkdir _build && cd _build cmake .. cmake --build . sudo cmake --install .

Helper Scripts

The project includes several helper scripts for common tasks:

  • rebuild.sh - Clean and rebuild the entire project from scratch
  • run_demos.sh - Execute all demo programs sequentially with detailed output and summary
  • run_tests.sh - Run all test executables with summary reporting (use --detailed for full output)
  • build_docs.sh - Generate Doxygen documentation in HTML format

Usage examples:

# Quick rebuild ./rebuild.sh # Run all demos with colored output ./run_demos.sh # Run tests with summary only ./run_tests.sh # Run tests with detailed output ./run_tests.sh --detailed # Generate documentation ./build_docs.sh

CMake Options

  • UTEST_BUILD_DEMO: Build the demo project (ON by default)
  • UTEST_BUILD_TESTS: Build the tests (ON by default)

Example with options:

cmake -DUTEST_BUILD_DEMO=OFF -DUTEST_BUILD_TESTS=ON ..

Integration

C++11 Compatibility

This library is fully compatible with C++11 and later standards. To use it in your project, ensure your compiler supports C++11:

# In your CMakeLists.txt set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON)

Or with compiler flags:

g++ -std=c++11 your_tests.cpp clang++ -std=c++11 your_tests.cpp

The library leverages modern C++11 features for clean, expressive test code while maintaining compatibility with older codebases.

Method 1: Direct inclusion

Simply copy include/utest.h into your project and include it.

Method 2: CMake integration

Add utest as a subdirectory in your CMake project:

add_subdirectory(path/to/utest) target_link_libraries(your_project PRIVATE utest)

Or, if installed:

find_package(utest REQUIRED) target_link_libraries(your_project PRIVATE utest::utest)

How to use library

This library is header-only solution, so you just need to include single header file utest.h in your test runner code.

Create a runner application executing single function which executes all tests plus adds prolog (UTEST_PROLOG) and epilog (UTEST_EPILOG) code. Each test must be prepared as a function called test_aaa and must be registered using UTEST_FUNC macro.

Example complete test runner:

#include "utest.h" void test_assert_equals() { int a{42}; UTEST_ASSERT_EQUALS(a, 42); } int run_all_tests() { UTEST_PROLOG(); UTEST_FUNC(assert_equals); UTEST_EPILOG(); } int main() { return run_all_tests(); }

See tests in "tests" subdirectory and the "demo" directory for more examples.

Demo Project

The demo project demonstrates various aspects of the library across multiple executable demos:

Available Demos

1. Core Features Demo (utest_demo)

  • File: demo_core_features.cpp
  • Executable: ./bin/utest_demo
  • Features demonstrated:
    • Basic assertions (equality, true/false)
    • Assertions with custom error messages
    • Exception testing with lambda functions
    • Complex test scenarios with collections and vectors
    • String comparisons and container operations

2. Unicode Checkmarks Demo (demo_unicode_checkmarks)

  • File: demo_unicode_checkmarks.cpp
  • Executable: ./bin/demo_unicode_checkmarks
  • Features demonstrated:
    • Default Unicode checkmark output format
    • Test grouping with UTEST_FUNC_DEF2 syntax
    • Multiple grouped test scenarios
    • Various assertion types (GT, GTE, NEQ, etc.)

3. Verbose Mode Demo (demo_verbose_mode)

  • File: demo_verbose_mode.cpp
  • Executable: ./bin/demo_verbose_mode
  • Features demonstrated:
    • Verbose output mode showing test names before execution
    • Performance timing measurements
    • Grouped test organization and display
    • Test progress tracking

4. Failure Handling Demo (demo_with_failure)

  • File: demo_with_failure.cpp
  • Executable: ./bin/demo_with_failure
  • Features demonstrated:
    • Intentional test failures for error reporting demonstration
    • Comprehensive error messages with file/line information
    • Mixed passing and failing tests in the same runner
    • Error handling and exit code behavior

5. No Tests Scenario Demo (demo_no_tests)

  • File: demo_no_tests.cpp
  • Executable: ./bin/demo_no_tests
  • Features demonstrated:
    • Behavior when no tests are registered or executed
    • Default failure handling for empty test suites
    • Use of UTEST_ALLOW_EMPTY_TESTS() for conditional testing

To run all demos:

mkdir _build && cd _build cmake .. cmake --build . ./run_demos.sh

To run individual demos:

./bin/utest_demo # Core features demo ./bin/demo_unicode_checkmarks # Unicode checkmarks demo  ./bin/demo_verbose_mode # Verbose mode demo ./bin/demo_with_failure # Failure handling demo ./bin/demo_no_tests # No tests scenario demo

Test Output

There are two ways of viewing test results:

  1. As standard application - from IDE or console, this will show which tests are failing, example:
OK: Test [assert_true] succeeded OK: Test [assert_false] succeeded OK: Test [assert_true_msg] succeeded OK: Test [assert_false_msg] succeeded Error: Test [assert_equals] failed!, error: Assertion failed, at /home/piotr/tmp/utest/tests/testUTest.cpp:33 in void test_assert_equals(): 42 != 43 OK: Test [assert_equals_msg] succeeded OK: Test [assert_throws] succeeded OK: Test [assert_throws_msg] succeeded Failures! 
  1. As make test or ctest - this will only show which runners are failing
piotr@piotr-Prec-M47:~/tmp/utest/_build$ make test Running tests... Test project /home/piotr/tmp/utest/_build Start 1: testUTest, 1/1 Test #1: testUTest, .......................***Failed 0.00 sec 0% tests passed, 1 tests failed out of 1 Total Test time (real) = 0.00 sec The following tests FAILED: 1 - testUTest, (Failed) Errors while running CTest make: *** [Makefile:84: test] Error 8 

Available macros

Core Macros

  • UTEST_PROLOG() - Initialize the test framework
  • UTEST_EPILOG() - Finalize and report test results
  • UTEST_FUNC(name) - Run a test function (function should be named test_name)
  • UTEST_FUNC2(group, name) - Run a grouped test function (function should be named test_group_name)

Configuration Macros

  • UTEST_ALLOW_EMPTY_TESTS() - Allow test runner to succeed even when no tests are run
  • UTEST_USE_ASCII_CHECKMARKS() - Use ASCII [OK]/[FAIL] instead of Unicode checkmarks
  • UTEST_SHOW_PERFORMANCE() - Enable performance timing for each test
  • UTEST_ENABLE_VERBOSE_MODE() - Show test names before execution (useful for debugging)

Function Definition Macros

  • UTEST_FUNC_DEF(name) - Define a test function: void test_name()
  • UTEST_FUNC_DEF2(group, name) - Define a grouped test function: void test_group_name()

Assertion Macros

  • UTEST_ASSERT_TRUE(condition) - Assert that condition is true
  • UTEST_ASSERT_TRUE_MSG(condition, msg) - Assert that condition is true, with custom message
  • UTEST_ASSERT_FALSE(condition) - Assert that condition is false
  • UTEST_ASSERT_FALSE_MSG(condition, msg) - Assert that condition is false, with custom message
  • UTEST_ASSERT_EQUALS(a, b) - Assert that a equals b
  • UTEST_ASSERT_EQUALS_MSG(a, b, msg) - Assert that a equals b, with custom message
  • UTEST_ASSERT_NOT_EQUALS(a, b) - Assert that a does not equal b
  • UTEST_ASSERT_NOT_EQUALS_MSG(a, b, msg) - Assert that a does not equal b, with custom message
  • UTEST_ASSERT_STR_EQUALS(a, b) - Assert that strings a and b are equal
  • UTEST_ASSERT_STR_NOT_EQUALS(a, b) - Assert that strings a and b are not equal
  • UTEST_ASSERT_GT(a, b) - Assert that a is greater than b
  • UTEST_ASSERT_GTE(a, b) - Assert that a is greater than or equal to b
  • UTEST_ASSERT_LT(a, b) - Assert that a is less than b
  • UTEST_ASSERT_LTE(a, b) - Assert that a is less than or equal to b
  • UTEST_ASSERT_THROWS(F) - Assert that function F throws an exception
  • UTEST_ASSERT_THROWS_MSG(F, MSG) - Assert that function F throws an exception, with custom message
  • UTEST_ASSERT_DOES_NOT_THROW(F) - Assert that function F does not throw an exception
  • UTEST_ASSERT_DOES_NOT_THROW_MSG(F, MSG) - Assert that function F does not throw an exception, with custom message
  • UTEST_ASSERT_NULL(ptr) - Assert that pointer ptr is null
  • UTEST_ASSERT_NOT_NULL(ptr) - Assert that pointer ptr is not null

Convenient Aliases

  • UTEST_ASSERT_EQ(a, b) - Alias for UTEST_ASSERT_EQUALS
  • UTEST_ASSERT_NEQ(a, b) - Alias for UTEST_ASSERT_NOT_EQUALS
  • UTEST_ASSERT_SEQ(a, b) - Alias for UTEST_ASSERT_STR_EQUALS
  • UTEST_ASSERT_SNEQ(a, b) - Alias for UTEST_ASSERT_STR_NOT_EQUALS

Build Organization

The build system organizes binaries into dedicated subdirectories:

  • Main demo: bin/utest_demo
  • Additional demos: bin/demo_unicode_checkmarks, bin/demo_verbose_mode, bin/demo_with_failure, bin/demo_no_tests
  • Tests: bin/tests/test_*

Handling No Tests Scenario

By default, if no tests are run, the test framework will exit with failure. This can be changed using:

UTEST_PROLOG(); UTEST_ALLOW_EMPTY_TESTS(); // Allow success even with no tests // No test functions called here UTEST_EPILOG(); // Will return SUCCESS instead of FAILURE

This is useful for:

  • Conditional test execution
  • Test suites that may be empty under certain conditions
  • Template-based test generation where some configurations may produce no tests

New Features

Test Grouping

Tests can be organized into groups using UTEST_FUNC_DEF2 and UTEST_FUNC2:

// Define grouped test functions UTEST_FUNC_DEF2(ModuleA, Feature1) { UTEST_ASSERT_TRUE(some_condition); } UTEST_FUNC_DEF2(ModuleA, Feature2) { UTEST_ASSERT_EQUALS(calculate(), expected); } // Run grouped tests UTEST_FUNC2(ModuleA, Feature1); UTEST_FUNC2(ModuleA, Feature2);

In the test summary, tests with the same group name will be displayed together:

ModuleA: [OK] Feature1 [OK] Feature2 

Performance Timing

Enable performance timing to see how long each test takes:

UTEST_PROLOG(); UTEST_SHOW_PERFORMANCE(); // Enable timing UTEST_FUNC(my_test); UTEST_EPILOG();

Output will show timing information:

[OK] Test [my_test] succeeded (1.234ms) 

Verbose Mode

Enable verbose mode to see test names before execution:

UTEST_PROLOG(); UTEST_ENABLE_VERBOSE_MODE(); // Show test names before execution UTEST_FUNC(my_test); UTEST_EPILOG();

Output will show test names before execution:

Running test: my_test [OK] Test [my_test] succeeded (1.234ms) 

For grouped tests:

Running test: GroupName::TestName [OK] Test [GroupName::TestName] succeeded (1.234ms) 

ASCII Checkmarks

For environments that don't support Unicode characters:

UTEST_PROLOG(); UTEST_USE_ASCII_CHECKMARKS(); // Use [OK]/[FAIL] instead of Unicode checkmarks UTEST_FUNC(my_test); UTEST_EPILOG();

String and Lambda Testing

The library now supports comprehensive string testing and modern C++ features:

// String testing with std::string and const char* void test_strings() { std::string str = "hello"; UTEST_ASSERT_EQUALS(str, "hello"); UTEST_ASSERT_EQUALS("world", "world"); } // Lambda and functor testing void test_lambdas() { auto throwing_lambda = []() { throw std::exception(); }; UTEST_ASSERT_THROWS(throwing_lambda); auto safe_lambda = []() { return 42; }; UTEST_ASSERT_DOES_NOT_THROW(safe_lambda); }

Compatibility Notes

C++11 Features Used

The library takes advantage of several C++11 features to provide clean, modern syntax:

  • Lambda expressions: For exception testing and complex test scenarios
  • Auto keyword: For type deduction in test code
  • Uniform initialization: For cleaner object construction
  • std::chrono: For high-precision timing measurements
  • nullptr: For safe null pointer testing
  • static_assert: For compile-time type checking
  • SFINAE with decltype: For template metaprogramming

Compiler Support

Tested with:

  • GCC 4.8+ (C++11 support)
  • Clang 3.3+ (C++11 support)
  • MSVC 2013+ (C++11 support)
  • Any compiler with full C++11 support

License

See LICENSE.txt

About

Unit testing (header-only) library for C++

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published