Files
cmake-examples/05-unit-testing/catch-vendored
2017-09-24 17:16:29 +01:00
..
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00
2017-09-24 17:16:29 +01:00

= Catch Unit Testing Framework
:toc:
:toc-placement!:

toc::[]


# Introduction

Using link:https://cmake.org/Wiki/CMake/Testing_With_CTest[CTest] you can generate
a `make test` target to run automated unit-tests. This example shows how to
find the https://github.com/philsquared/Catch[catch framework],
create tests and run them.

The files in this tutorial are below:

```
$ tree
.
├── 3rd_party
│   └── catch
│       ├── catch
│       │   └── catch.hpp
│       └── CMakeLists.txt
├── CMakeLists.txt
├── Reverse.h
├── Reverse.cpp
├── Palindrome.h
├── Palindrome.cpp
├── unit_tests.cpp
```

  * link:3rd_party/catch/catch/catch.hpp[] - Vendored copy of the https://github.com/philsquared/Catch/releases/download/v2.0.0-develop.4/catch.hpp[single header version of catch]
  * link:3rd_party/catch/CMakeLists.txt[] - CMake file to make Catch available as a library
  * link:CMakeLists.txt[] - Contains the CMake commands you wish to run
  * link:Reverse.h[] / link:Reverse.cpp[.cpp] - Class to reverse a string
  * link:Palindrome.h[] / link:Palindrome.cpp[.cpp] - Class to test if a string is a palindrome
  * link:unit_test.cpp[] - Unit Tests using catch unit test framework

# Requirements

A C++11 compatible compiler

# Concepts

## Vendoring catch

As catch is available as a single header file I have downloaded it and checked it into my repository. This mean
that I don't have any external dependencies when building my project. This is one of the 
https://github.com/philsquared/Catch/blob/master/docs/build-systems.md#cmake[recommended] ways to use Catch.

## Catch Interface Library

The CMakeLists in the catch directory creates an `INTERFACE` library and `ALIAS` library to make it
easy to add Catch to your executable.

[source,cmake]
----
add_library(Catch INTERFACE)
add_library(Catch::Test ALIAS Catch)
target_include_directories(Catch INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
----

## Build with C++11

As Catch requires C++11 to build, I have used the `CMAKE_CXX_STANDARD` to set C++11. As described
in earlier examples you can use other methods to set this standard.

## Enabling testing

To enable testing you must include the following line in your top level CMakeLists.txt

[source,cmake]
----
enable_testing()
----

This will enable testing for the current folder and all folders below it.

## Adding a testing executable

The requirement for this step will depend on your unit-test framework. In the example
of catch, you can create binary(s) which includes all the unit tests that you want to run.

[source,cmake]
----
add_executable(unit_tests unit_tests.cpp)

target_link_libraries(unit_tests
    example_unit_test
    Catch::Test
)
----

In the above code, a unit test binary is added, which links against the catch `ALIAS` target created earlier.

## Add A test

To add a test you call the link:https://cmake.org/cmake/help/v3.0/command/add_test.html[`add_test()`] function.
This will create a named test which will run the supplied command.

[source,cmake]
----
add_test(test_all unit_tests)
----

In this example, we create a test called `test_all` which will run the executable
created by the `unit_tests` executable created from the call to `add_executable`

# Building the Example

[source,bash]
----
$ mkdir build

$ cd build/

$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- 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: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /data/code/cmake-examples/05-unit-testing/catch-vendored/build


$ make
Scanning dependencies of target example_unit_test
[ 20%] Building CXX object CMakeFiles/example_unit_test.dir/Reverse.cpp.o
[ 40%] Building CXX object CMakeFiles/example_unit_test.dir/Palindrome.cpp.o
[ 60%] Linking CXX static library libexample_unit_test.a
[ 60%] Built target example_unit_test
Scanning dependencies of target unit_tests
[ 80%] Building CXX object CMakeFiles/unit_tests.dir/unit_tests.cpp.o
[100%] Linking CXX executable unit_tests
[100%] Built target unit_tests


$ make test
Running tests...
Test project /data/code/cmake-examples/05-unit-testing/catch-vendored/build
    Start 1: test_all
1/1 Test #1: test_all .........................   Passed    0.00 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.00 sec
----

If the code is changed and it causes the unit tests to produce an error.
Then when running the tests you will see the following output.

[source,bash]
----
Running tests...
Test project /data/code/cmake-examples/05-unit-testing/catch-vendored/build
    Start 1: test_all
1/1 Test #1: test_all .........................***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 - test_all (Failed)
Errors while running CTest
Makefile:61: recipe for target 'test' failed
make: *** [test] Error 8
----