C++11 TAP13 Unit Testing Framework

cipra is a simple, TAP-compatible Unit Testing Framework for C++. cipra is Free and Open Source Software, released under a 3-clause BSD-style license. It's written in 100% standard C++11 and is only a couple header files, making it easy to include in your C++11 project.

TAP, the Test Anything Protocol, is a standard output format for software unit test frameworks that was originally designed for Perl, but can serve other languages. It has a rich number of tools ("harnesses") that parse TAP formatted output and do useful things with it. TAP, however, is equally human-readable.

The name cipra (pronounced /ˈʃi.pɾaː/ "SHEE-prah") comes from the lojban phrase "lo cipra", which means "the test". It is properly written with an initial minuscule 'c', even when at the start of a sentence.

Click here to download the latest version.


2014-02-17: Sourceforge source viewer is down

We appologize for the inconvenience. It seems to be related to this Sourceforge bug. You can still clone our git repository to view the source code, but at present, there is no web interface to view it.

2013-10-18: Bugfix 1.2.1 Released

2013-08-14: Version 1.2 Released

2013-04-29: Version 1.1 Released

2013-04-13: Version 1.0 Released



cipra's API is heavily influenced by Perl's Test::More module. A full tutorial can be found in the documentation here.

// Uncomment on GCC and other compilers that support abi:: functions.
//#define CIPRA_CXA_ABI
#include <cipra.hpp>

int main(int argc, char* argv[])
    struct my_fixture : cipra::fixture {
        virtual void test() override // define this function to run tests
            plan(17); // Run 17 tests.

            ok([]() { return true; }, "ok() succeeds on true");
            ok([]() { return false; }, "ok() fails on false");
            ok([]() { throw 0; return true; }, "ok() fails on throw");

            ok(true, "ok() with just boolean arguments works");

            throws([]() { throw 0; }, "throws() detects int throw");
            throws([]() { }, "throws() fails on no throw");

            throws<int>([]() { throw 0; }, "throws<int>() detects int throw");
            throws<int>([]() { throw 'a'; },
                       "throws<int>() fails on char throw");
            throws<int>([]() { }, "throws<int>() fails on no throw");

            nothrows([]() { }, "nothrows() accepts no throw");
            nothrows([]() { throw 0; }, "nothrows() fails on int throw");

            nothrows<int>([]() { throw 'a'; },
                         "nothrows<int>() accepts char throw");
            nothrows<int>([]() {}, "nothrows<int>() accepts no throw");
            nothrows<int>([]() { throw 0; },
                         "nothrows<int>() fails on int throw");

            // See the file variadic.cpp for examples of the
            // new_ok<>() function.

            pass("Will pass automatically.");
            pass("No matter what.");
            fail("Always fails.");

            is(5, 5, "5 == 5");
            is(5, 6, "5 == 6; this should fail.");
            is(std::string("cipra"), std::string("cipra"), "String equality");

            isnt(5, 6, "5 != 6");
            isnt(5, 5, "5 != 5; this should fail.");
            isnt(std::string(";,.pyfgcrl"), std::string("qwertyuiop"),
                 "Programmer Dvorak is not QWERTY");
    } test;

    return test.run();


cipra is written in portable C++11 code: it only requires a C++11 compiler (like modern versions of GCC and Clang). It optionally supports a compatibility mode for MSVC 2012, which lacks variadic templates, but we encourage you to upgrade to the November 2012 CTP or the newest preview.

cipra is Free and Open Source Software, and as such, we encourage you to use it or a modified version in your own projects, subject to certain licensing terms and conditions. These terms can be found in the COPYING files in the project root directory. Please be certain you understand these terms before using cipra in your own project. cipra's source code is licensed under a BSD-style 3-clause license, while it's documentation is licensed under various Creative Comons licenses.

To download our latest release, click here. Older releases, MD5 and SHA1 checksums, and file sizes can be found in our downloads space.

Alternatively, you can view our git repository online or run the following command to clone it locally:

$ git clone git://git.code.sf.net/p/cipra/code cipra-code


We welcome patches and pull-requests! Both can be emailed directly to Patrick M. Niedzielski at PatrickNiedzielski AT gmail DOT com. If you'd like to get involved as a member of the team, send an email with your Sourceforge user name.

We also welcome bug report and feature requests. Please open a ticket if you find a bug or want a feature implemented.

There is currently only one mailing list for cipra:

Low traffic. This list is used to announce new vrsions of cipra and possibly other important announcements. Anyone may subscribe to this mailing list, but only moderators may post. View or search the archives, or subscribe.

Future Plans

cipra's 1.x interface is rather heavy-weight: first you have to declare a new class that inherits from cipra::fixture. Then, you need to declare a test() member function that contains your tests. Finally, you need to instantiate this class and run the test. Compared with Perl's Test::More, this has a significant amount of boiler-plate code.

Also, cipra currently uses diagnostics to output information like expected values or caught exceptions. Since TAP13, diagnostics were deprecated in favor of YAMLish blocks, which have greater flexibility and parsability.

Furthermore, with current versions of cipra, if the test program itself prints to stdout or stderr, the TAP output becomes dirty. Good TAP consumers should ignore all lines that don't match /^ok|^not ok/, but a better solution would be to capture the output and print it in a YAMLish block.

cipra 2.0 should fix all of these problems. Ideas further into the future include writing a TAP consumer in C++11, so that cipra can be used in environments where Perl's prove command (or some other TAP consumer) is not installed, making output asychronous to allow for testing of concurrent applications, and possibly more compiler support.

External Links