Skip to content

Commit 1128686

Browse files
authored
Merge pull request #312 from jonathon-bell/doctest
Basic doctest integration
2 parents a5724ea + e5321d0 commit 1128686

4 files changed

Lines changed: 181 additions & 1 deletion

File tree

doc/doctest.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Doctest integration
2+
3+
rapidcheck comes with a basic integration for the [doctest](https://github.com/doctest/doctest) library.
4+
5+
## Usage
6+
7+
This support is available through the `extras/doctest` module. You can either
8+
add the `extras/doctest/include` directory directly to your include path:
9+
10+
```cmake
11+
add_subdirectory(rapidcheck)
12+
set include_directories(rapidcheck/extras/doctest/include)
13+
add_executable(MyTest main.cpp)
14+
```
15+
16+
...or else link against the `rapidcheck_doctest` cmake target:
17+
18+
```cmake
19+
add_subdirectory(rapidcheck)
20+
add_executable(MyTest main.cpp)
21+
target_link_libraries(MyTest rapidcheck_doctest)
22+
```
23+
24+
Either way, you can then write:
25+
26+
```cpp
27+
#include <doctest/doctest.h>
28+
#include "rapidcheck.h"
29+
#include "rapidcheck/doctest.h'
30+
```
31+
32+
## Reference
33+
34+
### `rc::doctest::check("My test description", []{return true;}, /*verbose=*/true)`
35+
36+
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.
37+
38+
The third parameter is optional and defaults to `false`.
39+
40+
```cpp
41+
TEST_CASE("001: My first test case")
42+
{
43+
rc::doctest::check("integer addition is commutative",
44+
[](int a, int b)
45+
{
46+
return a + b == b + a); // true for success, false for failure
47+
});
48+
49+
// no problem mixing rapidcheck tests with other doctest assertions
50+
SUB_CASE("Normal doctest stuff")
51+
{
52+
REQUIRE(1 == 1);
53+
}
54+
}
55+
```

extras/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Since
1+
# Since
22
option(RC_INSTALL_ALL_EXTRAS "Add all possible integrations without
33
requiring the initialization of all the submodules in ext." OFF)
44

@@ -7,6 +7,11 @@ if (RC_ENABLE_CATCH OR RC_ENABLE_TESTS OR RC_INSTALL_ALL_EXTRAS)
77
add_subdirectory(catch)
88
endif()
99

10+
option(RC_ENABLE_DOCTEST "Build DocTest support" OFF)
11+
if (RC_ENABLE_DOCTEST OR RC_ENABLE_TESTS OR RC_INSTALL_ALL_EXTRAS)
12+
add_subdirectory(doctest)
13+
endif()
14+
1015
option(RC_ENABLE_GMOCK "Build Google Mock integration" OFF)
1116
if (RC_ENABLE_GMOCK OR RC_INSTALL_ALL_EXTRAS)
1217
add_subdirectory(gmock)

extras/doctest/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
add_library(rapidcheck_doctest INTERFACE)
2+
target_link_libraries(rapidcheck_doctest INTERFACE rapidcheck)
3+
target_include_directories(rapidcheck_doctest INTERFACE
4+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
5+
$<INSTALL_INTERFACE:include>
6+
)
7+
8+
# An INTERFACE library does not need to install anything but its headers
9+
# and information on its targets.
10+
install(TARGETS rapidcheck_doctest EXPORT rapidcheckConfig)
11+
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#pragma once
2+
3+
#include <sstream>
4+
#include <source_location>
5+
6+
#include <rapidcheck.h>
7+
8+
namespace rc::doctest {
9+
10+
/**
11+
* Checks the given predicate by applying it to randomly generated arguments.
12+
*
13+
* Quotes the given description string if the predicate can be falsified.
14+
*
15+
* Traces a progress message to 'stdout' if the flag 'v' is true.
16+
*
17+
* Like the function 'rc::check', but integrates with 'doctest' to include its
18+
* result in the statistics that are gathered for a test run.
19+
*
20+
* For example:
21+
*
22+
* TEST_CASE("addition is commutative")
23+
* {
24+
* wol::test::check("a+b == b+a", [](int a, int b) { return a+b == b+a; });
25+
* }
26+
*
27+
* @param d A description of the predicate being checked.
28+
* @param t A predicate to check.
29+
* @param v A flag requesting verbose output.
30+
*
31+
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/properties.md
32+
* for more on 'rc::check', on which this function is modeled.
33+
*
34+
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/catch.md
35+
* for more on the integration of 'rapidcheck' and 'catch', on which
36+
* this implementation is based.
37+
*/
38+
template <class testable>
39+
void check(const char* d,
40+
testable&& t,
41+
bool v = false,
42+
std::source_location s = std::source_location::current())
43+
{
44+
using namespace rc::detail;
45+
using namespace doctest::detail;
46+
47+
DOCTEST_SUBCASE(d)
48+
{
49+
auto r = checkTestable(std::forward<testable>(t));
50+
51+
if (r.template is<SuccessResult>())
52+
{
53+
if (!r.template get<SuccessResult>().distribution.empty() || v)
54+
{
55+
std::cout << "- " << d << std::endl;
56+
printResultMessage(r, std::cout);
57+
std::cout << std::endl;
58+
}
59+
60+
REQUIRE(true);
61+
}
62+
else
63+
{
64+
std::ostringstream o;
65+
printResultMessage(r, o << '\n');
66+
DOCTEST_INFO(o.str());
67+
ResultBuilder b(doctest::assertType::DT_CHECK, s.file_name(), s.line(), s.function_name());
68+
DOCTEST_ASSERT_LOG_REACT_RETURN(b);
69+
}
70+
}
71+
}
72+
73+
/**
74+
* Checks the given predicate by applying it to randomly generated arguments.
75+
*
76+
* Quotes the given description string if the predicate can be falsified.
77+
*
78+
* Traces a progress message to 'stdout' if the flag 'v' is true.
79+
*
80+
* Like the function 'rc::check', but integrates with 'doctest' to include its
81+
* result in the statitics that are gathered for a test run.
82+
*
83+
* For example:
84+
*
85+
* TEST_CASE("addition is commutative")
86+
* {
87+
* wol::test::check("a+b == b+a", [](int a, int b) { return a+b == b+a; });
88+
* }
89+
*
90+
* @param t A predicate to check.
91+
* @param v A flag requesting verbose output.
92+
*
93+
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/properties.md
94+
* for more on 'rc::check', on which this function is modeled.
95+
*
96+
* @see https://github.com/emil-e/rapidcheck/blob/master/doc/catch.md
97+
* for more on the integration of 'rapidcheck' and 'catch', on which
98+
* this implementation is based.
99+
*/
100+
template <class testable>
101+
inline
102+
void check(testable&& t,
103+
bool v = false,
104+
std::source_location s = std::source_location::current())
105+
{
106+
check("", t, v ,s);
107+
}
108+
109+
} // namespace rc::doctest

0 commit comments

Comments
 (0)