Clion Boost

Posted : admin On 1/26/2022
Uncategorized
  1. Clion Add Include Path
  2. Clion Import Cmake Project
  3. Clion Boost
  4. Clion Boosts
  5. Clion Add External Library

Frameworks Google Test. Google Test and Google Mock are a pair of powerful unit testing tools: the framework is portable, it. Boost unit testing framework (Boost.Test) is a part of the Boost library. It is a fully-functional. The main difference of Catch2 from Google. CLion is a cross-platform IDE which natively supports C and C, libc and Boost. It offers instant navigation to a symbol's declaration or usages, code generation for constructors/destructors, operators and more. There are dozens of refactorings, code analysis (including Data Flow Analysis and Clang-Tidy integration) and integration with GDB and LLDB. To help you focus on code and raise your productivity, CLion has handy keyboard shortcuts for nearly all its features, actions, and commands. Vim fans are welcome to install the Vim-emulation plugin. Local and remote work With an embedded terminal, run any command without leaving the IDE, locally or remotely using the SSH protocol. Boost.Build support for JetBrains CLion IDE. Contribute to grafikrobot/clion-boost-build development by creating an account on GitHub. For C language the top three unit test frameworks are: Google Test (37%), Boost.Test (8%), CppUnit (8%). For C – Google Test (45%), Boost.Test (26%), CppUnit (11%). CLion already supports Google Test and Catch unit test frameworks. And now it comes with the Boost.Test support!

Hi all,

Welcome to the newest edition of C++ Annotated and its companion, the No Diagnostic Required YouTube show! They are now available in the following formats:

  • The regular digest published monthly on this blog (use the form on the right to subscribe).
  • C++ Annotated emails, which you can subscribe to by filling out this form.
  • The No Diagnostic Required show here in the blog or on YouTube. To stay tuned, follow us on Twitter.
  • You should be able to find us in most podcast players by searching for 'No Diagnostic Required' (see the list on our website).

December news

Watch the new episode of No Diagnostic Required below, or just read on!

20 years of LLVM

How long have you been aware of the LLVM project, or maybe contributed to it? Turns out it started a full 20 years ago! All are invited to share their experiences with LLVM in the dedicated tweet that celebrates the date. Don’t forget to use the #CelebrateLLVM hashtag.

Because of that thread, people often start with LLVM as a backend for their programming language, such as Event, a language for rule-based complex-event processing on distributed networks, or Julia, a language for technical computing. At JetBrains, we’re also building Kotlin/Native for Native on top of the LLVM platform.

But LLVM is much more than a compiler backend. It’s also a set of various tools like analyzers, formatter, debugger, linker, an implementation of the standard library, OpenCL, OpenMP, and more. It’s impressive to see the ecosystem growing and getting more contributions from the community and more developers relying on LLVM in all sorts of projects.

Our users often ask us how to set up Clang on Windows without Microsoft Visual Studio installed. Clang from the LLVM repo is built using MSVC, and all the built-in macros and include search paths are set up for use with Visual Studio. However, the MSYS2 Clang works with the mingw-w64 toolchain nicely. Read on about how to configure it.

More 20s. C++20 is officially published!

Boost cpp library

While C++20 is already in use in many projects, the newest standard was officially published in December. Which means you can now officially buy its final version!

If you are curious about what the final set is like, check out the overview at cppreference, for example. There are many awesome things inside, from big ones like Coroutines (co_yes!), Modules, and Concepts to language features like the 3-way comparison, feature test macros, constevel/constinit, new attributes ([[no_unique_address]] is definitely great!), as well as dozens of library features like Ranges, formatting library, Calendar, and TimeZone. And I just remembered a nice old thread on Reddit discussing what folks are most excited about in C++20. What are your favorites? Let us know in the comments!

There are many talks and articles on each of these new additions, but more important is what exactly is supported in the compiler you are using. That means it’s time to check out the recent compiler releases and implementation status (for Clang, for GCC, for MSVC).

C++20’s 3-way comparison

Chances are you’ve heard about the new 3-way comparison, also known as the spaceship operator. You might even know it makes the comparison implementation in C++ much more convenient. But how? And what problem does it address?

The biggest benefit is probably that you can implement less if you customize the comparison. Before C++20, you had to implement two equality operators and four relational operators, and even more if you compared different types. Now just two are enough: equality and the new spaceship operator. And it’s not just that you save some time coding, but now member comparison operators can handle heterogeneous comparisons, too!

Igor Akhmetov spent the whole 2020.3 release cycle implementing support for the 3-way comparison operator in ReSharper C++. In this article, he describes what ReSharper C++ brings to its users in terms of support, such as the updated Create Operator from Usage action, quick-fixes to add a missing <compare> header, and more.

Boost 1.75 release

Boost is often called a playground for the future C++ standard updates, which provides an interesting perspective from which to view its release. Version 1.75 that came out in December brought three new libraries to Boost:

  • JSON: for JSON parsing and serialization in C++11. Interestingly, it can be header-only and doesn’t have Boost dependencies (without Boost it requires C++17).
  • LEAF: an error-handling library for C++11. Its biggest benefits include: no dynamic memory allocations, the transport of arbitrary error types independent of the call stack depth (the library is designed with the use case of a trivial success-or-failure flow in mind, when callers of the function do not handle the errors), and an ability to use the library w/o exception handling. And again, a single-header format w/o dependencies is possible.
  • PFR: a C++14 library for very basic reflection. The best thing about it is that it gives you access to structure elements by index and provides other std::tuple-like methods for user-defined types – without macro or boilerplate code! And again, it’s a header-only library without dependencies on Boost itself. Note that pre-C++14 compilers are not supported.

Now let’s talk about a few events and shows that happened recently.

Two’s Complement (podcast)

With so many of us being stuck at home for extended periods this year, more new podcasts are emerging from the community. Last month we launched No Diagnostic Required and mentioned TLB Hit and ADSP. This month we see Two’s Complement from Matt Godbolt and Ben Rady. It isn’t, strictly speaking, a C++ podcast, but given how well-known Matt is in the C++ community, I thought it was worth sharing. In the first episode – episode 0, of course – Ben and Matt talk about their early careers and how they got to where they are now.

CoSy Tech (New systems language conference)

Just as we reach podcast overload, we’ve also been overloaded with conferences that are relevant to the C++ community for some time. So what better time to start another one? But CoSy Tech is a bit different. JeanHeyd Meneide, a.k.a. ThePhd, is introducing a conference for systems language programmers – so not just C++, but C, Rust, and even Lua and Zig. But, perhaps more significantly, he is prioritizing diversity and inclusion. That may not sound particularly unique these days. Other conferences, like C++ on Sea, have diversity and inclusion at the heart of their mission statement. But CoSy Tech – a collaboration between JeanHeyd and Shepherd Oasis – aims to take it further still. We wish JeanHeyd the best of luck.

CLion AMA on Reddit

In December 2020, the CLion team held a Q&A session on Reddit that was dedicated to the recent CLion 2020.3 release and our plans for 2021. Seven team members (and a few more behind the scenes) answered about 35 questions and participated in discussions spread over 118 comments in the threads under the post. We then posted a follow-up.

Interestingly, readers were very much interested in Meson and Bazel project models. According to our Developer Ecosystem study, these models account for 2-4% percent each of the overall usage. Bazel seems to be steadily growing over the years and is mostly driven by Google. Meson is used in such projects as AQEMU (a Qt GUI for QEMU virtual machines), GTK+ (the multi-platform toolkit used by GNOME), Pacman (a package manager for Arch Linux), and Wayland. While CLion doesn’t have any immediate plans on either of these, the compilation database workaround for Meson and a Google plugin for Bazel seem like workable options for the time being.

Another interesting aspect is the interest in cross-debuggers, like between Python and C++ or between Java and C++. We’re looking to identify the trending use cases, apart from the obvious Android and NDK specific one for Java/C++, and things like Cython for Python/C++. If you know of any others, please let us know in the comments.

An interview question that could easily trap you

This might be (at first glance) an obvious interview question, but as the reddit thread confirms, it’s much trickier than many might imagine.

There’s code dereferencing a null pointer and it’s wrapped in a try-catch block. The catch-branch is printing to the output stream. Do we get the output or not? Dereferencing a pointer is Undefined Behavior, according to the standard. But then it comes down to each compiler to implement this case, and that’s where the details can make a difference. An interesting observation is that a segmentation fault can still cause the corresponding message to be printed, instead of calling the C++ exception handler. Different behavior is still possible for MSVC, which has the /EH flag that exactly specifies the exception-handling mechanism and can lead to catch() actually catching both structured (asynchronous) and standard C++ (synchronous) exceptions.

That’s it for today. Enjoy the holidays, and we’ll see you in January!

The JetBrains C++ team
The Drive to Develop

This tutorial gives an overview of the unit testing approach and discusses four frameworks supported by CLion: Google Test, Boost.Test, Catch2, and Doctest. The Unit Testing in CLion part will guide you through the process of including these frameworks into your project and describe the instruments that CLion provides to help you work with unit testing.

Basics of unit testing

Unit testing aims to check individual units of your source code separately. A unit here is the smallest part of code that can be tested in isolation, for example, a free function or a class method.

Unit testing helps:

  • Modularize your code

    As code's testability depends on its design, unit tests facilitate breaking it into specialized easy-to-test pieces.

  • Avoid regressions

    When you have a suite of unit tests, you can run it iteratively to ensure that everything keeps working correctly every time you add new functionality or introduce changes.

  • Document your code

    Running, debugging, or even just reading tests can give a lot of information about how the original code works, so you can use them as implicit documentation.

A single unit test is a method that checks some specific functionality and has clear pass/fail criteria. The generalized structure of a single test looks like this:

Test (TestGroupName, TestName) { 1 - setup block 2 - running the under-test functionality 3 - checking the results (assertions block)}

Good practices for unit testing include:

  • Creating tests for all publicly exposed functions, including class constructors and operators.

  • Covering all code paths and checking both trivial and edge cases, including those with incorrect input data (see negative testing ).

  • Assuring that each test works independently and does't prevent other tests from execution.

  • Organizing tests in a way that the order in which you run them doesn't affect the results.

It's useful to group test cases when they are logically connected or use the same data. Suites combine tests with common functionality (for example, when performing different cases for the same function). Fixture classes help organize shared resources for multiple tests. They are used to set up and clean up the environment for each test within a group and thus avoid code duplication.

Unit testing is often combined with mocking. Mock objects are lightweight implementations of test targets, used when the under-test functionality contains complex dependencies and it is difficult to construct a viable test case using real-world objects.

Frameworks

Manual unit testing involves a lot of routines: writing stub test code, implementing main(), printing output messages, and so on. Unit testing frameworks not only help automate these operations, but also let you benefit from the following:

  • Manageable assertion behavior

    With a framework, you can specify whether or not a failure of a single check should cancel the whole test execution: along with the regular ASSERT, frameworks provide EXPECT/CHECK macros that don't interrupt your test program on failure.

  • Various checkers

    Checkers are macros for comparing the expected and the actual result. Checkers provided by testing frameworks often have configurable severity (warning, regular expectation, or a requirement). Also, they can include tolerances for floating point comparisons and even pre-implemented exception handlers that check raising of an exception under certain conditions.

  • Tests organization

    With frameworks, it's easy to create and run subsets of tests grouped by common functionality (suites) or shared data (fixtures). Also, modern frameworks automatically register new tests, so you don't need to do that manually.

  • Customizable messages

    Frameworks take care of the tests output: they can show verbose descriptive outputs, as well as user-defined messages or only briefed pass/fail results (the latter is especially handy for regression testing).

  • XML reports

    Most of the testing frameworks provide exporting results in XML format. This is useful when you need to further pass the results to a continuous integration system such as TeamCity or Jenkins.

Clion

Clion Add Include Path

There are many unit testing frameworks for C++. Further on, we will focus on some of the most popular: Google Test, Boost.Test, Catch2, and Doctest. All four are integrated in CLion, but before we dive into the integration details, let's briefly cover the essential points of each framework.

Google Test

Google Test and Google Mock are a pair of powerful unit testing tools: the framework is portable, it includes a rich set of fatal and non-fatal assertions, provides instruments for creating fixtures and test groups, gives informative messages, and exports the results in XML. Probably the only drawback is a need to build gtest/gmock in your project in order to use it.

Assertions

In Google Test, the statements that check whether a condition is true are referred to as assertions. Non-fatal assertions have the EXPECT_ prefix in their names, and assertions that cause fatal failure and abort the execution are named starting with ASSERT_. For example:

TEST (SquareTest /*test suite name*/, PosZeroNeg /*test name*/) { EXPECT_EQ (9.0, (3.0*2.0)); // fail, test continues ASSERT_EQ (0.0, (0.0)); // success ASSERT_EQ (9, (3)*(-3.0)); // fail, test interrupts ASSERT_EQ (-9, (-3)*(-3.0));// not executed due to the previous assert }

Some of the asserts available in Google Test are listed below (in this table, ASSERT_ is given as an example and can be switched with EXPECT_ ):

LogicalASSERT_TRUE(condition)
ASSERT_FALSE(condition)
General comparisonASSERT_EQ(expected, actual) / ASSERT_NE(val1, val2)
ASSERT_LT(val1, val2) / ASSERT_LE(val1, val2)
ASSERT_GT(val1, val2) / ASSERT_GE(val1, val2)
Float point comparisonASSERT_FLOAT_EQ(expected, actual)
ASSERT_DOUBLE_EQ(expected, actual)
ASSERT_NEAR(val1, val2, abs_error)
String comparisonASSERT_STREQ(expected_str, actual_str) / ASSERT_STRNE(str1, str2)
ASSERT_STRCASEEQ(expected_str, actual_str) / ASSERT_STRCASENE(str1, str2)
Exception checkingASSERT_THROW(statement, exception_type)
ASSERT_ANY_THROW(statement)
ASSERT_NO_THROW(statement)

Also, Google Test supports predicate assertions which help making output messages more informative. For example, instead of EXPECT_EQ(a, b) you can use a predicate function that checks a and b for equivalency and returns a boolean result. In case of failure, the assertion will print values of the function arguments:

Predicate assertion example

bool IsEq(int a, int b){ if (ab) return true; else return false; } TEST(BasicChecks, TestEq) { int a = 0; int b = 1; EXPECT_EQ(a, b); EXPECT_PRED2(IsEq, a, b); }

Output

Failure Value of: b Actual: 1 Expected: a Which is: 0Failure IsEq(a, b) evaluates to false, where a evaluates to 0 b evaluates to 1

In EXPECT_PRED2 above, predN is a predicate function with N arguments. Google Test currently supports predicate assertions of arity up to 5.

Clion Import Cmake Project

Fixtures

Google tests that share common objects or subroutines can be grouped into fixtures. Here is how a generalized fixture looks like:

class myTestFixture: public ::testing::test { public: myTestFixture( ) { // initialization; // can also be done in SetUp() } void SetUp( ) { // initialization or some code to run before each test } void TearDown( ) { // code to run after each test; // can be used instead of a destructor, // but exceptions can be handled in this function only } ~myTestFixture( ) { //resources cleanup, no exceptions allowed } // shared user data };

When used for a fixture, a TEST() macro should be replaced with TEST_F() to allow the test to access the fixture's members and functions:

Setting up

There are several options you can choose from when adding Google Test into a CMake project:

  • Download the sources and copy them into the project structure.

    This is probably the quickest way to start working with the framework, but there will be no automatic synchronization with the Google Test repository, so you will have to take care of keeping the sources up to date.

    You can find an example of using this approach in the sample project below.

  • If you are working with git, you can add gtest as a git submodule for your project.

  • Another option is to use CMake to download gtest as part of the build's configuration step.

To learn more about Google Test, explore the samples in the framework's repository. Also, take a look at Advanced options for details of other noticeable Google Test features such as value-parametrized tests and type-parameterized tests.

Boost.Test

Boost unit testing framework (Boost.Test) is a part of the Boost library. It is a fully-functional and scalable framework, with wide range of assertion macros, XML output, and other features. Boost.Test itself lacks mocking functionality, but it can be combined with stand-alone mocking frameworks such as gmock.

Checkers

For most of the Boost.Test checkers, you can set a severity level:

  • WARN produces a warning message if the check failed, but the error counter isn't increased and the test case continues.

  • CHECK reports an error and increases the error counter when the check is failed, but the test case continues.

  • REQUIRE is used for reporting fatal errors, when the execution of the test case should be aborted (for example, to check whether an object that will be used later was created successfully).

This way, a Boost checker is usually a macro of the BOOST_[level]_[checkname] format that takes one or several arguments. Basic macros are BOOST_WARN, BOOST_CHECK, and BOOST_REQUIRE. They take one argument of an expression to check, for example:

BOOST_WARN(sizeof(int) sizeof(long)); BOOST_CHECK( i 1 ); BOOST_REQUIRE( j > 5 );

Clion Boost

A few examples of other checkers are given below:

General comparison

BOOST_[level]_EQUAL, BOOST_[level]_NE, BOOST_[level]_GT

In case of failure, these macros not only give the test failed message, but also show the expected and the actual value:

int i = 2; int j = 1; BOOST_CHECK( i j ); // reports the fact of failure only: 'check i j failed' BOOST_CHECK_EQUAL( i, j ); // reports 'check i j failed [2 != 1]'
Float point comparisonBOOST_[level]_CLOSE/ BOOST_[level]_CLOSE_FRACTION/ BOOST_[level]_SMALL
Exception checkingBOOST_[level]_THROW/ BOOST_[level]_NO_THROW/ BOOST_[level]_EXCEPTION

Suites

You can organize Boost tests into suites using the pair of BOOST_AUTO_TEST_SUITE(suite_name) and BOOST_AUTO_TEST_SUITE_END() macros. A simple test suite looks like this:

#define BOOST_TEST_MODULE Suite_example #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_SUITE(TwoTwoFour_suite) BOOST_AUTO_TEST_CASE(testPlus) { BOOST_CHECK_EQUAL(2+2, 4); } BOOST_AUTO_TEST_CASE(testMult) { BOOST_CHECK_EQUAL(2*2, 4); } BOOST_AUTO_TEST_SUITE_END()

Fixtures

To write a fixture with Boost, you can use either a regular BOOST_AUTO_TEST_CASE macro written after a fixture class declaration or a special BOOST_FIXTURE_TEST_CASE macro:

struct SampleF { SampleF() : i(1) { } ~SampleF() { } int i; }; BOOST_FIXTURE_TEST_CASE(SampleF_test, SampleF) { // accessing i from SampleF directly BOOST_CHECK_EQUAL(i, 1); BOOST_CHECK_EQUAL(i, 2); BOOST_CHECK_EQUAL(i, 3); }

Setting up

You can choose between three usage variants for the framework: header-only, static library, or shared library. When picking the most suitable option, keep in mind that Boost.Test used as header-only might require significant compilation time.

Find an example of the shared library usage variant in the sample project below (switch to the Boost.Test tab).

Catch2

The main difference of Catch2 from Google and Boost is that it's a header-only testing system: to create tests with Catch2, you need to download and include only one header file, catch.hpp. The framework's name stands for C++ Automated Test Cases in Headers (version two). CLion supports Catch versions 1.7.2 and later.

As well as Boost.Test, Catch2 doesn't provide mocking functionality. However, you can combine it with standalone mocking frameworks such as Hippomocks, FakeIt, or Trompeloeil.

Sample test

The following example shows a simple test written with Catch2:

#define CATCH_CONFIG_MAIN // provides main(); this line is required in only one .cpp file #include 'catch.hpp' int theAnswer() { return 6*9; } // function to be tested TEST_CASE( 'Life, the universe and everything', '[42][theAnswer]' ) { REQUIRE(theAnswer() 42); }

In the above example, Life, the universe and everything is a free-form test name, which must be unique. The second argument of the TEST_CASE macro is a combination of two tags, [42] and [theAnswer]. Both test name and tags are regular strings that are not limited to be valid C++ identifiers. You can run collections of tests by specifying a wildcarded test name or a tag expression.

Clion Boost

Notice the assertion line REQUIRE(theAnswer() 42). Unlike other frameworks, Catch2 doesn't have a collection of asserts to capture various conditional forms. Instead, it parses the actual C/C++ code of the conditional expression and also uses it to describe the result:

...Failure: REQUIRE(theAnswer() 42)with expansion: 54 42

The REQUIRE macro aborts a test on failure, while the alternative CHECK macro only reports the failure and lets the test carry on. Within both of these macros, you can use all C++ comparison operators and pass the arguments in any order.

Sections

Another important feature of Catch2 is the way to organize tests in cases and sections (while the class-based fixture mechanism is also supported ). Take a look at this example from the documentation:

TEST_CASE( 'vectors can be sized and resized', '[vector]' ) { // initialization block executed for each section std::vector<int> v( 5 ); REQUIRE( v.size() 5 ); REQUIRE( v.capacity() >= 5 ); // end of initialization block SECTION( 'resizing bigger changes size and capacity' ) { v.resize( 10 ); REQUIRE( v.size() 10 ); REQUIRE( v.capacity() >= 10 ); } SECTION( 'resizing smaller changes size but not capacity' ) { v.resize( 0 ); REQUIRE( v.size() 0 ); REQUIRE( v.capacity() >= 5 ); } }

In the above snippet, TEST_CASE is executed from the start for each SECTION. Two REQUIRE statements at the top of the TEST_CASE enforce that size is 5 and capacity is at least 5 at the entry of each section. This way, shared objects are allocated on stack and there is no need to create a fixture class for them. On each run through a TEST_CASE, Catch2 executes one section and skips the others. Next time, it executes the second section, and so on.

Sections can be nested to create a sequence of checking operations. Each leaf section (a section with no nested sections inside) is executed once. When a parent section fails, it prevents child sections from running. For example:

SECTION( 'reserving bigger changes capacity but not size' ) { v.reserve( 10 ); REQUIRE( v.size() 5 ); REQUIRE( v.capacity() >= 10 ); // verify that attempting to reserve a smaller capacity changes nothing SECTION( 'reserving smaller again does not change capacity' ) { v.reserve( 7 ); REQUIRE( v.capacity() >= 10 ); } }

Catch2 also supports the alternative BDD-style syntax for test cases and sections.

Template tests

Catch2 supports type-parametrized test cases in the form of the following macros:

  • TEMPLATE_TEST_CASE( test name , tags, type1, type2, ..., typen )
  • TEMPLATE_PRODUCT_TEST_CASE( test name , tags, (template-type1, template-type2, ..., template-typen), (template-arg1, template-arg2, ..., template-argm) )
  • TEMPLATE_LIST_TEST_CASE( test name, tags, type list )

These macros behave in the same way as regular TEST_CASE, but are run for every type or type combination. See Type-parametrized test cases for details.

In addition to type-parametrized test cases, Catch2 also provides TEMPLATE_TEST_CASE_SIG and TEMPLATE_PRODUCT_TEST_CASE_SIG for creating signature-based parametrized test cases, which have similar syntax with the additional signature argument:

TEMPLATE_TEST_CASE_SIG( test name , tags, signature, type1, type2, ..., typen )

For more information, refer to Signature-based parametrized test cases.

Setting up

To start using Catch2, download the catch.hpp header using the link from the documentation and copy it into your project tree. See an example in the sample project below (switch to the Catch2 tab).

Doctest

Similarly to Catch2, Doctest is a single-header framework with self-registering tests. As stated in its documentation, Doctest was designed after Catch and shares some parts of the Catch's code - see How is doctest different from Catch.

Doctest doesn't support mocking but you can integrate it with third-party mocking libraries such as trompeloeil, googlemock, or FakeIt.

Sample test

A simple test written with Doctest looks like this:

// provides main(); this line is required in only one .cpp file #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include 'doctest.h' //function to be tested int fact(int n) { return n <= 1 ? n : fact(n - 1) * n; } TEST_CASE('testing the factorial function') { CHECK(fact(0) 1); // should fail CHECK(fact(1) 1); CHECK(fact(2) 2); CHECK(fact(3) 6); CHECK(fact(10) 3628800); }

In the example above, testing the factorial function is a free-form test name, which doesn't have to be unique. CHECK is one of the Doctest's assertion macros.

Test cases, subtests, and suites

Doctest provides the mechanism of subcases for creating nested tests with shared common setup and teardown (however, class-based fixtures are also supported ).

TEST_CASE('vectors can be sized and resized') { std::vector<int> v(5); REQUIRE(v.size() 5); REQUIRE(v.capacity() >= 5); SUBCASE('adding to the vector increases it's size') { v.push_back(1); CHECK(v.size() 6); CHECK(v.capacity() >= 6); } SUBCASE('reserving increases just the capacity') { v.reserve(6); CHECK(v.size() 5); CHECK(v.capacity() >= 6); } }

In the code above, TEST_CASE() is executed from the start for each SUBCASE(). Two REQUIRE statements guarantee that size is 5 and capacity is at least 5 at the entry of each subcase. If one of the CHECK() -s fails, this means the test has failed, but the execution continues. On each run of a TEST_CASE(), Doctest executes one subcase and skips the others. Next time, the second one is executed, and so on.

Similarly to Catch's sections, subcases can be nested to create sequences of checking operations. Each leaf subcase (a subcase with no nested subcases inside) is executed once. When a parent subcase fails, it prevents child subcases from running.

You can group test cases into suites using the TEST_SUITE() or TEST_SUITE_BEGIN()/ TEST_SUITE_END() macros:

TEST_CASE(') {} // not part of any test suite TEST_SUITE('math') { TEST_CASE(') {} // part of the math test suite TEST_CASE(') {} // part of the math test suite } TEST_SUITE_BEGIN('utils'); TEST_CASE(') {} // part of the utils test suite TEST_SUITE_END(); TEST_CASE(') {} // not part of any test suite

Doctest also supports the BDD-style syntax.

Setting up

To start using Doctest, download the latest version of doctest.h and copy it into your project tree. See an example in the sample project below (switch to the Doctest tab).

Unit testing in CLion

CLion's integration of Google Test, Boost.Test, Catch2, and Doctest includes full code insight for framework libraries, dedicated run/debug configurations, gutter icons to run or debug tests/suites/fixtures and check their status, a specialized test runner, and also code generation for tests and fixture classes (available for Google Tests).

For CMake projects, CLion also supports CTest.

Setting up a testing framework for your project

In this chapter, we will discuss how to add the Google Test, Boost.Test, Catch2, and Doctest framework to a project in CLion and how to write a simple set of tests.

As an example, we will use the DateConverter project that you can clone from github repo. This program calculates the absolute value of a date given in the Gregorian calendar format and converts it into a Julian calendar date. Initially, the project doesn't include any tests - we will add them step by step. To see the difference between the frameworks, we will use all four to perform the same tests. You can find the final version of the project in the DateConverter_withTests repository. Here is how the project structure will be transformed:

For each framework, we will do the following:

  1. Add the framework to the DateConverter project.

  2. Create two test files, AbsoluteDateTest.cpp and ConverterTests.cpp. These files will be named similarly for each framework, and they will contain test code written using the syntax of a particular framework.

Now let's open the cloned DateConverter project and follow the instructions given in the tabs below:

Include the Google Test framework

  1. Create a folder for Google Tests under the DateConverter project root. Inside it, create another folder for the framework's files. In our example, it's Google_tests and Google_tests/lib folders respectfully.

  2. Download Google Test from the official repository. Extract the contents of the googletest-master folder into Google_tests/lib.

  3. Add a CMakeLists.txt file to the Google_tests folder (right-click it in the project tree and select New CMakeLists.txt ). Add the following lines:

    project(Google_tests) add_subdirectory(lib) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
  4. In the rootCMakeLists.txt script, add the add_subdirectory(Google_tests) line at the end and reload the project.

Add Google tests

  1. Click Google_tests folder in the project tree and select New C/C++ Source File, call it AbsoluteDateTest.cpp.

    CLion prompts to add this file to an existing target. We don't need to do that, since we are going to create a new target for this file on the next step.

    Repeat this step for ConverterTests.cpp.

  2. With two source files added, we can create a test target for them and link it with the DateConverter_lib library.

    Add the following lines to Google_tests/CMakeLists.txt:

    # adding the Google_Tests_run target add_executable(Google_Tests_run ConverterTests.cpp AbsoluteDateTest.cpp) # linking Google_Tests_run with DateConverter_lib which will be tested target_link_libraries(Google_Tests_run DateConverter_lib) target_link_libraries(Google_Tests_run gtest gtest_main)
  3. Copy the Google Test version of our checks from AbsoluteDateTest.cpp and ConverterTests.cpp to your AbsoluteDateTest.cpp and ConverterTests.cpp files.

    Now the tests are ready to run. For example, let's click in the left gutter next to the DateConverterFixture declaration in ConverterTests.cpp and choose Run.... We will get the following results:

Include the Boost.Test framework

  1. Install and build Boost Testing Framework following these instructions (further in the tests we will use the shared library usage variant to link the framework).

  2. Create a folder for Boost tests under the DateConverter project root. In our example, it's called Boost_tests.

  3. Add a CMakeLists.txt file to the Boost_tests folder (right-click it in the project tree and select New CMakeLists.txt ). Add the following lines:

    set (Boost_USE_STATIC_LIBS OFF) find_package (Boost REQUIRED COMPONENTS unit_test_framework) include_directories (${Boost_INCLUDE_DIRS})
  4. In the rootCMakeLists.txt script, add the add_subdirectory(Boost_tests) line at the end and reload the project.

Add Boost tests

  1. Click Boost_tests in the project tree and select New C/C++ Source File, call it AbsoluteDateTest.cpp.

    CLion will prompt to add this file to an existing target. We don't need to do that, since we are going to create a new target for this file on the next step.

    Repeat this step for ConverterTests.cpp.

  2. With two source files added, we can create a test target for them and link it with the DateConverter_lib library. Add the following lines to Boost_tests/CMakeLists.txt:

    add_executable (Boost_Tests_run ConverterTests.cpp AbsoluteDateTest.cpp) target_link_libraries (Boost_Tests_run ${Boost_LIBRARIES}) target_link_libraries (Boost_Tests_run DateConverter_lib)

    Reload the project.

  3. Copy the Boost.Test version of our checks from AbsoluteDateTest.cpp and ConverterTests.cpp to the corresponding source files in your project.

    Now the tests are ready to run. For example, let's click in the left gutter next to BOOST_AUTO_TEST_SUITE(AbsoluteDateCheckSuite) in AbsoluteDateTest.cpp and choose Run.... We will get the following results:

Include the Catch2 framework

  1. Create a folder for Catch2 tests under the DateConverter project root. In our example, it's called Catch_tests.

  2. Download the catch.hpp header using the link from the documentation and place it in the Catch_tests folder.

Add Catch2 tests

  1. Click Catch_tests in the project tree and select New C/C++ Source File, call it AbsoluteDateTest.cpp.

    CLion will prompt to add this file to an existing target. We don't need to do that, since we are going to create a new target for this file on the next step.

    Repeat this step for ConverterTests.cpp.

  2. Add a CMakeLists.txt file to the Catch_tests folder (right-click the folder in the project tree and select New CMakeLists.txt ). Add the following lines:

    add_executable(Catch_tests_run ConverterTests.cpp AbsoluteDateTest.cpp) target_link_libraries(Catch_tests_run DateConverter_lib)
  3. In the rootCMakeLists.txt, add add_subdirectory(Catch_tests) in the end and reload the project.

  4. Copy the Catch2 version of our checks from AbsoluteDateTest.cpp and ConverterTests.cpp to the corresponding source files in your project.

    Now the tests are ready to run. For example, lets' click in the left gutter next to TEST_CASE( 'Check various dates', '[DateConverterTests]' ) in ConverterTests.cpp and choose Run.... We will get the following results:

Include the Doctest framework

  1. Create a folder for Doctest tests under the DateConverter project root. In our example, it's called Doctest_tests.

  2. Download the doctest.h header and place it in the Doctest_tests folder.

Add Doctest tests

  1. Click Doctest_tests in the project tree and select New C/C++ Source File, call it AbsoluteDateTest.cpp.

    CLion will prompt to add this file to an existing target. We don't need to do that, since we are going to create a new target for this file on the next step.

    Repeat this step for ConverterTests.cpp.

  2. Add a CMakeLists.txt file to the Doctest_tests folder (right-click the folder in the project tree and select New CMakeLists.txt ). Add the following lines:

    add_executable(Doctest_tests_run ConverterTests.cpp AbsoluteDateTest.cpp) target_link_libraries(Doctest_tests_run DateConverter_lib)
  3. In the rootCMakeLists.txt, add add_subdirectory(Doctest_tests) in the end and reload the project.

  4. Copy the Doctest version of our checks from AbsoluteDateTest.cpp and ConverterTests.cpp to the corresponding source files in your project.

    Now the tests are ready to run. For example, lets' click in the left gutter next to TEST_CASE('Check various dates') in ConverterTests.cpp and choose Run.... We will get the following results:

Run/Debug configurations for tests

Test frameworks provide the main() entry for test programs, so it is possible to run them as regular applications in CLion. However, we recommend using the dedicated run/debug configurations for Google Test, Boost.Test, Catch2, and Doctest. These configurations include test-related settings and let you benefit from the built-in test runner (which is unavailable if you run the tests as regular applications).

Create a run/debug configuration for tests

  • Go to Run Edit Configurations, click and select one of the framework-specific templates:

CLion atomatically creates Google Test configurations for Cmake targets linked with gtest or gmock, as well as Doctest configurations for the detected Doctest targets.

Set up your configuration

  • Depending on the framework, specify test pattern, suite, or tags (for Catch2). Auto-completion is available in the fields to help you quickly fill them up:

  • You can use wildcards when specifying test patterns. For example, set the following pattern to run only the PlusOneDiff and PlusFour_Leap tests from the sample project:

  • In other fields of the configuration settings, you can set environment variables or command line options. For example, in the Program arguments field you can set -s for Catch2 tests to force passing tests to show the full output, or --gtest_repeat to run a Google test multiple times:

    The output will look as follows:

    Repeating all tests (iteration 1) ... Repeating all tests (iteration 2) ... Repeating all tests (iteration 3) ...

Instead of editing each configuration separately, you can modify the template itself: settings will be used by default in new configurations based on that template.

Gutter icons for tests

In CLion, there are several ways to start a run/debug session for tests, one of which is using special gutter icons. These icons help quickly run or debug a single test or a whole suite/fixture:

Gutter icons also show test results (when already available): success or failure .

When you run a test/suite/fixture using gutter icons, CLion creates temporary Run/Debug configurations of the corresponding type. You can see these configurations greyed out in the list. To save a temporary configuration, select it in the Edit Configurations dialog and press :

Test runner

When you run a test configuration, the results (and the process) are shown in the test runner window that includes:

  • progress bar with the percentage of tests executed so far,

  • tree view of all the running tests with their status and duration,

  • tests' output stream,

  • toolbar with the options to rerun failed tests, export or open previous results saved automatically , sort the tests alphabetically to easily find a particular test, or sort them by duration to understand which test ran longer than others.

For example, here is how the test runner window looks like if we intentionally break some of the Catch2 tests in the sample project:

Code generation for Google tests

If you are using Google Test framework, CLion's Generate menu can help you save time on writing test code. In a test file where you have gtest included, press Alt+Insert to see the code generation options.

When called from a fixture, the menu additionally includes SetUp Method and TearDown Method:

For fixture tests, code generation converts TEST() macros into the appropriate TEST_F(), TEST_P(), TYPED_TEST(), or TYPED_TEST_P() (see Typed Tests ).

Other features

Quick Documentation for test macros

Clion Boosts

To help you explore the macros provided by testing frameworks, Quick Documentation pop-up shows the final macro replacement and formats it properly. It also highlights the strings and keywords used in the result substitution:

Clion Add External Library

Show Test List

To reduce the time of initial indexing, CLion uses lazy test detection. It means that tests are excluded from indexing until you open some of the test files or run/debug test configurations. To check which tests are currently detected for your project, call Show Test List from Help Find Action. Note that calling this action doesn't trigger indexing.