Skip to content

Commit

Permalink
Merge pull request #312 from jonathon-bell/doctest
Browse files Browse the repository at this point in the history
Basic doctest integration
  • Loading branch information
emil-e authored Aug 15, 2023
2 parents a5724ea + e5321d0 commit 1128686
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 1 deletion.
55 changes: 55 additions & 0 deletions doc/doctest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Doctest integration

rapidcheck comes with a basic integration for the [doctest](https://github.com/doctest/doctest) library.

## Usage

This support is available through the `extras/doctest` module. You can either
add the `extras/doctest/include` directory directly to your include path:

```cmake
add_subdirectory(rapidcheck)
set include_directories(rapidcheck/extras/doctest/include)
add_executable(MyTest main.cpp)
```

...or else link against the `rapidcheck_doctest` cmake target:

```cmake
add_subdirectory(rapidcheck)
add_executable(MyTest main.cpp)
target_link_libraries(MyTest rapidcheck_doctest)
```

Either way, you can then write:

```cpp
#include <doctest/doctest.h>
#include "rapidcheck.h"
#include "rapidcheck/doctest.h'
```
## Reference
### `rc::doctest::check("My test description", []{return true;}, /*verbose=*/true)`
The `rc::doctest::check` function is a drop-in replacement for `rc::check` that reports its success or failure to the `doctest` test runner for inclusion in the statistics gathered for a test run.
The third parameter is optional and defaults to `false`.
```cpp
TEST_CASE("001: My first test case")
{
rc::doctest::check("integer addition is commutative",
[](int a, int b)
{
return a + b == b + a); // true for success, false for failure
});
// no problem mixing rapidcheck tests with other doctest assertions
SUB_CASE("Normal doctest stuff")
{
REQUIRE(1 == 1);
}
}
```
7 changes: 6 additions & 1 deletion extras/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Since
# Since
option(RC_INSTALL_ALL_EXTRAS "Add all possible integrations without
requiring the initialization of all the submodules in ext." OFF)

Expand All @@ -7,6 +7,11 @@ if (RC_ENABLE_CATCH OR RC_ENABLE_TESTS OR RC_INSTALL_ALL_EXTRAS)
add_subdirectory(catch)
endif()

option(RC_ENABLE_DOCTEST "Build DocTest support" OFF)
if (RC_ENABLE_DOCTEST OR RC_ENABLE_TESTS OR RC_INSTALL_ALL_EXTRAS)
add_subdirectory(doctest)
endif()

option(RC_ENABLE_GMOCK "Build Google Mock integration" OFF)
if (RC_ENABLE_GMOCK OR RC_INSTALL_ALL_EXTRAS)
add_subdirectory(gmock)
Expand Down
11 changes: 11 additions & 0 deletions extras/doctest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_library(rapidcheck_doctest INTERFACE)
target_link_libraries(rapidcheck_doctest INTERFACE rapidcheck)
target_include_directories(rapidcheck_doctest INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

# An INTERFACE library does not need to install anything but its headers
# and information on its targets.
install(TARGETS rapidcheck_doctest EXPORT rapidcheckConfig)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
109 changes: 109 additions & 0 deletions extras/doctest/include/rapidcheck/doctest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#pragma once

#include <sstream>
#include <source_location>

#include <rapidcheck.h>

namespace rc::doctest {

/**
* Checks the given predicate by applying it to randomly generated arguments.
*
* Quotes the given description string if the predicate can be falsified.
*
* Traces a progress message to 'stdout' if the flag 'v' is true.
*
* Like the function 'rc::check', but integrates with 'doctest' to include its
* result in the statistics that are gathered for a test run.
*
* For example:
*
* TEST_CASE("addition is commutative")
* {
* wol::test::check("a+b == b+a", [](int a, int b) { return a+b == b+a; });
* }
*
* @param d A description of the predicate being checked.
* @param t A predicate to check.
* @param v A flag requesting verbose output.
*
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/properties.md
* for more on 'rc::check', on which this function is modeled.
*
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/catch.md
* for more on the integration of 'rapidcheck' and 'catch', on which
* this implementation is based.
*/
template <class testable>
void check(const char* d,
testable&& t,
bool v = false,
std::source_location s = std::source_location::current())
{
using namespace rc::detail;
using namespace doctest::detail;

DOCTEST_SUBCASE(d)
{
auto r = checkTestable(std::forward<testable>(t));

if (r.template is<SuccessResult>())
{
if (!r.template get<SuccessResult>().distribution.empty() || v)
{
std::cout << "- " << d << std::endl;
printResultMessage(r, std::cout);
std::cout << std::endl;
}

REQUIRE(true);
}
else
{
std::ostringstream o;
printResultMessage(r, o << '\n');
DOCTEST_INFO(o.str());
ResultBuilder b(doctest::assertType::DT_CHECK, s.file_name(), s.line(), s.function_name());
DOCTEST_ASSERT_LOG_REACT_RETURN(b);
}
}
}

/**
* Checks the given predicate by applying it to randomly generated arguments.
*
* Quotes the given description string if the predicate can be falsified.
*
* Traces a progress message to 'stdout' if the flag 'v' is true.
*
* Like the function 'rc::check', but integrates with 'doctest' to include its
* result in the statitics that are gathered for a test run.
*
* For example:
*
* TEST_CASE("addition is commutative")
* {
* wol::test::check("a+b == b+a", [](int a, int b) { return a+b == b+a; });
* }
*
* @param t A predicate to check.
* @param v A flag requesting verbose output.
*
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/properties.md
* for more on 'rc::check', on which this function is modeled.
*
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/catch.md
* for more on the integration of 'rapidcheck' and 'catch', on which
* this implementation is based.
*/
template <class testable>
inline
void check(testable&& t,
bool v = false,
std::source_location s = std::source_location::current())
{
check("", t, v ,s);
}

} // namespace rc::doctest

0 comments on commit 1128686

Please sign in to comment.